// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2025 Kybernetik //
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
namespace Animancer.Editor
{
/// [Editor-Only]
/// A utility for automatically swapping materials based on supported shaders.
///
///
/// This system is used to allow materials to be used in any render pipeline.
///
/// https://kybernetik.com.au/animancer/api/Animancer.Editor/MaterialVariantGroup
//[CreateAssetMenu(
// menuName = Strings.MenuPrefix + "Material Variant Group",
// order = Strings.AssetMenuOrder + 5)]
[AnimancerHelpUrl(typeof(MaterialVariantGroup))]
public class MaterialVariantGroup : ScriptableObject
{
/************************************************************************************************************************/
[SerializeField]
private Material _Material;
/// The target material.
public ref Material Material
=> ref _Material;
[SerializeField]
private Material[] _Variants;
/// The variants to try applying to the target material.
public ref Material[] Variants
=> ref _Variants;
/************************************************************************************************************************/
/// Applies the first variant that successfully loaded its shader.
protected virtual void OnEnable()
{
if (_Material == null ||
_Variants.IsNullOrEmpty())
return;
foreach (var variant in _Variants)
{
if (variant == null ||
variant.shader == null ||
!variant.shader.isSupported)
continue;
if (_Material.shader != variant.shader)
{
_Material.shader = variant.shader;
_Material.CopyPropertiesFromMaterial(variant);
}
return;
}
}
/************************************************************************************************************************/
/// [Editor-Only]
/// Loads all assets of this type to ensure their is called.
///
private class Initializer : AssetPostprocessor
{
/************************************************************************************************************************/
/// Loads all assets of this type to ensure their is called.
private static void OnPostprocessAllAssets(
string[] importedAssets,
string[] deletedAssets,
string[] movedAssets,
string[] movedFromAssetPaths,
bool didDomainReload)
{
if (!didDomainReload)
return;
var filter = $"t:{nameof(MaterialVariantGroup)}";
var guids = AssetDatabase.FindAssets(filter);
if (guids.Length == 0)
return;
for (int i = 0; i < guids.Length; i++)
{
var path = AssetDatabase.GUIDToAssetPath(guids[i]);
AssetDatabase.LoadAssetAtPath(path);
}
}
/************************************************************************************************************************/
}
/************************************************************************************************************************/
}
}
#endif