VFXAttributeExpression.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using UnityEngine.VFX;
  6. namespace UnityEditor.VFX
  7. {
  8. [Flags]
  9. enum VFXAttributeMode
  10. {
  11. None = 0,
  12. Read = 1 << 0,
  13. Write = 1 << 1,
  14. ReadWrite = Read | Write,
  15. ReadSource = 1 << 2,
  16. }
  17. struct VFXAttribute
  18. {
  19. public static readonly float kDefaultSize = 0.1f;
  20. [Tooltip("Outputs a unique, constant, per-particle random value.")]
  21. public static readonly VFXAttribute Seed = new VFXAttribute("seed", VFXValueType.Uint32);
  22. [Tooltip("No special function at the moment, can be used as a custom Vector3 to store additional per-particle data.")]
  23. public static readonly VFXAttribute OldPosition = new VFXAttribute("oldPosition", VFXValueType.Float3, VFXVariadic.False, SpaceableType.Position);
  24. [Tooltip("The current position of the particle.")]
  25. public static readonly VFXAttribute Position = new VFXAttribute("position", VFXValueType.Float3, VFXVariadic.False, SpaceableType.Position);
  26. [Tooltip("The velocity of the particle.")]
  27. public static readonly VFXAttribute Velocity = new VFXAttribute("velocity", VFXValueType.Float3, VFXVariadic.False, SpaceableType.Vector);
  28. [Tooltip("The direction the particle is moving in.")]
  29. public static readonly VFXAttribute Direction = new VFXAttribute("direction", VFXValue.Constant(new Vector3(0.0f, 0.0f, 1.0f)), VFXVariadic.False, SpaceableType.Vector);
  30. [Tooltip("The color of the particle.")]
  31. public static readonly VFXAttribute Color = new VFXAttribute("color", VFXValue.Constant(Vector3.one));
  32. [Tooltip("The transparency value of the particle. Transparent particles with a value of 0 or less are invisible.")]
  33. public static readonly VFXAttribute Alpha = new VFXAttribute("alpha", VFXValue.Constant(1.0f));
  34. [Tooltip("The uniform size of the particle.")]
  35. public static readonly VFXAttribute Size = new VFXAttribute("size", VFXValue.Constant(kDefaultSize));
  36. [Tooltip("The scale of the particle along the X axis, as a multiplier to its size.")]
  37. public static readonly VFXAttribute ScaleX = new VFXAttribute("scaleX", VFXValue.Constant(1.0f), VFXVariadic.BelongsToVariadic);
  38. [Tooltip("The per-axis scale of the particle along the Y axis, as a multiplier to its size.")]
  39. public static readonly VFXAttribute ScaleY = new VFXAttribute("scaleY", VFXValue.Constant(1.0f), VFXVariadic.BelongsToVariadic);
  40. [Tooltip("The per-axis scale of the particle along the Z axis, as a multiplier to its size.")]
  41. public static readonly VFXAttribute ScaleZ = new VFXAttribute("scaleZ", VFXValue.Constant(1.0f), VFXVariadic.BelongsToVariadic);
  42. [Tooltip("Indicates how long the particle can stay alive. If the particle’s age exceeds its lifetime, the particle is destroyed.")]
  43. public static readonly VFXAttribute Lifetime = new VFXAttribute("lifetime", VFXValue.Constant(1.0f));
  44. [Tooltip("The age of the particle. If a particle’s age exceeds its lifetime, it gets destroyed.")]
  45. public static readonly VFXAttribute Age = new VFXAttribute("age", VFXValueType.Float);
  46. [Tooltip("The particle angle per axis. For Camera-facing billboard particles, the Z axis is most likely the desired axis of rotation.")]
  47. public static readonly VFXAttribute AngleX = new VFXAttribute("angleX", VFXValueType.Float, VFXVariadic.BelongsToVariadic);
  48. [Tooltip("The particle angle per axis. For Camera-facing billboard particles, the Z axis is most likely the desired axis of rotation.")]
  49. public static readonly VFXAttribute AngleY = new VFXAttribute("angleY", VFXValueType.Float, VFXVariadic.BelongsToVariadic);
  50. [Tooltip("The particle angle per axis. For Camera-facing billboard particles, the Z axis is most likely the desired axis of rotation.")]
  51. public static readonly VFXAttribute AngleZ = new VFXAttribute("angleZ", VFXValueType.Float, VFXVariadic.BelongsToVariadic);
  52. [Tooltip("The angular rotation of the particle, in degrees per second.")]
  53. public static readonly VFXAttribute AngularVelocityX = new VFXAttribute("angularVelocityX", VFXValueType.Float, VFXVariadic.BelongsToVariadic);
  54. [Tooltip("The angular rotation of the particle, in degrees per second.")]
  55. public static readonly VFXAttribute AngularVelocityY = new VFXAttribute("angularVelocityY", VFXValueType.Float, VFXVariadic.BelongsToVariadic);
  56. [Tooltip("The angular rotation of the particle, in degrees per second.")]
  57. public static readonly VFXAttribute AngularVelocityZ = new VFXAttribute("angularVelocityZ", VFXValueType.Float, VFXVariadic.BelongsToVariadic);
  58. [Tooltip("The current index of the flipbook. This attribute is used if ‘UV Mode’ in the output is set to use flipbooks.")]
  59. public static readonly VFXAttribute TexIndex = new VFXAttribute("texIndex", VFXValueType.Float);
  60. [Tooltip("The current index of the mesh. This attribute is used with multi mesh outputs.")]
  61. public static readonly VFXAttribute MeshIndex = new VFXAttribute("meshIndex", VFXValueType.Uint32);
  62. [Tooltip("The point around which the particle rotates, moves, or is scaled. By default, this is the center of the particle.")]
  63. public static readonly VFXAttribute PivotX = new VFXAttribute("pivotX", VFXValue.Constant(0.0f), VFXVariadic.BelongsToVariadic);
  64. [Tooltip("The point around which the particle rotates, moves, or is scaled. By default, this is the center of the particle.")]
  65. public static readonly VFXAttribute PivotY = new VFXAttribute("pivotY", VFXValue.Constant(0.0f), VFXVariadic.BelongsToVariadic);
  66. [Tooltip("The point around which the particle rotates, moves, or is scaled. By default, this is the center of the particle.")]
  67. public static readonly VFXAttribute PivotZ = new VFXAttribute("pivotZ", VFXValue.Constant(0.0f), VFXVariadic.BelongsToVariadic);
  68. [Tooltip("Outputs the ID of the particle. Each particle gets assigned an incremental unique ID value when it is created.")]
  69. public static readonly VFXAttribute ParticleId = new VFXAttribute("particleId", VFXValueType.Uint32);
  70. [Tooltip("Determines which is the X (right-left) axis of the particle.")]
  71. public static readonly VFXAttribute AxisX = new VFXAttribute("axisX", VFXValue.Constant(Vector3.right), VFXVariadic.False, SpaceableType.Vector);
  72. [Tooltip("Determines which is the Y (up-down) axis of the particle.")]
  73. public static readonly VFXAttribute AxisY = new VFXAttribute("axisY", VFXValue.Constant(Vector3.up), VFXVariadic.False, SpaceableType.Vector);
  74. [Tooltip("Determines which is the Z (forward-back) axis of the particle.")]
  75. public static readonly VFXAttribute AxisZ = new VFXAttribute("axisZ", VFXValue.Constant(Vector3.forward), VFXVariadic.False, SpaceableType.Vector);
  76. [Tooltip("Indicates whether a particle is alive or should be destroyed. Can also be used within an output to toggle the rendering of that particle, without destroying it.")]
  77. public static readonly VFXAttribute Alive = new VFXAttribute("alive", VFXValue.Constant(true));
  78. [Tooltip("The mass of the particle, which is used in many physics calculations.")]
  79. public static readonly VFXAttribute Mass = new VFXAttribute("mass", VFXValue.Constant(1.0f));
  80. [Tooltip("The position where the particle is aiming to go. This value is used by the line output, but it can also be used to store any desired value for a custom simulation.")]
  81. public static readonly VFXAttribute TargetPosition = new VFXAttribute("targetPosition", VFXValueType.Float3, VFXVariadic.False, SpaceableType.Position);
  82. [Tooltip("")]
  83. public static readonly VFXAttribute EventCount = new VFXAttribute("eventCount", VFXValueType.Uint32);
  84. [Tooltip("Outputs the time since the Spawn context was triggered. To use, add a 'Set Spawn Time' block to the desired Spawn Context.")]
  85. public static readonly VFXAttribute SpawnTime = new VFXAttribute("spawnTime", VFXValueType.Float);
  86. [Tooltip("Outputs the index of the particle within its particle strip. Each particle gets assigned an incremental index value for the strip within which it is created. This attribute is available in systems using the 'Particle Strip' data type.")]
  87. public static readonly VFXAttribute ParticleIndexInStrip = new VFXAttribute("particleIndexInStrip", VFXValueType.Uint32);
  88. [Tooltip("Outputs the index of the particle within all the particles spawned in the current frame.")]
  89. public static readonly VFXAttribute SpawnIndex = new VFXAttribute("spawnIndex", VFXValueType.Uint32);
  90. [Tooltip("Outputs the index of the current strip. Each strip gets assigned an incremental value when it is created. This attribute is available in systems using the 'Particle Strip' data type.")]
  91. public static readonly VFXAttribute StripIndex = new VFXAttribute("stripIndex", VFXValueType.Uint32);
  92. [Tooltip("Outputs the total particle count within the current strip. This attribute is available in systems using the 'Particle Strip' data type.")]
  93. public static readonly VFXAttribute ParticleCountInStrip = new VFXAttribute("particleCountInStrip", VFXValueType.Uint32);
  94. [Tooltip("Outputs the spawn index of the particle within its strip. This attribute is available in systems using the 'Particle Strip' data type.")]
  95. public static readonly VFXAttribute SpawnIndexInStrip = new VFXAttribute("spawnIndexInStrip", VFXValueType.Uint32);
  96. [Tooltip("Outputs the number of particles spawned. This value is relative in the Spawn Context.")]
  97. public static readonly VFXAttribute SpawnCount = new VFXAttribute("spawnCount", VFXValue.Constant(1.0f));
  98. // Internal as we dont want it to appear in the graph
  99. internal static readonly VFXAttribute StripAlive = new VFXAttribute("stripAlive", VFXValue.Constant(true)); // Internal attribute used to keep track of the state of the attached strip (TODO: Use a number to handle more tha 1 strip)
  100. public static readonly VFXAttribute[] AllAttribute = VFXReflectionHelper.CollectStaticReadOnlyExpression<VFXAttribute>(typeof(VFXAttribute));
  101. public static readonly VFXAttribute[] AllAttributeReadOnly = new VFXAttribute[] { Seed, ParticleId, ParticleIndexInStrip, SpawnTime, SpawnIndex, SpawnCount, StripIndex, ParticleCountInStrip, SpawnIndexInStrip };
  102. public static readonly VFXAttribute[] AllAttributeWriteOnly = new VFXAttribute[] { EventCount };
  103. public static readonly VFXAttribute[] AllAttributeLocalOnly = new VFXAttribute[] { EventCount, ParticleIndexInStrip, StripIndex, ParticleCountInStrip };
  104. public static readonly string[] All = AllAttribute.Select(e => e.name).ToArray();
  105. public static readonly string[] AllReadOnly = AllAttributeReadOnly.Select(e => e.name).ToArray();
  106. public static readonly string[] AllLocalOnly = AllAttributeLocalOnly.Select(e => e.name).ToArray();
  107. public static readonly string[] AllWriteOnly = AllAttributeWriteOnly.Select(e => e.name).ToArray();
  108. public static readonly string[] AllExceptLocalOnly = All.Except(AllLocalOnly).ToArray();
  109. public static readonly string[] AllWritable = All.Except(AllReadOnly).ToArray();
  110. public static readonly string[] AllReadWritable = All.Except(AllReadOnly).Except(AllWriteOnly).ToArray();
  111. public static readonly VFXAttribute[] AllVariadicAttribute = new VFXAttribute[]
  112. {
  113. new VFXAttribute("angle", VFXValueType.Float3, VFXVariadic.True),
  114. new VFXAttribute("angularVelocity", VFXValueType.Float3, VFXVariadic.True),
  115. new VFXAttribute("pivot", VFXValueType.Float3, VFXVariadic.True),
  116. new VFXAttribute("scale", VFXValue.Constant(new Vector3((float)ScaleX.value.GetContent(), (float)ScaleY.value.GetContent(), (float)ScaleZ.value.GetContent())), VFXVariadic.True)
  117. };
  118. public static readonly string[] AllVariadic = AllVariadicAttribute.Select(e => e.name).ToArray();
  119. public static readonly string[] AllIncludingVariadic = AllAttribute.Where(e => e.variadic != VFXVariadic.BelongsToVariadic).Select(e => e.name).ToArray().Concat(AllVariadic).ToArray();
  120. public static readonly string[] AllIncludingVariadicExceptLocalOnly = AllIncludingVariadic.Except(AllLocalOnly).ToArray();
  121. public static readonly string[] AllIncludingVariadicExceptWriteOnly = AllIncludingVariadic.Except(AllWriteOnly).ToArray();
  122. public static readonly string[] AllIncludingVariadicWritable = AllIncludingVariadic.Except(AllReadOnly).ToArray();
  123. public static readonly string[] AllIncludingVariadicReadWritable = AllIncludingVariadic.Except(AllReadOnly).Except(AllWriteOnly).ToArray();
  124. static private VFXValue GetValueFromType(VFXValueType type)
  125. {
  126. switch (type)
  127. {
  128. case VFXValueType.Boolean: return VFXValue.Constant<bool>();
  129. case VFXValueType.Uint32: return VFXValue.Constant<uint>();
  130. case VFXValueType.Int32: return VFXValue.Constant<int>();
  131. case VFXValueType.Float: return VFXValue.Constant<float>();
  132. case VFXValueType.Float2: return VFXValue.Constant<Vector2>();
  133. case VFXValueType.Float3: return VFXValue.Constant<Vector3>();
  134. case VFXValueType.Float4: return VFXValue.Constant<Vector4>();
  135. default: throw new InvalidOperationException(string.Format("Unexpected attribute type: {0}", type));
  136. }
  137. }
  138. public VFXAttribute(string name, VFXValueType type, VFXVariadic variadic = VFXVariadic.False, SpaceableType space = SpaceableType.None)
  139. : this(name, GetValueFromType(type), variadic, space)
  140. {
  141. }
  142. public VFXAttribute(string name, VFXValue value, VFXVariadic variadic = VFXVariadic.False, SpaceableType space = SpaceableType.None)
  143. {
  144. this.name = name;
  145. this.value = value;
  146. this.variadic = variadic;
  147. this.space = space;
  148. if (space != SpaceableType.None && variadic != VFXVariadic.False)
  149. {
  150. throw new InvalidOperationException("Can't mix spaceable and variadic attributes : " + name);
  151. }
  152. }
  153. public static VFXAttribute Find(string attributeName)
  154. {
  155. int index = Array.FindIndex(AllAttribute, e => e.name == attributeName);
  156. if (index != -1)
  157. return AllAttribute[index];
  158. index = Array.FindIndex(AllVariadicAttribute, e => e.name == attributeName);
  159. if (index != -1)
  160. return AllVariadicAttribute[index];
  161. throw new ArgumentException(string.Format("Unable to find attribute expression : {0}", attributeName));
  162. }
  163. public static bool Exist(string attributeName)
  164. {
  165. bool exist = Array.Exists(AllAttribute, e => e.name == attributeName);
  166. if (!exist)
  167. exist = Array.Exists(AllVariadicAttribute, e => e.name == attributeName);
  168. return exist;
  169. }
  170. public string GetNameInCode(VFXAttributeLocation location)
  171. {
  172. string structName = location == VFXAttributeLocation.Source ? "sourceAttributes" : "attributes";
  173. return String.Format("{0}.{1}", structName, name);
  174. }
  175. public string name;
  176. public VFXValue value;
  177. public VFXVariadic variadic;
  178. public SpaceableType space;
  179. public VFXValueType type
  180. {
  181. get
  182. {
  183. return value.valueType;
  184. }
  185. }
  186. }
  187. struct VFXAttributeInfo
  188. {
  189. public VFXAttributeInfo(VFXAttribute attrib, VFXAttributeMode mode)
  190. {
  191. this.attrib = attrib;
  192. this.mode = mode;
  193. }
  194. public VFXAttribute attrib;
  195. public VFXAttributeMode mode;
  196. }
  197. enum VFXAttributeLocation
  198. {
  199. Current = 0,
  200. Source = 1,
  201. }
  202. enum VFXVariadic
  203. {
  204. False = 0,
  205. True = 1,
  206. BelongsToVariadic = 2
  207. }
  208. enum VariadicChannelOptions
  209. {
  210. X = 0,
  211. Y = 1,
  212. Z = 2,
  213. XY = 3,
  214. XZ = 4,
  215. YZ = 5,
  216. XYZ = 6
  217. };
  218. #pragma warning disable 0659
  219. sealed class VFXAttributeExpression : VFXExpression
  220. {
  221. public VFXAttributeExpression(VFXAttribute attribute, VFXAttributeLocation location = VFXAttributeLocation.Current) : base(Flags.PerElement)
  222. {
  223. m_attribute = attribute;
  224. m_attributeLocation = location;
  225. }
  226. public override VFXExpressionOperation operation
  227. {
  228. get
  229. {
  230. return VFXExpressionOperation.None;
  231. }
  232. }
  233. public override VFXValueType valueType
  234. {
  235. get
  236. {
  237. return m_attribute.type;
  238. }
  239. }
  240. public string attributeName
  241. {
  242. get
  243. {
  244. return m_attribute.name;
  245. }
  246. }
  247. public VFXAttributeLocation attributeLocation
  248. {
  249. get
  250. {
  251. return m_attributeLocation;
  252. }
  253. }
  254. public VFXAttribute attribute { get { return m_attribute; } }
  255. private VFXAttribute m_attribute;
  256. private VFXAttributeLocation m_attributeLocation;
  257. public override bool Equals(object obj)
  258. {
  259. if (!(obj is VFXAttributeExpression))
  260. return false;
  261. var other = (VFXAttributeExpression)obj;
  262. return valueType == other.valueType && attributeLocation == other.attributeLocation && attributeName == other.attributeName;
  263. }
  264. protected override int GetInnerHashCode()
  265. {
  266. return (attributeName.GetHashCode() * 397) ^ attributeLocation.GetHashCode();
  267. }
  268. sealed protected override VFXExpression Evaluate(VFXExpression[] constParents)
  269. {
  270. return this;
  271. }
  272. public override string GetCodeString(string[] parents)
  273. {
  274. return attribute.GetNameInCode(attributeLocation);
  275. }
  276. public override IEnumerable<VFXAttributeInfo> GetNeededAttributes()
  277. {
  278. yield return new VFXAttributeInfo(attribute, m_attributeLocation == VFXAttributeLocation.Source ? VFXAttributeMode.ReadSource : VFXAttributeMode.Read);
  279. }
  280. }
  281. sealed class VFXReadEventAttributeExpression : VFXExpression
  282. {
  283. private VFXAttribute m_attribute;
  284. private UInt32 m_elementOffset;
  285. public VFXReadEventAttributeExpression(VFXAttribute attribute, UInt32 elementOffset) : base(Flags.PerSpawn | Flags.InvalidOnGPU)
  286. {
  287. m_attribute = attribute;
  288. m_elementOffset = elementOffset;
  289. }
  290. protected override int GetInnerHashCode()
  291. {
  292. return m_attribute.name.GetHashCode();
  293. }
  294. public override bool Equals(object obj)
  295. {
  296. if (!(obj is VFXReadEventAttributeExpression))
  297. return false;
  298. var other = (VFXReadEventAttributeExpression)obj;
  299. return valueType == other.valueType && attributeName == other.attributeName && m_elementOffset == other.elementOffset;
  300. }
  301. public override IEnumerable<VFXAttributeInfo> GetNeededAttributes()
  302. {
  303. yield return new VFXAttributeInfo(m_attribute, VFXAttributeMode.Read);
  304. }
  305. private UInt32 elementOffset => m_elementOffset;
  306. public string attributeName => m_attribute.name;
  307. public override VFXValueType valueType => m_attribute.type;
  308. public override VFXExpressionOperation operation => VFXExpressionOperation.ReadEventAttribute;
  309. protected override int[] additionnalOperands => new int[] { (int)m_elementOffset, (int)m_attribute.type };
  310. }
  311. #pragma warning restore 0659
  312. }