using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.Rendering
{
///
/// Material quality flags.
///
[Flags]
[MovedFrom("Utilities")]
public enum MaterialQuality
{
/// Low Material Quality.
Low = 1 << 0,
/// Medium Material Quality.
Medium = 1 << 1,
/// High Material Quality.
High = 1 << 2
}
///
/// Material Quality utility class.
///
[MovedFrom("Utilities")]
public static class MaterialQualityUtilities
{
///
/// Keywords strings for Material Quality levels.
///
public static string[] KeywordNames =
{
"MATERIAL_QUALITY_LOW",
"MATERIAL_QUALITY_MEDIUM",
"MATERIAL_QUALITY_HIGH",
};
///
/// String representation of the MaterialQuality enum.
///
public static string[] EnumNames = Enum.GetNames(typeof(MaterialQuality));
///
/// Keywords for Material Quality levels.
///
public static ShaderKeyword[] Keywords =
{
new ShaderKeyword(KeywordNames[0]),
new ShaderKeyword(KeywordNames[1]),
new ShaderKeyword(KeywordNames[2]),
};
///
/// Returns the highest available quality level in a MaterialQuality bitfield.
///
/// Input MaterialQuality bitfield.
/// The highest available quality level.
public static MaterialQuality GetHighestQuality(this MaterialQuality levels)
{
for (var i = Keywords.Length - 1; i >= 0; --i)
{
var level = (MaterialQuality)(1 << i);
if ((levels & level) != 0)
return level;
}
return 0;
}
///
/// Returns the closest available quality level in a MaterialQuality bitfield.
///
/// Available MaterialQuality bitfield.
/// Input MaterialQuality level.
/// The closest available quality level.
public static MaterialQuality GetClosestQuality(this MaterialQuality availableLevels, MaterialQuality requestedLevel)
{
// Special fallback when there are no available quality levels. Needs to match in the shader stripping code
if (availableLevels == 0)
return MaterialQuality.Low;
// First we want to find the closest available quality level below the requested one.
int requestedLevelIndex = ToFirstIndex(requestedLevel);
MaterialQuality chosenQuality = (MaterialQuality)0;
for (int i = requestedLevelIndex; i >= 0; --i)
{
var level = FromIndex(i);
if ((level & availableLevels) != 0)
{
chosenQuality = level;
break;
}
}
if (chosenQuality != 0)
return chosenQuality;
// If none is found then we fallback to the closest above.
for (var i = requestedLevelIndex + 1; i < Keywords.Length; ++i)
{
var level = FromIndex(i);
var diff = Math.Abs(requestedLevel - level);
if ((level & availableLevels) != 0)
{
chosenQuality = level;
break;
}
}
Debug.Assert(chosenQuality != 0);
return chosenQuality;
}
///
/// Set the global keyword for the provided MaterialQuality.
///
/// MaterialQuality level to set the keyword for.
public static void SetGlobalShaderKeywords(this MaterialQuality level)
{
for (var i = 0; i < KeywordNames.Length; ++i)
{
if ((level & (MaterialQuality)(1 << i)) != 0)
Shader.EnableKeyword(KeywordNames[i]);
else
Shader.DisableKeyword(KeywordNames[i]);
}
}
///
/// Set the global keyword for the provided MaterialQuality.
///
/// MaterialQuality level to set the keyword for.
/// Command Buffer used to setup the keyword.
public static void SetGlobalShaderKeywords(this MaterialQuality level, CommandBuffer cmd)
{
for (var i = 0; i < KeywordNames.Length; ++i)
{
if ((level & (MaterialQuality)(1 << i)) != 0)
cmd.EnableShaderKeyword(KeywordNames[i]);
else
cmd.DisableShaderKeyword(KeywordNames[i]);
}
}
///
/// Returns the index (in the MaterialQuality enum) of the first available level.
///
/// MaterialQuality bitfield.
/// The index of the first available level.
public static int ToFirstIndex(this MaterialQuality level)
{
for (var i = 0; i < KeywordNames.Length; ++i)
{
if ((level & (MaterialQuality)(1 << i)) != 0)
return i;
}
return -1;
}
///
/// Returns the enum equivalent of the index in the MaterialQuality enum list.
///
/// Index of the material quality.
/// The equivalent enum.
public static MaterialQuality FromIndex(int index) => (MaterialQuality)(1 << index);
}
}