This commit is contained in:
2024-09-20 20:30:10 +02:00
commit 4fabf1a6fd
29169 changed files with 1706941 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
using System;
namespace UnityEditor.Rendering
{
/// <summary>
/// Set of utilities for Material reimporting.
/// </summary>
public static class AssetReimportUtils
{
/// <summary>
/// Re-imports a given type of asset, and sends an analytic with the elapsed time
/// </summary>
/// <param name="duration">The elapsed time</param>
/// <param name="numberOfAssetsReimported">The number of assets that have been re-imported</param>
/// <param name="importNeedDelegate">A delegate if you want to skip some asset to be re-imported</param>
/// <typeparam name="TAsset">The asset type that will be re-imported</typeparam>
public static void ReimportAll<TAsset>(out double duration, out uint numberOfAssetsReimported, Func<string, bool> importNeedDelegate = null)
{
numberOfAssetsReimported = 0;
duration = 0.0;
using (TimedScope.FromRef(ref duration))
{
string[] distinctGuids = AssetDatabase
.FindAssets($"t:{typeof(TAsset).Name}", null);
try
{
AssetDatabase.StartAssetEditing();
for (int i = 0, total = distinctGuids.Length; i < total; ++i)
{
var path = AssetDatabase.GUIDToAssetPath(distinctGuids[i]);
EditorUtility.DisplayProgressBar($"{typeof(TAsset).Name} Upgrader re-import", $"({i} of {total}) {path}", (float)i / (float)total);
if (importNeedDelegate?.Invoke(path) ?? true)
{
AssetDatabase.ImportAsset(path);
numberOfAssetsReimported++;
}
}
}
finally
{
// Ensure the AssetDatabase knows we're finished editing
AssetDatabase.StopAssetEditing();
}
}
EditorUtility.ClearProgressBar();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 601dae3a21ff49bab849c25eb27709e1
timeCreated: 1666002147

View File

@@ -0,0 +1,286 @@
using UnityEngine;
namespace UnityEditor.Rendering
{
/// <summary>
/// Set of extensions to allow storing, getting and setting the expandable states of a <see cref="MaterialEditor"/> areas
/// </summary>
public static partial class MaterialEditorExtension
{
const string k_KeyPrefix = "CoreRP:Material:UI_State:";
/// <summary>
/// Obtains if an area is expanded in a <see cref="MaterialEditor"/>
/// </summary>
/// <param name="editor"><see cref="MaterialEditor"/></param>
/// <param name="mask">The mask identifying the area to check the state</param>
/// <param name="defaultExpandedState">Default value if is key is not present</param>
/// <returns>true if the area is expanded</returns>
internal static bool IsAreaExpanded(this MaterialEditor editor, uint mask, uint defaultExpandedState = uint.MaxValue)
{
string key = editor.GetEditorPrefsKey();
if (EditorPrefs.HasKey(key))
{
uint state = (uint)EditorPrefs.GetInt(key);
return (state & mask) > 0;
}
EditorPrefs.SetInt(key, (int)defaultExpandedState);
return (defaultExpandedState & mask) > 0;
}
/// <summary>
/// Sets if the area is expanded <see cref="MaterialEditor"/>
/// </summary>
/// <param name="editor"><see cref="MaterialEditor"/></param>
/// <param name="mask">The mask identifying the area to check the state</param>
internal static void SetIsAreaExpanded(this MaterialEditor editor, uint mask, bool value)
{
string key = editor.GetEditorPrefsKey();
uint state = (uint)EditorPrefs.GetInt(key);
if (value)
{
state |= mask;
}
else
{
mask = ~mask;
state &= mask;
}
EditorPrefs.SetInt(key, (int)state);
}
static string GetEditorPrefsKey(this MaterialEditor editor)
{
return k_KeyPrefix + (editor.target as Material).shader.name;
}
}
/// <summary>
/// Set of extensions to handle more shader property drawer
/// </summary>
public static partial class MaterialEditorExtension
{
static Rect GetRect(MaterialProperty prop)
{
return EditorGUILayout.GetControlRect(true, MaterialEditor.GetDefaultPropertyHeight(prop), EditorStyles.layerMaskField);
}
/// <summary>
/// Draw an integer property field for a float shader property.
/// </summary>
/// <param name="editor"><see cref="MaterialEditor"/></param>
/// <param name="prop">The MaterialProperty to make a field for</param>
/// <param name="label">Label for the property</param>
/// <param name="transform">Optional function to apply on the new value</param>
public static void IntShaderProperty(this MaterialEditor editor, MaterialProperty prop, GUIContent label, System.Func<int, int> transform = null)
{
MaterialEditor.BeginProperty(prop);
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = prop.hasMixedValue;
int newValue = EditorGUI.IntField(GetRect(prop), label, (int)prop.floatValue);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck())
{
if (transform != null)
newValue = transform(newValue);
prop.floatValue = newValue;
}
MaterialEditor.EndProperty();
}
/// <summary>
/// Draw an integer slider for a range shader property.
/// </summary>
/// <param name="editor"><see cref="MaterialEditor"/></param>
/// <param name="prop">The MaterialProperty to make a field for</param>
/// <param name="label">Label for the property</param>
public static void IntSliderShaderProperty(this MaterialEditor editor, MaterialProperty prop, GUIContent label)
{
var limits = prop.rangeLimits;
editor.IntSliderShaderProperty(prop, (int)limits.x, (int)limits.y, label);
}
/// <summary>
/// Draw an integer slider for a float shader property.
/// </summary>
/// <param name="editor"><see cref="MaterialEditor"/></param>
/// <param name="prop">The MaterialProperty to make a field for</param>
/// <param name="min">The value at the left end of the slider</param>
/// <param name="max">The value at the right end of the slider</param>
/// <param name="label">Label for the property</param>
public static void IntSliderShaderProperty(this MaterialEditor editor, MaterialProperty prop, int min, int max, GUIContent label)
{
MaterialEditor.BeginProperty(prop);
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = prop.hasMixedValue;
int newValue = EditorGUI.IntSlider(GetRect(prop), label, (int)prop.floatValue, min, max);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck())
{
editor.RegisterPropertyChangeUndo(label.text);
prop.floatValue = newValue;
}
MaterialEditor.EndProperty();
}
/// <summary>
/// Draw a property field for a float shader property.
/// </summary>
/// <param name="editor"><see cref="MaterialEditor"/></param>
/// <param name="prop">The MaterialProperty to make a field for</param>
/// <param name="label">Label for the property</param>
/// <param name="min">The minimum value the user can specify</param>
public static void MinFloatShaderProperty(this MaterialEditor editor, MaterialProperty prop, GUIContent label, float min)
{
MaterialEditor.BeginProperty(prop);
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = prop.hasMixedValue;
float newValue = EditorGUI.FloatField(GetRect(prop), label, prop.floatValue);
newValue = Mathf.Max(min, newValue);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck())
prop.floatValue = newValue;
MaterialEditor.EndProperty();
}
/// <summary>
/// Draw an vector3 field for a vector shader property.
/// </summary>
/// <param name="editor"><see cref="MaterialEditor"/></param>
/// <param name="prop">The MaterialProperty to make a field for</param>
/// <param name="label">Label for the property</param>
public static void Vector3ShaderProperty(this MaterialEditor editor, MaterialProperty prop, GUIContent label)
{
MaterialEditor.BeginProperty(prop);
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = prop.hasMixedValue;
var vector = EditorGUILayout.Vector3Field(label, prop.vectorValue);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck())
prop.vectorValue = vector;
MaterialEditor.EndProperty();
}
/// <summary>
/// Draw a popup selection field for a float shader property.
/// </summary>
/// <param name="editor"><see cref="MaterialEditor"/></param>
/// <param name="prop">The MaterialProperty to make a field for</param>
/// <param name="label">Label for the property</param>
/// <param name="displayedOptions">An array with the options shown in the popup</param>
/// <returns>The index of the option that has been selected by the user</returns>
public static int PopupShaderProperty(this MaterialEditor editor, MaterialProperty prop, GUIContent label, string[] displayedOptions)
{
MaterialEditor.BeginProperty(prop);
int val = (int)prop.floatValue;
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = prop.hasMixedValue;
int newValue = EditorGUILayout.Popup(label, val, displayedOptions);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck() && (newValue != val || prop.hasMixedValue))
{
editor.RegisterPropertyChangeUndo(label.text);
prop.floatValue = val = newValue;
}
MaterialEditor.EndProperty();
return val;
}
/// <summary>
/// Draw an integer popup selection field for a float shader property.
/// </summary>
/// <param name="editor"><see cref="MaterialEditor"/></param>
/// <param name="prop">The MaterialProperty to make a field for</param>
/// <param name="label">Label for the property</param>
/// <param name="displayedOptions">An array with the options shown in the popup</param>
/// <param name="optionValues">An array with the values for each option</param>
/// <returns>The value of the option that has been selected by the user</returns>
public static int IntPopupShaderProperty(this MaterialEditor editor, MaterialProperty prop, string label, string[] displayedOptions, int[] optionValues)
{
MaterialEditor.BeginProperty(prop);
int val = (int)prop.floatValue;
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = prop.hasMixedValue;
int newValue = EditorGUILayout.IntPopup(label, val, displayedOptions, optionValues);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck() && (newValue != val || prop.hasMixedValue))
{
editor.RegisterPropertyChangeUndo(label);
prop.floatValue = val = newValue;
}
MaterialEditor.EndProperty();
return val;
}
/// <summary>
/// Draw a special slider to specify a range between a min and a max for two float shader properties.
/// </summary>
/// <param name="editor"><see cref="MaterialEditor"/></param>
/// <param name="min">The MaterialProperty containing the lower value of the range the slider shows</param>
/// <param name="max">The MaterialProperty containing the upper value of the range the slider shows</param>
/// <param name="minLimit">The limit at the left end of the slider</param>
/// <param name="maxLimit">The limit at the right end of the slider</param>
/// <param name="label">Label for the property</param>
public static void MinMaxShaderProperty(this MaterialEditor editor, MaterialProperty min, MaterialProperty max, float minLimit, float maxLimit, GUIContent label)
{
MaterialEditor.BeginProperty(min);
MaterialEditor.BeginProperty(max);
float minValue = min.floatValue;
float maxValue = max.floatValue;
EditorGUI.BeginChangeCheck();
EditorGUILayout.MinMaxSlider(label, ref minValue, ref maxValue, minLimit, maxLimit);
if (EditorGUI.EndChangeCheck())
{
min.floatValue = minValue;
max.floatValue = maxValue;
}
MaterialEditor.EndProperty();
MaterialEditor.EndProperty();
}
/// <summary>
/// Draw a special slider to specify a range between a min and a max for a vector shader property.
/// </summary>
/// <param name="editor"><see cref="MaterialEditor"/></param>
/// <param name="remapProp">The MaterialProperty containing the range the slider shows in the x and y components of its vectorValue</param>
/// <param name="minLimit">The limit at the left end of the slider</param>
/// <param name="maxLimit">The limit at the right end of the slider</param>
/// <param name="label">Label for the property</param>
public static void MinMaxShaderProperty(this MaterialEditor editor, MaterialProperty remapProp, float minLimit, float maxLimit, GUIContent label)
{
MaterialEditor.BeginProperty(remapProp);
Vector2 remap = remapProp.vectorValue;
EditorGUI.BeginChangeCheck();
EditorGUILayout.MinMaxSlider(label, ref remap.x, ref remap.y, minLimit, maxLimit);
if (EditorGUI.EndChangeCheck())
remapProp.vectorValue = remap;
MaterialEditor.EndProperty();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 007ecb3820c25954d90dcb206cd59ed5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,94 @@
using System;
using UnityEngine;
namespace UnityEditor.Rendering
{
/// <summary>
/// Create a toggleable header for material UI, must be used within a scope.
/// <example>Example:
/// <code>
/// void OnGUI()
/// {
/// using (var header = new MaterialHeaderScope(text, ExpandBit, editor))
/// {
/// if (header.expanded)
/// EditorGUILayout.LabelField("Hello World !");
/// }
/// }
/// </code>
/// </example>
/// </summary>
public struct MaterialHeaderScope : IDisposable
{
/// <summary>Indicates whether the header is expanded or not. Is true if the header is expanded, false otherwise.</summary>
public readonly bool expanded;
bool spaceAtEnd;
#if !UNITY_2020_1_OR_NEWER
int oldIndentLevel;
#endif
/// <summary>
/// Creates a material header scope to display the foldout in the material UI.
/// </summary>
/// <param name="title">GUI Content of the header.</param>
/// <param name="bitExpanded">Bit index which specifies the state of the header (whether it is open or collapsed) inside Editor Prefs.</param>
/// <param name="materialEditor">The current material editor.</param>
/// <param name="spaceAtEnd">Set this to true to make the block include space at the bottom of its UI. Set to false to not include any space.</param>
/// <param name="subHeader">Set to true to make this into a sub-header. This affects the style of the header. Set to false to make this use the standard style.</param>
/// <param name="defaultExpandedState">The default state if the header is not present</param>
/// <param name="documentationURL">[optional] Documentation page</param>
public MaterialHeaderScope(GUIContent title, uint bitExpanded, MaterialEditor materialEditor, bool spaceAtEnd = true, bool subHeader = false, uint defaultExpandedState = uint.MaxValue, string documentationURL = "")
{
if (title == null)
throw new ArgumentNullException(nameof(title));
bool beforeExpanded = materialEditor.IsAreaExpanded(bitExpanded, defaultExpandedState);
#if !UNITY_2020_1_OR_NEWER
oldIndentLevel = EditorGUI.indentLevel;
EditorGUI.indentLevel = subHeader ? 1 : 0; //fix for preset in 2019.3 (preset are one more indentation depth in material)
#endif
this.spaceAtEnd = spaceAtEnd;
if (!subHeader)
CoreEditorUtils.DrawSplitter();
GUILayout.BeginVertical();
bool saveChangeState = GUI.changed;
expanded = subHeader
? CoreEditorUtils.DrawSubHeaderFoldout(title, beforeExpanded, isBoxed: false)
: CoreEditorUtils.DrawHeaderFoldout(title, beforeExpanded, documentationURL: documentationURL);
if (expanded ^ beforeExpanded)
{
materialEditor.SetIsAreaExpanded((uint)bitExpanded, expanded);
saveChangeState = true;
}
GUI.changed = saveChangeState;
}
/// <summary>
/// Creates a material header scope to display the foldout in the material UI.
/// </summary>
/// <param name="title">Title of the header.</param>
/// <param name="bitExpanded">Bit index which specifies the state of the header (whether it is open or collapsed) inside Editor Prefs.</param>
/// <param name="materialEditor">The current material editor.</param>
/// <param name="spaceAtEnd">Set this to true to make the block include space at the bottom of its UI. Set to false to not include any space.</param>
/// <param name="subHeader">Set to true to make this into a sub-header. This affects the style of the header. Set to false to make this use the standard style.</param>
public MaterialHeaderScope(string title, uint bitExpanded, MaterialEditor materialEditor, bool spaceAtEnd = true, bool subHeader = false)
: this(EditorGUIUtility.TrTextContent(title, string.Empty), bitExpanded, materialEditor, spaceAtEnd, subHeader)
{
}
/// <summary>Disposes of the material scope header and cleans up any resources it used.</summary>
void IDisposable.Dispose()
{
if (expanded && spaceAtEnd && (Event.current.type == EventType.Repaint || Event.current.type == EventType.Layout))
EditorGUILayout.Space();
#if !UNITY_2020_1_OR_NEWER
EditorGUI.indentLevel = oldIndentLevel;
#endif
GUILayout.EndVertical();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5c6068e6e01454142ba896167109475c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
using System;
using UnityEngine;
namespace UnityEditor.Rendering
{
/// <summary>
/// Item to store information used by <see cref="MaterialHeaderScopeList"></see>/>
/// </summary>
internal struct MaterialHeaderScopeItem
{
/// <summary><see cref="GUIContent"></see> that will be rendered on the <see cref="MaterialHeaderScope"></see></summary>
public GUIContent headerTitle { get; set; }
/// <summary>The bitmask for this scope</summary>
public uint expandable { get; set; }
/// <summary>The action that will draw the controls for this scope</summary>
public Action<Material> drawMaterialScope { get; set; }
/// <summary>The url of the scope</summary>
public string url { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a8ac7c57cfc5071499b0c58d63d71d2b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Rendering
{
/// <summary>
/// Collection to store <see cref="MaterialHeaderScopeItem"></see>
/// </summary>
public class MaterialHeaderScopeList
{
readonly uint m_DefaultExpandedState;
internal readonly List<MaterialHeaderScopeItem> m_Items = new List<MaterialHeaderScopeItem>();
/// <summary>
/// Constructor that initializes it with the default expanded state for the internal scopes
/// </summary>
/// <param name="defaultExpandedState">By default, everything is expanded</param>
public MaterialHeaderScopeList(uint defaultExpandedState = uint.MaxValue)
{
m_DefaultExpandedState = defaultExpandedState;
}
/// <summary>
/// Registers a <see cref="MaterialHeaderScopeItem"/> into the list
/// </summary>
/// <typeparam name="TEnum">A valid <see cref="struct"/> and <see cref="IConvertible"/></typeparam>
/// <param name="title"><see cref="GUIContent"/> The title of the scope</param>
/// <param name="expandable">The mask identifying the scope</param>
/// <param name="action">The action that will be drawn if the scope is expanded</param>
public void RegisterHeaderScope<TEnum>(GUIContent title, TEnum expandable, Action<Material> action)
where TEnum : struct, IConvertible
{
m_Items.Add(new MaterialHeaderScopeItem()
{
headerTitle = title,
expandable = Convert.ToUInt32(expandable),
drawMaterialScope = action,
url = DocumentationUtils.GetHelpURL<TEnum>(expandable)
});
}
/// <summary>
/// Draws all the <see cref="MaterialHeaderScopeItem"/> with its information stored
/// </summary>
/// <param name="materialEditor"><see cref="MaterialEditor"/></param>
/// <param name="material"><see cref="Material"/></param>
public void DrawHeaders(MaterialEditor materialEditor, Material material)
{
if (material == null)
throw new ArgumentNullException(nameof(material));
if (materialEditor == null)
throw new ArgumentNullException(nameof(materialEditor));
foreach (var item in m_Items)
{
using var header = new MaterialHeaderScope(
item.headerTitle,
item.expandable,
materialEditor,
defaultExpandedState: m_DefaultExpandedState,
documentationURL: item.url);
if (!header.expanded)
continue;
item.drawMaterialScope(material);
EditorGUILayout.Space();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b8701f1243e63c04b82c52dbd9fa1e9b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: