VFXExpressionAbstractValues.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. using System;
  2. using System.Linq;
  3. using System.Runtime.CompilerServices;
  4. using UnityEngine;
  5. using UnityEngine.VFX;
  6. using UnityObject = UnityEngine.Object;
  7. namespace UnityEditor.VFX
  8. {
  9. #pragma warning disable 0659
  10. abstract class VFXValue : VFXExpression
  11. {
  12. public enum Mode
  13. {
  14. Variable, // Variable that should never be folded
  15. FoldableVariable, // Variable that can be folded
  16. Constant, // Immutable value
  17. }
  18. // Syntactic sugar method to create a constant value
  19. static public VFXValue<int> Constant(Texture2D value)
  20. {
  21. return new VFXTexture2DValue(value.GetInstanceID(), Mode.Constant);
  22. }
  23. static public VFXValue<int> Constant(Texture3D value)
  24. {
  25. return new VFXTexture3DValue(value.GetInstanceID(), Mode.Constant);
  26. }
  27. static public VFXValue<int> Constant(Cubemap value)
  28. {
  29. return new VFXTextureCubeValue(value.GetInstanceID(), Mode.Constant);
  30. }
  31. static public VFXValue<int> Constant(Texture2DArray value)
  32. {
  33. return new VFXTexture2DArrayValue(value.GetInstanceID(), Mode.Constant);
  34. }
  35. static public VFXValue<int> Constant(CubemapArray value)
  36. {
  37. return new VFXTextureCubeArrayValue(value.GetInstanceID(), Mode.Constant);
  38. }
  39. static public VFXValue<int> Constant(CameraBuffer value)
  40. {
  41. return new VFXCameraBufferValue(value, Mode.Constant);
  42. }
  43. static public VFXValue<T> Constant<T>(T value = default(T))
  44. {
  45. return new VFXValue<T>(value, Mode.Constant);
  46. }
  47. private static Flags GetFlagsFromMode(Mode mode, Flags flags)
  48. {
  49. flags |= Flags.Value;
  50. if (mode != Mode.Variable)
  51. {
  52. flags |= Flags.Foldable;
  53. if (mode == Mode.Constant)
  54. flags |= Flags.Constant;
  55. }
  56. return flags;
  57. }
  58. protected VFXValue(Mode mode, Flags flags)
  59. : base(GetFlagsFromMode(mode, flags))
  60. {
  61. m_Mode = mode;
  62. }
  63. public Mode ValueMode { get { return m_Mode; } }
  64. sealed public override VFXExpressionOperation operation { get { return VFXExpressionOperation.Value; } }
  65. protected sealed override VFXExpression Evaluate(VFXExpression[] constParents)
  66. {
  67. if (m_Mode == Mode.Constant)
  68. return this;
  69. return CopyExpression(Mode.Constant);
  70. }
  71. public override string GetCodeString(string[] parents)
  72. {
  73. if (Is(Flags.InvalidOnGPU) || !Is(Flags.Constant))
  74. throw new InvalidOperationException(string.Format("Type {0} is either not valid on GPU or expression is not constant", valueType));
  75. return VFXShaderWriter.GetValueString(valueType, GetContent());
  76. }
  77. abstract public VFXValue CopyExpression(Mode mode);
  78. public override bool Equals(object obj)
  79. {
  80. if (ReferenceEquals(this, obj))
  81. return true;
  82. if (m_Mode == Mode.Constant)
  83. {
  84. var val = obj as VFXValue;
  85. if (val == null)
  86. return false;
  87. if (val.m_Mode != Mode.Constant)
  88. return false;
  89. if (valueType != val.valueType)
  90. return false;
  91. var content = GetContent();
  92. var otherContent = val.GetContent();
  93. if (content == null)
  94. return otherContent == null;
  95. return content.Equals(otherContent);
  96. }
  97. else
  98. return false;
  99. }
  100. protected override int GetInnerHashCode()
  101. {
  102. if (m_Mode == Mode.Constant)
  103. {
  104. int hashCode = valueType.GetHashCode();
  105. var content = GetContent();
  106. if (content != null)
  107. hashCode ^= content.GetHashCode();
  108. return hashCode;
  109. }
  110. return RuntimeHelpers.GetHashCode(this);
  111. }
  112. public abstract void SetContent(object value);
  113. private Mode m_Mode;
  114. protected object m_Content;
  115. }
  116. class VFXValue<T> : VFXValue
  117. {
  118. protected static Flags GetFlagsFromType(VFXValueType valueType)
  119. {
  120. var flags = Flags.None;
  121. if (!IsTypeValidOnGPU(valueType))
  122. flags |= VFXExpression.Flags.InvalidOnGPU;
  123. if (!IsTypeConstantFoldable(valueType))
  124. flags |= VFXExpression.Flags.InvalidConstant;
  125. return flags;
  126. }
  127. public VFXValue(T content, Mode mode = Mode.FoldableVariable, Flags flag = Flags.None) : base(mode, flag | GetFlagsFromType(ToValueType()))
  128. {
  129. m_Content = content;
  130. }
  131. public override VFXValue CopyExpression(Mode mode)
  132. {
  133. var copy = new VFXValue<T>(Get(), mode);
  134. return copy;
  135. }
  136. private static readonly VFXValue s_Default = new VFXValue<T>(default(T), VFXValue.Mode.Constant);
  137. public static VFXValue Default { get { return s_Default; } }
  138. public T Get()
  139. {
  140. return (T)m_Content;
  141. }
  142. public override object GetContent()
  143. {
  144. return Get();
  145. }
  146. public override void SetContent(object value)
  147. {
  148. m_Content = default(T);
  149. if (value == null)
  150. {
  151. return;
  152. }
  153. var fromType = value.GetType();
  154. var toType = typeof(T);
  155. if (typeof(Texture).IsAssignableFrom(toType) && toType.IsAssignableFrom(fromType))
  156. {
  157. m_Content = (T)value;
  158. }
  159. else if (typeof(Mesh).IsAssignableFrom(toType) && toType.IsAssignableFrom(fromType))
  160. {
  161. m_Content = (T)value;
  162. }
  163. else if (fromType == toType || toType.IsAssignableFrom(fromType))
  164. {
  165. m_Content = (T)Convert.ChangeType(value, toType);
  166. }
  167. else if (toType == typeof(GraphicsBuffer))
  168. {
  169. //We can't serialize a reference of GraphicsBuffer
  170. m_Content = null;
  171. }
  172. else
  173. {
  174. var implicitMethod = fromType.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)
  175. .FirstOrDefault(m => m.Name == "op_Implicit" && m.ReturnType == toType);
  176. if (implicitMethod != null)
  177. {
  178. m_Content = (T)implicitMethod.Invoke(null, new object[] { value });
  179. }
  180. else
  181. {
  182. Debug.LogErrorFormat("Cannot cast from {0} to {1}", fromType, toType);
  183. }
  184. }
  185. }
  186. private static VFXValueType ToValueType()
  187. {
  188. Type t = typeof(T);
  189. if (typeof(Texture).IsAssignableFrom(t))
  190. {
  191. return VFXValueType.None;
  192. }
  193. var valueType = GetVFXValueTypeFromType(t);
  194. if (valueType == VFXValueType.None)
  195. throw new ArgumentException("Invalid type");
  196. return valueType;
  197. }
  198. static private readonly VFXValueType s_ValueType = ToValueType();
  199. protected override int[] additionnalOperands
  200. {
  201. get
  202. {
  203. return new int[] { (int)s_ValueType };
  204. }
  205. }
  206. }
  207. class VFXObjectValue : VFXValue<int>
  208. {
  209. public VFXObjectValue(int instanceID, Mode mode, VFXValueType contentType) : base(instanceID, mode, GetFlagsFromType(contentType))
  210. {
  211. m_ContentType = contentType;
  212. }
  213. sealed protected override int[] additionnalOperands
  214. {
  215. get
  216. {
  217. return new int[] { (int)m_ContentType };
  218. }
  219. }
  220. public override VFXValue CopyExpression(Mode mode)
  221. {
  222. var copy = new VFXObjectValue((int)m_Content, mode, m_ContentType);
  223. return copy;
  224. }
  225. public override T Get<T>()
  226. {
  227. if (typeof(T) == typeof(int))
  228. return (T)(object)base.Get();
  229. return (T)(object)EditorUtility.InstanceIDToObject(base.Get());
  230. }
  231. public override object GetContent()
  232. {
  233. return Get();
  234. }
  235. public override void SetContent(object value)
  236. {
  237. if (value == null)
  238. {
  239. m_Content = (int)0;
  240. return;
  241. }
  242. if (value is UnityObject obj)
  243. {
  244. m_Content = obj.GetInstanceID();
  245. return;
  246. }
  247. if (value is CameraBuffer cameraBuffer)
  248. {
  249. m_Content = cameraBuffer;
  250. return;
  251. }
  252. if (value is GraphicsBuffer)
  253. {
  254. m_Content = (int)0;
  255. return;
  256. }
  257. m_Content = (int)value;
  258. }
  259. VFXValueType m_ContentType;
  260. }
  261. #pragma warning restore 0659
  262. }