particleHelper.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import { Nullable } from "../types";
  2. import { Scene } from "../scene";
  3. import { Tools } from "../Misc/tools";
  4. import { Vector3 } from "../Maths/math.vector";
  5. import { Color4 } from '../Maths/math.color';
  6. import { AbstractMesh } from "../Meshes/abstractMesh";
  7. import { Texture } from "../Materials/Textures/texture";
  8. import { EngineStore } from "../Engines/engineStore";
  9. import { IParticleSystem } from "./IParticleSystem";
  10. import { GPUParticleSystem } from "./gpuParticleSystem";
  11. import { ParticleSystemSet } from "./particleSystemSet";
  12. import { ParticleSystem } from "./particleSystem";
  13. import { WebRequest } from '../Misc/webRequest';
  14. /**
  15. * This class is made for on one-liner static method to help creating particle system set.
  16. */
  17. export class ParticleHelper {
  18. /**
  19. * Gets or sets base Assets URL
  20. */
  21. public static BaseAssetsUrl = ParticleSystemSet.BaseAssetsUrl;
  22. /** Define the Url to load snippets */
  23. public static SnippetUrl = "https://snippet.babylonjs.com";
  24. /**
  25. * Create a default particle system that you can tweak
  26. * @param emitter defines the emitter to use
  27. * @param capacity defines the system capacity (default is 500 particles)
  28. * @param scene defines the hosting scene
  29. * @param useGPU defines if a GPUParticleSystem must be created (default is false)
  30. * @returns the new Particle system
  31. */
  32. public static CreateDefault(emitter: Nullable<AbstractMesh | Vector3>, capacity = 500, scene?: Scene, useGPU = false): IParticleSystem {
  33. var system: IParticleSystem;
  34. if (useGPU) {
  35. system = new GPUParticleSystem("default system", { capacity: capacity }, scene!);
  36. } else {
  37. system = new ParticleSystem("default system", capacity, scene!);
  38. }
  39. system.emitter = emitter;
  40. system.particleTexture = new Texture("https://www.babylonjs.com/assets/Flare.png", system.getScene());
  41. system.createConeEmitter(0.1, Math.PI / 4);
  42. // Particle color
  43. system.color1 = new Color4(1.0, 1.0, 1.0, 1.0);
  44. system.color2 = new Color4(1.0, 1.0, 1.0, 1.0);
  45. system.colorDead = new Color4(1.0, 1.0, 1.0, 0.0);
  46. // Particle Size
  47. system.minSize = 0.1;
  48. system.maxSize = 0.1;
  49. // Emission speed
  50. system.minEmitPower = 2;
  51. system.maxEmitPower = 2;
  52. // Update speed
  53. system.updateSpeed = 1 / 60;
  54. system.emitRate = 30;
  55. return system;
  56. }
  57. /**
  58. * This is the main static method (one-liner) of this helper to create different particle systems
  59. * @param type This string represents the type to the particle system to create
  60. * @param scene The scene where the particle system should live
  61. * @param gpu If the system will use gpu
  62. * @returns the ParticleSystemSet created
  63. */
  64. public static CreateAsync(type: string, scene: Nullable<Scene>, gpu: boolean = false): Promise<ParticleSystemSet> {
  65. if (!scene) {
  66. scene = EngineStore.LastCreatedScene;
  67. }
  68. let token = {};
  69. scene!._addPendingData(token);
  70. return new Promise((resolve, reject) => {
  71. if (gpu && !GPUParticleSystem.IsSupported) {
  72. scene!._removePendingData(token);
  73. return reject("Particle system with GPU is not supported.");
  74. }
  75. Tools.LoadFile(`${ParticleHelper.BaseAssetsUrl}/systems/${type}.json`, (data) => {
  76. scene!._removePendingData(token);
  77. const newData = JSON.parse(data.toString());
  78. return resolve(ParticleSystemSet.Parse(newData, scene!, gpu));
  79. }, undefined, undefined, undefined, () => {
  80. scene!._removePendingData(token);
  81. return reject(`An error occured while the creation of your particle system. Check if your type '${type}' exists.`);
  82. });
  83. });
  84. }
  85. /**
  86. * Static function used to export a particle system to a ParticleSystemSet variable.
  87. * Please note that the emitter shape is not exported
  88. * @param systems defines the particle systems to export
  89. * @returns the created particle system set
  90. */
  91. public static ExportSet(systems: IParticleSystem[]): ParticleSystemSet {
  92. var set = new ParticleSystemSet();
  93. for (var system of systems) {
  94. set.systems.push(system);
  95. }
  96. return set;
  97. }
  98. /**
  99. * Creates a particle system from a snippet saved in a remote file
  100. * @param name defines the name of the particle system to create (can be null or empty to use the one from the json data)
  101. * @param url defines the url to load from
  102. * @param scene defines the hosting scene
  103. * @param gpu If the system will use gpu
  104. * @param rootUrl defines the root URL to use to load textures and relative dependencies
  105. * @returns a promise that will resolve to the new particle system
  106. */
  107. public static ParseFromFileAsync(name: Nullable<string>, url: string, scene: Scene, gpu: boolean = false, rootUrl: string = ""): Promise<IParticleSystem> {
  108. return new Promise((resolve, reject) => {
  109. var request = new WebRequest();
  110. request.addEventListener("readystatechange", () => {
  111. if (request.readyState == 4) {
  112. if (request.status == 200) {
  113. let serializationObject = JSON.parse(request.responseText);
  114. let output: IParticleSystem;
  115. if (gpu) {
  116. output = GPUParticleSystem.Parse(serializationObject, scene, rootUrl);
  117. } else {
  118. output = ParticleSystem.Parse(serializationObject, scene, rootUrl);
  119. }
  120. if (name) {
  121. output.name = name;
  122. }
  123. resolve(output);
  124. } else {
  125. reject("Unable to load the particle system");
  126. }
  127. }
  128. });
  129. request.open("GET", url);
  130. request.send();
  131. });
  132. }
  133. /**
  134. * Creates a particle system from a snippet saved by the particle system editor
  135. * @param snippetId defines the snippet to load (can be set to _BLANK to create a default one)
  136. * @param scene defines the hosting scene
  137. * @param gpu If the system will use gpu
  138. * @param rootUrl defines the root URL to use to load textures and relative dependencies
  139. * @returns a promise that will resolve to the new particle system
  140. */
  141. public static CreateFromSnippetAsync(snippetId: string, scene: Scene, gpu: boolean = false, rootUrl: string = ""): Promise<IParticleSystem> {
  142. if (snippetId === "_BLANK") {
  143. let system = this.CreateDefault(null);
  144. system.start();
  145. return Promise.resolve(system);
  146. }
  147. return new Promise((resolve, reject) => {
  148. var request = new WebRequest();
  149. request.addEventListener("readystatechange", () => {
  150. if (request.readyState == 4) {
  151. if (request.status == 200) {
  152. var snippet = JSON.parse(JSON.parse(request.responseText).jsonPayload);
  153. let serializationObject = JSON.parse(snippet.particleSystem);
  154. let output: IParticleSystem;
  155. if (gpu) {
  156. output = GPUParticleSystem.Parse(serializationObject, scene, rootUrl);
  157. } else {
  158. output = ParticleSystem.Parse(serializationObject, scene, rootUrl);
  159. }
  160. output.snippetId = snippetId;
  161. resolve(output);
  162. } else {
  163. reject("Unable to load the snippet " + snippetId);
  164. }
  165. }
  166. });
  167. request.open("GET", this.SnippetUrl + "/" + snippetId.replace(/#/g, "/"));
  168. request.send();
  169. });
  170. }
  171. }