VFXExpressionAbstractNumericOperation.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. using System;
  2. using System.Linq;
  3. using System.Runtime.CompilerServices;
  4. using UnityEngine;
  5. using UnityEngine.VFX;
  6. namespace UnityEditor.VFX
  7. {
  8. abstract class VFXExpressionNumericOperation : VFXExpression
  9. {
  10. protected VFXExpressionNumericOperation(VFXExpression[] parents)
  11. : base(Flags.None, parents)
  12. {
  13. m_additionnalOperands = new int[] { };
  14. }
  15. static private object[] ToObjectArray(float input) { return new object[] { input }; }
  16. static private object[] ToObjectArray(Vector2 input) { return new object[] { input.x, input.y }; }
  17. static private object[] ToObjectArray(Vector3 input) { return new object[] { input.x, input.y, input.z }; }
  18. static private object[] ToObjectArray(Vector4 input) { return new object[] { input.x, input.y, input.z, input.w }; }
  19. static protected object[] ToObjectArray(VFXExpression input)
  20. {
  21. switch (input.valueType)
  22. {
  23. case VFXValueType.Float: return ToObjectArray(input.Get<float>());
  24. case VFXValueType.Float2: return ToObjectArray(input.Get<Vector2>());
  25. case VFXValueType.Float3: return ToObjectArray(input.Get<Vector3>());
  26. case VFXValueType.Float4: return ToObjectArray(input.Get<Vector4>());
  27. case VFXValueType.Int32: return new object[] { input.Get<int>() };
  28. case VFXValueType.Uint32: return new object[] { input.Get<uint>() };
  29. case VFXValueType.Boolean: return new object[] { input.Get<bool>() };
  30. }
  31. return null;
  32. }
  33. static protected VFXExpression ToVFXValue(object[] input, VFXValue.Mode mode)
  34. {
  35. if (input[0] is int)
  36. {
  37. if (input.Length != 1)
  38. throw new InvalidOperationException("VFXExpressionMathOperation : Unexpected size of int");
  39. return new VFXValue<int>((int)input[0], mode);
  40. }
  41. else if (input[0] is uint)
  42. {
  43. if (input.Length != 1)
  44. throw new InvalidOperationException("VFXExpressionMathOperation : Unexpected size of uint");
  45. return new VFXValue<uint>((uint)input[0], mode);
  46. }
  47. else if (input[0] is bool)
  48. {
  49. if (input.Length != 1)
  50. throw new InvalidOperationException("VFXExpressionMathOperation : Unexpected size of bool");
  51. return new VFXValue<bool>((bool)input[0], mode);
  52. }
  53. else if (input[0] is float)
  54. {
  55. if (input.OfType<float>().Count() != input.Length)
  56. throw new InvalidOperationException("VFXExpressionMathOperation : Unexpected type of float among other float");
  57. switch (input.Length)
  58. {
  59. case 1: return new VFXValue<float>((float)input[0], mode);
  60. case 2: return new VFXValue<Vector2>(new Vector2((float)input[0], (float)input[1]), mode);
  61. case 3: return new VFXValue<Vector3>(new Vector3((float)input[0], (float)input[1], (float)input[2]), mode);
  62. case 4: return new VFXValue<Vector4>(new Vector4((float)input[0], (float)input[1], (float)input[2], (float)input[3]), mode);
  63. }
  64. }
  65. return null;
  66. }
  67. static protected bool IsNumeric(VFXValueType type)
  68. {
  69. return IsFloatValueType(type) || IsUIntValueType(type) || IsIntValueType(type) || IsBoolValueType(type);
  70. }
  71. sealed public override VFXExpressionOperation operation { get { return m_Operation; } }
  72. sealed protected override int[] additionnalOperands { get { return m_additionnalOperands; } }
  73. protected override VFXExpression Reduce(VFXExpression[] reducedParents)
  74. {
  75. var newExpression = (VFXExpressionNumericOperation)base.Reduce(reducedParents);
  76. newExpression.m_additionnalOperands = m_additionnalOperands.Select(o => o).ToArray();
  77. newExpression.m_Operation = m_Operation;
  78. return newExpression;
  79. }
  80. protected int[] m_additionnalOperands;
  81. protected VFXExpressionOperation m_Operation;
  82. }
  83. abstract class VFXExpressionUnaryNumericOperation : VFXExpressionNumericOperation
  84. {
  85. protected VFXExpressionUnaryNumericOperation(VFXExpression parent, VFXExpressionOperation operation) : base(new VFXExpression[1] { parent })
  86. {
  87. if (!IsNumeric(parent.valueType))
  88. {
  89. throw new ArgumentException("Incorrect VFXExpressionUnaryMathOperation");
  90. }
  91. m_additionnalOperands = new int[] { (int)parent.valueType };
  92. m_Operation = operation;
  93. }
  94. sealed protected override VFXExpression Evaluate(VFXExpression[] reducedParents)
  95. {
  96. var source = ToObjectArray(reducedParents[0]);
  97. var result = new object[source.Length];
  98. if (source[0] is float)
  99. {
  100. result = source.Select(o => (object)ProcessUnaryOperation((float)o)).ToArray();
  101. }
  102. else if (source[0] is int)
  103. {
  104. result = source.Select(o => (object)ProcessUnaryOperation((int)o)).ToArray();
  105. }
  106. else if (source[0] is uint)
  107. {
  108. result = source.Select(o => (object)ProcessUnaryOperation((uint)o)).ToArray();
  109. }
  110. else if (source[0] is bool)
  111. {
  112. result = source.Select(o => (object)ProcessUnaryOperation((bool)o)).ToArray();
  113. }
  114. else
  115. {
  116. throw new InvalidOperationException("Unexpected type in VFXExpressionUnaryMathOperation");
  117. }
  118. return ToVFXValue(result, VFXValue.Mode.Constant);
  119. }
  120. abstract protected float ProcessUnaryOperation(float input);
  121. abstract protected int ProcessUnaryOperation(int input);
  122. abstract protected uint ProcessUnaryOperation(uint input);
  123. abstract protected bool ProcessUnaryOperation(bool input);
  124. sealed public override string GetCodeString(string[] parents)
  125. {
  126. var valueType = this.parents.First().valueType;
  127. valueType = IsFloatValueType(valueType) ? VFXValueType.Float : valueType;
  128. return GetUnaryOperationCode(parents[0], valueType);
  129. }
  130. abstract protected string GetUnaryOperationCode(string x, VFXValueType type);
  131. }
  132. abstract class VFXExpressionBinaryNumericOperation : VFXExpressionNumericOperation
  133. {
  134. protected VFXExpressionBinaryNumericOperation(VFXExpression parentLeft, VFXExpression parentRight, VFXExpressionOperation operation)
  135. : base(new VFXExpression[2] { parentLeft, parentRight })
  136. {
  137. if (!IsNumeric(parentLeft.valueType) || !IsNumeric(parentRight.valueType))
  138. {
  139. throw new ArgumentException("Incorrect VFXExpressionBinaryMathOperation (not numeric type)");
  140. }
  141. if (parentRight.valueType != parentLeft.valueType)
  142. {
  143. throw new ArgumentException("Incorrect VFXExpressionBinaryFloatOperation (incompatible numeric type)");
  144. }
  145. m_additionnalOperands = new int[] { (int)parentLeft.valueType };
  146. m_Operation = operation;
  147. }
  148. sealed protected override VFXExpression Evaluate(VFXExpression[] reducedParents)
  149. {
  150. var parentLeft = reducedParents[0];
  151. var parentRight = reducedParents[1];
  152. var sourceLeft = ToObjectArray(parentLeft);
  153. var sourceRight = ToObjectArray(parentRight);
  154. var result = new object[sourceLeft.Length];
  155. if (sourceLeft[0] is float)
  156. {
  157. for (int iChannel = 0; iChannel < sourceLeft.Length; ++iChannel)
  158. {
  159. result[iChannel] = ProcessBinaryOperation((float)sourceLeft[iChannel], (float)sourceRight[iChannel]);
  160. }
  161. }
  162. else if (sourceLeft[0] is int)
  163. {
  164. for (int iChannel = 0; iChannel < sourceLeft.Length; ++iChannel)
  165. {
  166. result[iChannel] = ProcessBinaryOperation((int)sourceLeft[iChannel], (int)sourceRight[iChannel]);
  167. }
  168. }
  169. else if (sourceLeft[0] is uint)
  170. {
  171. for (int iChannel = 0; iChannel < sourceLeft.Length; ++iChannel)
  172. {
  173. result[iChannel] = ProcessBinaryOperation((uint)sourceLeft[iChannel], (uint)sourceRight[iChannel]);
  174. }
  175. }
  176. else if (sourceLeft[0] is bool)
  177. {
  178. for (int iChannel = 0; iChannel < sourceLeft.Length; ++iChannel)
  179. {
  180. result[iChannel] = ProcessBinaryOperation((bool)sourceLeft[iChannel], (bool)sourceRight[iChannel]);
  181. }
  182. }
  183. else
  184. {
  185. throw new InvalidOperationException("Unexpected type in VFXExpressionUnaryMathOperation");
  186. }
  187. return ToVFXValue(result, VFXValue.Mode.Constant);
  188. }
  189. abstract protected float ProcessBinaryOperation(float x, float y);
  190. abstract protected int ProcessBinaryOperation(int x, int y);
  191. abstract protected uint ProcessBinaryOperation(uint x, uint y);
  192. abstract protected bool ProcessBinaryOperation(bool x, bool y);
  193. sealed public override string GetCodeString(string[] parents)
  194. {
  195. var valueType = this.parents.First().valueType;
  196. valueType = IsFloatValueType(valueType) ? VFXValueType.Float : valueType;
  197. return GetBinaryOperationCode(parents[0], parents[1], valueType);
  198. }
  199. abstract protected string GetBinaryOperationCode(string x, string y, VFXValueType type);
  200. }
  201. }