295 lines
8.5 KiB
C#
295 lines
8.5 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using UnityEngine;
|
|
using UnityEngine.VFX;
|
|
using UnityObject = UnityEngine.Object;
|
|
|
|
namespace UnityEditor.VFX
|
|
{
|
|
#pragma warning disable 0659
|
|
abstract class VFXValue : VFXExpression
|
|
{
|
|
public enum Mode
|
|
{
|
|
Variable, // Variable that should never be folded
|
|
FoldableVariable, // Variable that can be folded
|
|
Constant, // Immutable value
|
|
}
|
|
|
|
// Syntactic sugar method to create a constant value
|
|
|
|
static public VFXValue<int> Constant(Texture2D value)
|
|
{
|
|
return new VFXTexture2DValue(value.GetInstanceID(), Mode.Constant);
|
|
}
|
|
|
|
static public VFXValue<int> Constant(Texture3D value)
|
|
{
|
|
return new VFXTexture3DValue(value.GetInstanceID(), Mode.Constant);
|
|
}
|
|
|
|
static public VFXValue<int> Constant(Cubemap value)
|
|
{
|
|
return new VFXTextureCubeValue(value.GetInstanceID(), Mode.Constant);
|
|
}
|
|
|
|
static public VFXValue<int> Constant(Texture2DArray value)
|
|
{
|
|
return new VFXTexture2DArrayValue(value.GetInstanceID(), Mode.Constant);
|
|
}
|
|
|
|
static public VFXValue<int> Constant(CubemapArray value)
|
|
{
|
|
return new VFXTextureCubeArrayValue(value.GetInstanceID(), Mode.Constant);
|
|
}
|
|
|
|
static public VFXValue<T> Constant<T>(T value = default(T))
|
|
{
|
|
return new VFXValue<T>(value, Mode.Constant);
|
|
}
|
|
|
|
private static Flags GetFlagsFromMode(Mode mode, Flags flags)
|
|
{
|
|
flags |= Flags.Value;
|
|
if (mode != Mode.Variable)
|
|
{
|
|
flags |= Flags.Foldable;
|
|
if (mode == Mode.Constant)
|
|
flags |= Flags.Constant;
|
|
}
|
|
return flags;
|
|
}
|
|
|
|
protected VFXValue(Mode mode, Flags flags)
|
|
: base(GetFlagsFromMode(mode, flags))
|
|
{
|
|
m_Mode = mode;
|
|
}
|
|
|
|
public Mode ValueMode { get { return m_Mode; } }
|
|
|
|
sealed public override VFXExpressionOperation operation { get { return VFXExpressionOperation.Value; } }
|
|
|
|
protected sealed override VFXExpression Evaluate(VFXExpression[] constParents)
|
|
{
|
|
if (m_Mode == Mode.Constant)
|
|
return this;
|
|
|
|
return CopyExpression(Mode.Constant);
|
|
}
|
|
|
|
public override string GetCodeString(string[] parents)
|
|
{
|
|
if (Is(Flags.InvalidOnGPU) || !Is(Flags.Constant))
|
|
throw new InvalidOperationException(string.Format("Type {0} is either not valid on GPU or expression is not constant", valueType));
|
|
|
|
return VFXShaderWriter.GetValueString(valueType, GetContent());
|
|
}
|
|
|
|
abstract public VFXValue CopyExpression(Mode mode);
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (ReferenceEquals(this, obj))
|
|
return true;
|
|
|
|
if (m_Mode == Mode.Constant)
|
|
{
|
|
var val = obj as VFXValue;
|
|
if (val == null)
|
|
return false;
|
|
|
|
if (val.m_Mode != Mode.Constant)
|
|
return false;
|
|
|
|
if (valueType != val.valueType)
|
|
return false;
|
|
|
|
var content = GetContent();
|
|
var otherContent = val.GetContent();
|
|
|
|
if (content == null)
|
|
return otherContent == null;
|
|
|
|
return content.Equals(otherContent);
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
protected override int GetInnerHashCode()
|
|
{
|
|
if (m_Mode == Mode.Constant)
|
|
{
|
|
int hashCode = valueType.GetHashCode();
|
|
var content = GetContent();
|
|
|
|
if (content != null)
|
|
hashCode ^= content.GetHashCode();
|
|
|
|
return hashCode;
|
|
}
|
|
|
|
return RuntimeHelpers.GetHashCode(this);
|
|
}
|
|
|
|
public abstract void SetContent(object value);
|
|
|
|
private Mode m_Mode;
|
|
protected object m_Content;
|
|
}
|
|
|
|
class VFXValue<T> : VFXValue
|
|
{
|
|
protected static Flags GetFlagsFromType(VFXValueType valueType)
|
|
{
|
|
var flags = Flags.None;
|
|
if (!IsTypeValidOnGPU(valueType))
|
|
flags |= VFXExpression.Flags.InvalidOnGPU;
|
|
if (!IsTypeConstantFoldable(valueType))
|
|
flags |= VFXExpression.Flags.InvalidConstant;
|
|
return flags;
|
|
}
|
|
|
|
public VFXValue(T content, Mode mode = Mode.FoldableVariable, Flags flag = Flags.None) : base(mode, flag | GetFlagsFromType(ToValueType()))
|
|
{
|
|
m_Content = content;
|
|
}
|
|
|
|
public override VFXValue CopyExpression(Mode mode)
|
|
{
|
|
var copy = new VFXValue<T>(Get(), mode);
|
|
return copy;
|
|
}
|
|
|
|
private static readonly VFXValue s_Default = new VFXValue<T>(default(T), VFXValue.Mode.Constant);
|
|
public static VFXValue Default { get { return s_Default; } }
|
|
|
|
public T Get()
|
|
{
|
|
return (T)m_Content;
|
|
}
|
|
|
|
public override object GetContent()
|
|
{
|
|
return Get();
|
|
}
|
|
|
|
public override void SetContent(object value)
|
|
{
|
|
m_Content = default(T);
|
|
if (value == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var fromType = value.GetType();
|
|
var toType = typeof(T);
|
|
|
|
if (typeof(Texture).IsAssignableFrom(toType) && toType.IsAssignableFrom(fromType))
|
|
{
|
|
m_Content = (T)value;
|
|
}
|
|
else if (typeof(Mesh).IsAssignableFrom(toType) && toType.IsAssignableFrom(fromType))
|
|
{
|
|
m_Content = (T)value;
|
|
}
|
|
else if (fromType == toType || toType.IsAssignableFrom(fromType))
|
|
{
|
|
m_Content = (T)Convert.ChangeType(value, toType);
|
|
}
|
|
else
|
|
{
|
|
var implicitMethod = fromType.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)
|
|
.FirstOrDefault(m => m.Name == "op_Implicit" && m.ReturnType == toType);
|
|
if (implicitMethod != null)
|
|
{
|
|
m_Content = (T)implicitMethod.Invoke(null, new object[] { value });
|
|
}
|
|
else
|
|
{
|
|
Debug.LogErrorFormat("Cannot cast from {0} to {1}", fromType, toType);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static VFXValueType ToValueType()
|
|
{
|
|
Type t = typeof(T);
|
|
if (typeof(Texture).IsAssignableFrom(t))
|
|
{
|
|
return VFXValueType.None;
|
|
}
|
|
var valueType = GetVFXValueTypeFromType(t);
|
|
if (valueType == VFXValueType.None)
|
|
throw new ArgumentException("Invalid type");
|
|
return valueType;
|
|
}
|
|
|
|
static private readonly VFXValueType s_ValueType = ToValueType();
|
|
protected override int[] additionnalOperands
|
|
{
|
|
get
|
|
{
|
|
return new int[] { (int)s_ValueType };
|
|
}
|
|
}
|
|
}
|
|
|
|
class VFXObjectValue : VFXValue<int>
|
|
{
|
|
public VFXObjectValue(int instanceID, Mode mode, VFXValueType contentType) : base(instanceID, mode, GetFlagsFromType(contentType))
|
|
{
|
|
m_ContentType = contentType;
|
|
}
|
|
|
|
sealed protected override int[] additionnalOperands
|
|
{
|
|
get
|
|
{
|
|
return new int[] { (int)m_ContentType };
|
|
}
|
|
}
|
|
|
|
public override VFXValue CopyExpression(Mode mode)
|
|
{
|
|
var copy = new VFXObjectValue((int)m_Content, mode, m_ContentType);
|
|
return copy;
|
|
}
|
|
|
|
public override T Get<T>()
|
|
{
|
|
if (typeof(T) == typeof(int))
|
|
return (T)(object)base.Get();
|
|
|
|
return (T)(object)EditorUtility.InstanceIDToObject(base.Get());
|
|
}
|
|
|
|
public override object GetContent()
|
|
{
|
|
return Get();
|
|
}
|
|
|
|
public override void SetContent(object value)
|
|
{
|
|
if (value == null)
|
|
{
|
|
m_Content = (int)0;
|
|
return;
|
|
}
|
|
if (value is UnityObject obj)
|
|
{
|
|
m_Content = obj.GetInstanceID();
|
|
return;
|
|
}
|
|
|
|
m_Content = (int)value;
|
|
}
|
|
|
|
VFXValueType m_ContentType;
|
|
}
|
|
|
|
#pragma warning restore 0659
|
|
}
|