using System.Collections.Generic;
using UnityEngine;
namespace EPOOutline
{
///
/// Holds an information about how pass should be rendered.
///
[System.Serializable]
public class SerializedPass : ISerializationCallbackReceiver
{
///
/// The type of shader property.
///
public enum PropertyType
{
///
/// Color.
///
Color = 0,
///
/// Vector.
///
Vector = 1,
///
/// Float.
///
Float = 2,
///
/// Float but limited with a range.
///
Range = 3,
///
/// Texture.
///
TexEnv = 4
}
[System.Serializable]
private class SerializedPropertyKeyValuePair
{
[SerializeField]
public string PropertyName;
[SerializeField]
public SerializedPassProperty Property;
}
[System.Serializable]
private class SerializedPassProperty
{
#pragma warning disable CS0649
[SerializeField]
public Color ColorValue;
[SerializeField]
public float FloatValue;
[SerializeField]
public Vector4 VectorValue;
[SerializeField]
public PropertyType PropertyType;
#pragma warning restore CS0649
}
[SerializeField]
private Shader shader;
///
/// The that will be used for rendering the pass.
///
public Shader Shader
{
get => shader;
set
{
propertiesIsDirty = true;
shader = value;
}
}
[SerializeField]
private List serializedProperties = new List();
private Dictionary propertiesById = new Dictionary();
private Dictionary propertiesByName = new Dictionary();
private Material material;
private bool propertiesIsDirty = false;
internal Material Material
{
get
{
if (shader == null)
return null;
if (material == null || material.shader != shader)
{
if (material != null)
GameObject.DestroyImmediate(material);
material = new Material(shader);
}
if (!propertiesIsDirty)
return material;
foreach (var property in propertiesById)
{
switch (property.Value.PropertyType)
{
case PropertyType.Color:
material.SetColor(property.Key, property.Value.ColorValue);
break;
case PropertyType.Vector:
material.SetVector(property.Key, property.Value.VectorValue);
break;
case PropertyType.Float:
material.SetFloat(property.Key, property.Value.FloatValue);
break;
case PropertyType.Range:
material.SetFloat(property.Key, property.Value.FloatValue);
break;
case PropertyType.TexEnv:
break;
}
}
propertiesIsDirty = false;
return material;
}
}
///
/// Checks if the pass has the property.
///
/// The property name to check
/// Returns true if it has the property.
public bool HasProperty(string name)
{
return propertiesByName.ContainsKey(name);
}
///
/// Checks if the pass has the property.
///
/// The property hash to check
/// Returns true if it has the property.
public bool HasProperty(int hash)
{
return propertiesById.ContainsKey(hash);
}
///
/// Returns a vector from the pass.
///
/// The name of the vector.
/// The vector result.
public Vector4 GetVector(string name)
{
SerializedPassProperty result = null;
if (!propertiesByName.TryGetValue(name, out result))
{
Debug.LogError("The property " + name + " doesn't exist");
return Vector4.zero;
}
if (result.PropertyType == PropertyType.Vector)
return result.VectorValue;
Debug.LogError("The property " + name + " is not a vector property");
return Vector4.zero;
}
///
/// Returns a vector from the pass.
///
/// The hash of the vector.
/// The vector result.
public Vector4 GetVector(int hash)
{
SerializedPassProperty result = null;
if (!propertiesById.TryGetValue(hash, out result))
{
Debug.LogError("The property " + hash + " doesn't exist");
return Vector4.zero;
}
if (result.PropertyType == PropertyType.Vector)
return result.VectorValue;
Debug.LogError("The property " + hash + " is not a vector property");
return Vector4.zero;
}
///
/// Sets vector to the pass.
///
/// The name of the vector.
/// The vector value to be set.
public void SetVector(string name, Vector4 value)
{
propertiesIsDirty = true;
SerializedPassProperty result = null;
if (!propertiesByName.TryGetValue(name, out result))
{
result = new SerializedPassProperty();
result.PropertyType = PropertyType.Vector;
propertiesByName.Add(name, result);
propertiesById.Add(Shader.PropertyToID(name), result);
}
if (result.PropertyType != PropertyType.Vector)
{
Debug.LogError("The property " + name + " is not a vector property");
return;
}
result.VectorValue = value;
}
///
/// Sets vector to the pass.
///
/// The hash of the vector.
/// The vector value to be set.
public void SetVector(int hash, Vector4 value)
{
propertiesIsDirty = true;
SerializedPassProperty result = null;
if (!propertiesById.TryGetValue(hash, out result))
{
Debug.LogWarning("The property " + hash + " doesn't exist. Use string overload to create one.");
return;
}
if (result.PropertyType != PropertyType.Vector)
{
Debug.LogError("The property " + hash + " is not a vector property");
return;
}
result.VectorValue = value;
}
///
/// Returns a float from the pass.
///
/// The name of the float.
/// The float value from the pass.
public float GetFloat(string name)
{
SerializedPassProperty result = null;
if (!propertiesByName.TryGetValue(name, out result))
{
Debug.LogError("The property " + name + " doesn't exist");
return 0.0f;
}
if (result.PropertyType == PropertyType.Float || result.PropertyType == PropertyType.Range)
return result.FloatValue;
Debug.LogError("The property " + name + " is not a float property");
return 0.0f;
}
///
/// Returns a float from the pass.
///
/// The hash of the float.
/// The float value from the pass.
public float GetFloat(int hash)
{
SerializedPassProperty result = null;
if (!propertiesById.TryGetValue(hash, out result))
{
Debug.LogError("The property " + hash + " is doesn't exist");
return 0.0f;
}
if (result.PropertyType == PropertyType.Float || result.PropertyType == PropertyType.Range)
return result.FloatValue;
Debug.LogError("The property " + hash + " is not a float property");
return 0.0f;
}
///
/// Sets a float to the pass.
///
/// The name of the float.
/// The value to be set.
public void SetFloat(string name, float value)
{
propertiesIsDirty = true;
SerializedPassProperty result = null;
if (!propertiesByName.TryGetValue(name, out result))
{
result = new SerializedPassProperty();
result.PropertyType = PropertyType.Float;
propertiesByName.Add(name, result);
propertiesById.Add(Shader.PropertyToID(name), result);
}
if (result.PropertyType != PropertyType.Float && result.PropertyType != PropertyType.Range)
{
Debug.LogError("The property " + name + " is not a float property");
return;
}
result.FloatValue = value;
}
///
/// Sets a float to the pass.
///
/// The hash of the float.
/// The value to be set.
public void SetFloat(int hash, float value)
{
propertiesIsDirty = true;
SerializedPassProperty result = null;
if (!propertiesById.TryGetValue(hash, out result))
{
Debug.LogError("The property " + hash + " doesn't exist. Use string overload to create one.");
return;
}
if (result.PropertyType != PropertyType.Float)
{
Debug.LogError("The property " + hash + " is not a float property");
return;
}
result.FloatValue = value;
}
///
/// Returns a color from the pass.
///
/// The name of the color.
/// The color value from the pass.
public Color GetColor(string name)
{
SerializedPassProperty result = null;
if (!propertiesByName.TryGetValue(name, out result))
{
Debug.LogError("The property " + name + " doesn't exist");
return Color.black;
}
if (result.PropertyType == PropertyType.Color)
return result.ColorValue;
else
{
Debug.LogError("The property " + name + " is not a color property");
return Color.black;
}
}
///
/// Returns a color from the pass.
///
/// The hash of the color.
/// The color value from the pass.
public Color GetColor(int hash)
{
SerializedPassProperty result = null;
if (!propertiesById.TryGetValue(hash, out result))
{
Debug.LogError("The property " + hash + " doesn't exist");
return Color.black;
}
if (result.PropertyType == PropertyType.Color)
return result.ColorValue;
else
return Color.black;
}
///
/// Sets a color to the pass.
///
/// The name of the color
/// The value to be set.
public void SetColor(string name, Color value)
{
propertiesIsDirty = true;
SerializedPassProperty result = null;
if (!propertiesByName.TryGetValue(name, out result))
{
result = new SerializedPassProperty();
result.PropertyType = PropertyType.Color;
propertiesByName.Add(name, result);
propertiesById.Add(Shader.PropertyToID(name), result);
}
if (result.PropertyType != PropertyType.Color)
{
Debug.LogError("The property " + name + " is not a color property.");
return;
}
result.ColorValue = value;
}
///
/// Sets a color to the pass.
///
/// The hash of the color
/// The value to be set.
public void SetColor(int hash, Color value)
{
propertiesIsDirty = true;
SerializedPassProperty result = null;
if (!propertiesById.TryGetValue(hash, out result))
{
Debug.LogError("The property " + hash + " doesn't exist. Use string overload to create one.");
return;
}
if (result.PropertyType != PropertyType.Color)
{
Debug.LogError("The property " + hash + " is not a color property");
return;
}
result.ColorValue = value;
}
public void OnBeforeSerialize()
{
serializedProperties.Clear();
foreach (var property in propertiesByName)
{
var pair = new SerializedPropertyKeyValuePair();
pair.Property = property.Value;
pair.PropertyName = property.Key;
serializedProperties.Add(pair);
}
}
public void OnAfterDeserialize()
{
propertiesIsDirty = true;
propertiesById.Clear();
propertiesByName.Clear();
foreach (var serialized in serializedProperties)
{
if (propertiesByName.ContainsKey(serialized.PropertyName))
continue;
propertiesById.Add(Shader.PropertyToID(serialized.PropertyName), serialized.Property);
propertiesByName.Add(serialized.PropertyName, serialized.Property);
}
}
}
}