babylon.assetsManager.ts 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. module BABYLON {
  2. /**
  3. * Defines the list of states available for a task inside a {BABYLON.AssetsManager}
  4. */
  5. export enum AssetTaskState {
  6. /**
  7. * Initialization
  8. */
  9. INIT,
  10. /**
  11. * Running
  12. */
  13. RUNNING,
  14. /**
  15. * Done
  16. */
  17. DONE,
  18. /**
  19. * Error
  20. */
  21. ERROR
  22. }
  23. /**
  24. * Define an abstract asset task used with a {BABYLON.AssetsManager} class to load assets into a scene
  25. */
  26. export abstract class AbstractAssetTask {
  27. /**
  28. * Callback called when the task is successful
  29. */
  30. public onSuccess: (task: any) => void;
  31. /**
  32. * Callback called when the task is not successful
  33. */
  34. public onError: (task: any, message?: string, exception?: any) => void;
  35. /**
  36. * Creates a new {BABYLON.AssetsManager}
  37. * @param name defines the name of the task
  38. */
  39. constructor(
  40. /**
  41. * Task name
  42. */public name: string) {
  43. }
  44. private _isCompleted = false;
  45. private _taskState = AssetTaskState.INIT;
  46. private _errorObject: { message?: string; exception?: any; };
  47. /**
  48. * Get if the task is completed
  49. */
  50. public get isCompleted(): boolean {
  51. return this._isCompleted;
  52. }
  53. /**
  54. * Gets the current state of the task
  55. */
  56. public get taskState(): AssetTaskState {
  57. return this._taskState;
  58. }
  59. /**
  60. * Gets the current error object (if task is in error)
  61. */
  62. public get errorObject(): { message?: string; exception?: any; } {
  63. return this._errorObject;
  64. }
  65. /**
  66. * Internal only
  67. * @hidden
  68. */
  69. public _setErrorObject(message?: string, exception?: any) {
  70. if (this._errorObject) {
  71. return;
  72. }
  73. this._errorObject = {
  74. message: message,
  75. exception: exception
  76. };
  77. }
  78. /**
  79. * Execute the current task
  80. * @param scene defines the scene where you want your assets to be loaded
  81. * @param onSuccess is a callback called when the task is successfully executed
  82. * @param onError is a callback called if an error occurs
  83. */
  84. public run(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
  85. this._taskState = AssetTaskState.RUNNING;
  86. this.runTask(scene, () => {
  87. this.onDoneCallback(onSuccess, onError);
  88. }, (msg, exception) => {
  89. this.onErrorCallback(onError, msg, exception);
  90. });
  91. }
  92. /**
  93. * Execute the current task
  94. * @param scene defines the scene where you want your assets to be loaded
  95. * @param onSuccess is a callback called when the task is successfully executed
  96. * @param onError is a callback called if an error occurs
  97. */
  98. public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
  99. throw new Error("runTask is not implemented");
  100. }
  101. /**
  102. * Reset will set the task state back to INIT, so the next load call of the assets manager will execute this task again.
  103. * This can be used with failed tasks that have the reason for failure fixed.
  104. */
  105. public reset() {
  106. this._taskState = AssetTaskState.INIT;
  107. }
  108. private onErrorCallback(onError: (message?: string, exception?: any) => void, message?: string, exception?: any) {
  109. this._taskState = AssetTaskState.ERROR;
  110. this._errorObject = {
  111. message: message,
  112. exception: exception
  113. }
  114. if (this.onError) {
  115. this.onError(this, message, exception);
  116. }
  117. onError();
  118. }
  119. private onDoneCallback(onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
  120. try {
  121. this._taskState = AssetTaskState.DONE;
  122. this._isCompleted = true;
  123. if (this.onSuccess) {
  124. this.onSuccess(this);
  125. }
  126. onSuccess();
  127. } catch (e) {
  128. this.onErrorCallback(onError, "Task is done, error executing success callback(s)", e);
  129. }
  130. }
  131. }
  132. /**
  133. * Define the interface used by progress events raised during assets loading
  134. */
  135. export interface IAssetsProgressEvent {
  136. /**
  137. * Defines the number of remaining tasks to process
  138. */
  139. remainingCount: number;
  140. /**
  141. * Defines the total number of tasks
  142. */
  143. totalCount: number;
  144. /**
  145. * Defines the task that was just processed
  146. */
  147. task: AbstractAssetTask;
  148. }
  149. /**
  150. * Class used to share progress information about assets loading
  151. */
  152. export class AssetsProgressEvent implements IAssetsProgressEvent {
  153. /**
  154. * Defines the number of remaining tasks to process
  155. */
  156. public remainingCount: number;
  157. /**
  158. * Defines the total number of tasks
  159. */
  160. public totalCount: number;
  161. /**
  162. * Defines the task that was just processed
  163. */
  164. public task: AbstractAssetTask;
  165. /**
  166. * Creates a {BABYLON.AssetsProgressEvent}
  167. * @param remainingCount defines the number of remaining tasks to process
  168. * @param totalCount defines the total number of tasks
  169. * @param task defines the task that was just processed
  170. */
  171. constructor(remainingCount: number, totalCount: number, task: AbstractAssetTask) {
  172. this.remainingCount = remainingCount;
  173. this.totalCount = totalCount;
  174. this.task = task;
  175. }
  176. }
  177. /**
  178. * Define a task used by {BABYLON.AssetsManager} to load meshes
  179. */
  180. export class MeshAssetTask extends AbstractAssetTask {
  181. /**
  182. * Gets the list of loaded meshes
  183. */
  184. public loadedMeshes: Array<AbstractMesh>;
  185. /**
  186. * Gets the list of loaded particle systems
  187. */
  188. public loadedParticleSystems: Array<ParticleSystem>;
  189. /**
  190. * Gets the list of loaded skeletons
  191. */
  192. public loadedSkeletons: Array<Skeleton>;
  193. /**
  194. * Callback called when the task is successful
  195. */
  196. public onSuccess: (task: MeshAssetTask) => void;
  197. /**
  198. * Callback called when the task is successful
  199. */
  200. public onError: (task: MeshAssetTask, message?: string, exception?: any) => void;
  201. /**
  202. * Creates a new {BABYLON.MeshAssetTask}
  203. * @param name defines the name of the task
  204. * @param meshesNames defines the list of mesh's names you want to load
  205. * @param rootUrl defines the root url to use as a base to load your meshes and associated resources
  206. * @param sceneFilename defines the filename of the scene to load from
  207. */
  208. constructor(
  209. /**
  210. * Defines the name of the task
  211. */
  212. public name: string,
  213. /**
  214. * Defines the list of mesh's names you want to load
  215. */
  216. public meshesNames: any,
  217. /**
  218. * Defines the root url to use as a base to load your meshes and associated resources
  219. */
  220. public rootUrl: string,
  221. /**
  222. * Defines the filename of the scene to load from
  223. */
  224. public sceneFilename: string) {
  225. super(name);
  226. }
  227. /**
  228. * Execute the current task
  229. * @param scene defines the scene where you want your assets to be loaded
  230. * @param onSuccess is a callback called when the task is successfully executed
  231. * @param onError is a callback called if an error occurs
  232. */
  233. public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
  234. SceneLoader.ImportMesh(this.meshesNames, this.rootUrl, this.sceneFilename, scene,
  235. (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => {
  236. this.loadedMeshes = meshes;
  237. this.loadedParticleSystems = particleSystems;
  238. this.loadedSkeletons = skeletons;
  239. onSuccess();
  240. }, null, (scene, message, exception) => {
  241. onError(message, exception);
  242. }
  243. );
  244. }
  245. }
  246. /**
  247. * Define a task used by {BABYLON.AssetsManager} to load text content
  248. */
  249. export class TextFileAssetTask extends AbstractAssetTask {
  250. /**
  251. * Gets the loaded text string
  252. */
  253. public text: string;
  254. /**
  255. * Callback called when the task is successful
  256. */
  257. public onSuccess: (task: TextFileAssetTask) => void;
  258. /**
  259. * Callback called when the task is successful
  260. */
  261. public onError: (task: TextFileAssetTask, message?: string, exception?: any) => void;
  262. /**
  263. * Creates a new TextFileAssetTask object
  264. * @param name defines the name of the task
  265. * @param url defines the location of the file to load
  266. */
  267. constructor(
  268. /**
  269. * Defines the name of the task
  270. */
  271. public name: string,
  272. /**
  273. * Defines the location of the file to load
  274. */
  275. public url: string) {
  276. super(name);
  277. }
  278. /**
  279. * Execute the current task
  280. * @param scene defines the scene where you want your assets to be loaded
  281. * @param onSuccess is a callback called when the task is successfully executed
  282. * @param onError is a callback called if an error occurs
  283. */
  284. public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
  285. scene._loadFile(this.url, (data) => {
  286. this.text = data as string;
  287. onSuccess();
  288. }, undefined, false, false, (request, exception) => {
  289. if (request) {
  290. onError(request.status + " " + request.statusText, exception);
  291. }
  292. });
  293. }
  294. }
  295. /**
  296. * Define a task used by {BABYLON.AssetsManager} to load binary data
  297. */
  298. export class BinaryFileAssetTask extends AbstractAssetTask {
  299. /**
  300. * Gets the lodaded data (as an array buffer)
  301. */
  302. public data: ArrayBuffer;
  303. /**
  304. * Callback called when the task is successful
  305. */
  306. public onSuccess: (task: BinaryFileAssetTask) => void;
  307. /**
  308. * Callback called when the task is successful
  309. */
  310. public onError: (task: BinaryFileAssetTask, message?: string, exception?: any) => void;
  311. /**
  312. * Creates a new BinaryFileAssetTask object
  313. * @param name defines the name of the new task
  314. * @param url defines the location of the file to load
  315. */
  316. constructor(
  317. /**
  318. * Defines the name of the task
  319. */
  320. public name: string,
  321. /**
  322. * Defines the location of the file to load
  323. */
  324. public url: string) {
  325. super(name);
  326. }
  327. /**
  328. * Execute the current task
  329. * @param scene defines the scene where you want your assets to be loaded
  330. * @param onSuccess is a callback called when the task is successfully executed
  331. * @param onError is a callback called if an error occurs
  332. */
  333. public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
  334. scene._loadFile(this.url, (data) => {
  335. this.data = data as ArrayBuffer;
  336. onSuccess();
  337. }, undefined, true, true, (request, exception) => {
  338. if (request) {
  339. onError(request.status + " " + request.statusText, exception);
  340. }
  341. });
  342. }
  343. }
  344. /**
  345. * Define a task used by {BABYLON.AssetsManager} to load images
  346. */
  347. export class ImageAssetTask extends AbstractAssetTask {
  348. /**
  349. * Gets the loaded images
  350. */
  351. public image: HTMLImageElement;
  352. /**
  353. * Callback called when the task is successful
  354. */
  355. public onSuccess: (task: ImageAssetTask) => void;
  356. /**
  357. * Callback called when the task is successful
  358. */
  359. public onError: (task: ImageAssetTask, message?: string, exception?: any) => void;
  360. /**
  361. * Creates a new ImageAssetTask
  362. * @param name defines the name of the task
  363. * @param url defines the location of the image to load
  364. */
  365. constructor(
  366. /**
  367. * Defines the name of the task
  368. */
  369. public name: string,
  370. /**
  371. * Defines the location of the image to load
  372. */
  373. public url: string) {
  374. super(name);
  375. }
  376. /**
  377. * Execute the current task
  378. * @param scene defines the scene where you want your assets to be loaded
  379. * @param onSuccess is a callback called when the task is successfully executed
  380. * @param onError is a callback called if an error occurs
  381. */
  382. public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
  383. var img = new Image();
  384. Tools.SetCorsBehavior(this.url, img);
  385. img.onload = () => {
  386. this.image = img;
  387. onSuccess();
  388. };
  389. img.onerror = (err: ErrorEvent): any => {
  390. onError("Error loading image", err);
  391. };
  392. img.src = this.url;
  393. }
  394. }
  395. /**
  396. * Defines the interface used by texture loading tasks
  397. */
  398. export interface ITextureAssetTask<TEX extends BaseTexture> {
  399. /**
  400. * Gets the loaded texture
  401. */
  402. texture: TEX;
  403. }
  404. /**
  405. * Define a task used by {BABYLON.AssetsManager} to load 2D textures
  406. */
  407. export class TextureAssetTask extends AbstractAssetTask implements ITextureAssetTask<Texture> {
  408. /**
  409. * Gets the loaded texture
  410. */
  411. public texture: Texture;
  412. /**
  413. * Callback called when the task is successful
  414. */
  415. public onSuccess: (task: TextureAssetTask) => void;
  416. /**
  417. * Callback called when the task is successful
  418. */
  419. public onError: (task: TextureAssetTask, message?: string, exception?: any) => void;
  420. /**
  421. * Creates a new TextureAssetTask object
  422. * @param name defines the name of the task
  423. * @param url defines the location of the file to load
  424. * @param noMipmap defines if mipmap should not be generated (default is false)
  425. * @param invertY defines if texture must be inverted on Y axis (default is false)
  426. * @param samplingMode defines the sampling mode to use (default is BABYLON.Texture.TRILINEAR_SAMPLINGMODE)
  427. */
  428. constructor(
  429. /**
  430. * Defines the name of the task
  431. */
  432. public name: string,
  433. /**
  434. * Defines the location of the file to load
  435. */
  436. public url: string,
  437. /**
  438. * Defines if mipmap should not be generated (default is false)
  439. */
  440. public noMipmap?: boolean,
  441. /**
  442. * Defines if texture must be inverted on Y axis (default is false)
  443. */
  444. public invertY?: boolean,
  445. /**
  446. * Defines the sampling mode to use (default is BABYLON.Texture.TRILINEAR_SAMPLINGMODE)
  447. */
  448. public samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
  449. super(name);
  450. }
  451. /**
  452. * Execute the current task
  453. * @param scene defines the scene where you want your assets to be loaded
  454. * @param onSuccess is a callback called when the task is successfully executed
  455. * @param onError is a callback called if an error occurs
  456. */
  457. public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
  458. var onload = () => {
  459. onSuccess();
  460. };
  461. var onerror = (message?: string, exception?: any) => {
  462. onError(message, exception);
  463. };
  464. this.texture = new Texture(this.url, scene, this.noMipmap, this.invertY, this.samplingMode, onload, onerror);
  465. }
  466. }
  467. /**
  468. * Define a task used by {BABYLON.AssetsManager} to load cube textures
  469. */
  470. export class CubeTextureAssetTask extends AbstractAssetTask implements ITextureAssetTask<CubeTexture> {
  471. /**
  472. * Gets the loaded texture
  473. */
  474. public texture: CubeTexture;
  475. /**
  476. * Callback called when the task is successful
  477. */
  478. public onSuccess: (task: CubeTextureAssetTask) => void;
  479. /**
  480. * Callback called when the task is successful
  481. */
  482. public onError: (task: CubeTextureAssetTask, message?: string, exception?: any) => void;
  483. /**
  484. * Creates a new CubeTextureAssetTask
  485. * @param name defines the name of the task
  486. * @param url defines the location of the files to load (You have to specify the folder where the files are + filename with no extension)
  487. * @param extensions defines the extensions to use to load files (["_px", "_py", "_pz", "_nx", "_ny", "_nz"] by default)
  488. * @param noMipmap defines if mipmaps should not be generated (default is false)
  489. * @param files defines the explicit list of files (undefined by default)
  490. */
  491. constructor(
  492. /**
  493. * Defines the name of the task
  494. */
  495. public name: string,
  496. /**
  497. * Defines the location of the files to load (You have to specify the folder where the files are + filename with no extension)
  498. */
  499. public url: string,
  500. /**
  501. * Defines the extensions to use to load files (["_px", "_py", "_pz", "_nx", "_ny", "_nz"] by default)
  502. */
  503. public extensions?: string[],
  504. /**
  505. * Defines if mipmaps should not be generated (default is false)
  506. */
  507. public noMipmap?: boolean,
  508. /**
  509. * Defines the explicit list of files (undefined by default)
  510. */
  511. public files?: string[]) {
  512. super(name);
  513. }
  514. /**
  515. * Execute the current task
  516. * @param scene defines the scene where you want your assets to be loaded
  517. * @param onSuccess is a callback called when the task is successfully executed
  518. * @param onError is a callback called if an error occurs
  519. */
  520. public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
  521. var onload = () => {
  522. onSuccess();
  523. };
  524. var onerror = (message?: string, exception?: any) => {
  525. onError(message, exception);
  526. };
  527. this.texture = new CubeTexture(this.url, scene, this.extensions, this.noMipmap, this.files, onload, onerror);
  528. }
  529. }
  530. /**
  531. * Define a task used by {BABYLON.AssetsManager} to load HDR cube textures
  532. */
  533. export class HDRCubeTextureAssetTask extends AbstractAssetTask implements ITextureAssetTask<HDRCubeTexture> {
  534. /**
  535. * Gets the loaded texture
  536. */
  537. public texture: HDRCubeTexture;
  538. /**
  539. * Callback called when the task is successful
  540. */
  541. public onSuccess: (task: HDRCubeTextureAssetTask) => void;
  542. /**
  543. * Callback called when the task is successful
  544. */
  545. public onError: (task: HDRCubeTextureAssetTask, message?: string, exception?: any) => void;
  546. /**
  547. * Creates a new HDRCubeTextureAssetTask object
  548. * @param name defines the name of the task
  549. * @param url defines the location of the file to load
  550. * @param size defines the desired size (the more it increases the longer the generation will be) If the size is omitted this implies you are using a preprocessed cubemap.
  551. * @param noMipmap defines if mipmaps should not be generated (default is false)
  552. * @param generateHarmonics specifies whether you want to extract the polynomial harmonics during the generation process (default is true)
  553. * @param gammaSpace specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space) (default is false)
  554. * @param reserved Internal use only
  555. */
  556. constructor(
  557. /**
  558. * Defines the name of the task
  559. */
  560. public name: string,
  561. /**
  562. * Defines the location of the file to load
  563. */
  564. public url: string,
  565. /**
  566. * Defines the desired size (the more it increases the longer the generation will be)
  567. */
  568. public size: number,
  569. /**
  570. * Defines if mipmaps should not be generated (default is false)
  571. */
  572. public noMipmap = false,
  573. /**
  574. * Specifies whether you want to extract the polynomial harmonics during the generation process (default is true)
  575. */
  576. public generateHarmonics = true,
  577. /**
  578. * Specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space) (default is false)
  579. */
  580. public gammaSpace = false,
  581. /**
  582. * Internal Use Only
  583. */
  584. public reserved = false) {
  585. super(name);
  586. }
  587. /**
  588. * Execute the current task
  589. * @param scene defines the scene where you want your assets to be loaded
  590. * @param onSuccess is a callback called when the task is successfully executed
  591. * @param onError is a callback called if an error occurs
  592. */
  593. public run(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
  594. var onload = () => {
  595. onSuccess();
  596. };
  597. var onerror = (message?: string, exception?: any) => {
  598. onError(message, exception);
  599. };
  600. this.texture = new HDRCubeTexture(this.url, scene, this.size, this.noMipmap, this.generateHarmonics, this.gammaSpace, this.reserved, onload, onerror);
  601. }
  602. }
  603. /**
  604. * This class can be used to easily import assets into a scene
  605. * @see http://doc.babylonjs.com/how_to/how_to_use_assetsmanager
  606. */
  607. export class AssetsManager {
  608. private _scene: Scene;
  609. private _isLoading = false;
  610. protected _tasks = new Array<AbstractAssetTask>();
  611. protected _waitingTasksCount = 0;
  612. protected _totalTasksCount = 0;
  613. /**
  614. * Callback called when all tasks are processed
  615. */
  616. public onFinish: (tasks: AbstractAssetTask[]) => void;
  617. /**
  618. * Callback called when a task is successful
  619. */
  620. public onTaskSuccess: (task: AbstractAssetTask) => void;
  621. /**
  622. * Callback called when a task had an error
  623. */
  624. public onTaskError: (task: AbstractAssetTask) => void;
  625. /**
  626. * Callback called when a task is done (whatever the result is)
  627. */
  628. public onProgress: (remainingCount: number, totalCount: number, task: AbstractAssetTask) => void;
  629. /**
  630. * Observable called when all tasks are processed
  631. */
  632. public onTaskSuccessObservable = new Observable<AbstractAssetTask>();
  633. /**
  634. * Observable called when a task had an error
  635. */
  636. public onTaskErrorObservable = new Observable<AbstractAssetTask>();
  637. /**
  638. * Observable called when a task is successful
  639. */
  640. public onTasksDoneObservable = new Observable<AbstractAssetTask[]>();
  641. /**
  642. * Observable called when a task is done (whatever the result is)
  643. */
  644. public onProgressObservable = new Observable<IAssetsProgressEvent>();
  645. /**
  646. * Gets or sets a boolean defining if the {BABYLON.AssetsManager} should use the default loading screen
  647. * @see http://doc.babylonjs.com/how_to/creating_a_custom_loading_screen
  648. */
  649. public useDefaultLoadingScreen = true;
  650. /**
  651. * Creates a new AssetsManager
  652. * @param scene defines the scene to work on
  653. */
  654. constructor(scene: Scene) {
  655. this._scene = scene;
  656. }
  657. /**
  658. * Add a {BABYLON.MeshAssetTask} to the list of active tasks
  659. * @param taskName defines the name of the new task
  660. * @param meshesNames defines the name of meshes to load
  661. * @param rootUrl defines the root url to use to locate files
  662. * @param sceneFilename defines the filename of the scene file
  663. * @returns a new {BABYLON.MeshAssetTask} object
  664. */
  665. public addMeshTask(taskName: string, meshesNames: any, rootUrl: string, sceneFilename: string): MeshAssetTask {
  666. var task = new MeshAssetTask(taskName, meshesNames, rootUrl, sceneFilename);
  667. this._tasks.push(task);
  668. return task;
  669. }
  670. /**
  671. * Add a {BABYLON.TextFileAssetTask} to the list of active tasks
  672. * @param taskName defines the name of the new task
  673. * @param url defines the url of the file to load
  674. * @returns a new {BABYLON.TextFileAssetTask} object
  675. */
  676. public addTextFileTask(taskName: string, url: string): TextFileAssetTask {
  677. var task = new TextFileAssetTask(taskName, url);
  678. this._tasks.push(task);
  679. return task;
  680. }
  681. /**
  682. * Add a {BABYLON.BinaryFileAssetTask} to the list of active tasks
  683. * @param taskName defines the name of the new task
  684. * @param url defines the url of the file to load
  685. * @returns a new {BABYLON.BinaryFileAssetTask} object
  686. */
  687. public addBinaryFileTask(taskName: string, url: string): BinaryFileAssetTask {
  688. var task = new BinaryFileAssetTask(taskName, url);
  689. this._tasks.push(task);
  690. return task;
  691. }
  692. /**
  693. * Add a {BABYLON.ImageAssetTask} to the list of active tasks
  694. * @param taskName defines the name of the new task
  695. * @param url defines the url of the file to load
  696. * @returns a new {BABYLON.ImageAssetTask} object
  697. */
  698. public addImageTask(taskName: string, url: string): ImageAssetTask {
  699. var task = new ImageAssetTask(taskName, url);
  700. this._tasks.push(task);
  701. return task;
  702. }
  703. /**
  704. * Add a {BABYLON.TextureAssetTask} to the list of active tasks
  705. * @param taskName defines the name of the new task
  706. * @param url defines the url of the file to load
  707. * @param noMipmap defines if the texture must not receive mipmaps (false by default)
  708. * @param invertY defines if you want to invert Y axis of the loaded texture (false by default)
  709. * @param samplingMode defines the sampling mode to use (BABYLON.Texture.TRILINEAR_SAMPLINGMODE by default)
  710. * @returns a new {BABYLON.TextureAssetTask} object
  711. */
  712. public addTextureTask(taskName: string, url: string, noMipmap?: boolean, invertY?: boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE): TextureAssetTask {
  713. var task = new TextureAssetTask(taskName, url, noMipmap, invertY, samplingMode);
  714. this._tasks.push(task);
  715. return task;
  716. }
  717. /**
  718. * Add a {BABYLON.CubeTextureAssetTask} to the list of active tasks
  719. * @param taskName defines the name of the new task
  720. * @param url defines the url of the file to load
  721. * @param extensions defines the extension to use to load the cube map (can be null)
  722. * @param noMipmap defines if the texture must not receive mipmaps (false by default)
  723. * @param files defines the list of files to load (can be null)
  724. * @returns a new {BABYLON.CubeTextureAssetTask} object
  725. */
  726. public addCubeTextureTask(taskName: string, url: string, extensions?: string[], noMipmap?: boolean, files?: string[]): CubeTextureAssetTask {
  727. var task = new CubeTextureAssetTask(taskName, url, extensions, noMipmap, files);
  728. this._tasks.push(task);
  729. return task;
  730. }
  731. /**
  732. *
  733. * Add a {BABYLON.HDRCubeTextureAssetTask} to the list of active tasks
  734. * @param taskName defines the name of the new task
  735. * @param url defines the url of the file to load
  736. * @param size defines the size you want for the cubemap (can be null)
  737. * @param noMipmap defines if the texture must not receive mipmaps (false by default)
  738. * @param generateHarmonics defines if you want to automatically generate (true by default)
  739. * @param gammaSpace specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space) (default is false)
  740. * @param reserved Internal use only
  741. * @returns a new {BABYLON.HDRCubeTextureAssetTask} object
  742. */
  743. public addHDRCubeTextureTask(taskName: string, url: string, size: number, noMipmap = false, generateHarmonics = true, gammaSpace = false, reserved = false): HDRCubeTextureAssetTask {
  744. var task = new HDRCubeTextureAssetTask(taskName, url, size, noMipmap, generateHarmonics, gammaSpace, reserved);
  745. this._tasks.push(task);
  746. return task;
  747. }
  748. /**
  749. * Remove a task from the assets manager.
  750. * @param task the task to remove
  751. */
  752. public removeTask(task: AbstractAssetTask) {
  753. let index = this._tasks.indexOf(task);
  754. if (index > -1) {
  755. this._tasks.splice(index, 1);
  756. }
  757. }
  758. private _decreaseWaitingTasksCount(task: AbstractAssetTask): void {
  759. this._waitingTasksCount--;
  760. try {
  761. if (this.onProgress) {
  762. this.onProgress(
  763. this._waitingTasksCount,
  764. this._totalTasksCount,
  765. task
  766. );
  767. }
  768. this.onProgressObservable.notifyObservers(
  769. new AssetsProgressEvent(
  770. this._waitingTasksCount,
  771. this._totalTasksCount,
  772. task
  773. )
  774. );
  775. } catch (e) {
  776. Tools.Error("Error running progress callbacks.");
  777. console.log(e);
  778. }
  779. if (this._waitingTasksCount === 0) {
  780. try {
  781. if (this.onFinish) {
  782. this.onFinish(this._tasks);
  783. }
  784. // Let's remove successfull tasks
  785. var currentTasks = this._tasks.slice();
  786. for (var task of currentTasks) {
  787. if (task.taskState === AssetTaskState.DONE) {
  788. let index = this._tasks.indexOf(task);
  789. if (index > -1) {
  790. this._tasks.splice(index, 1);
  791. }
  792. }
  793. }
  794. this.onTasksDoneObservable.notifyObservers(this._tasks);
  795. } catch (e) {
  796. Tools.Error("Error running tasks-done callbacks.");
  797. console.log(e);
  798. }
  799. this._isLoading = false;
  800. this._scene.getEngine().hideLoadingUI();
  801. }
  802. }
  803. private _runTask(task: AbstractAssetTask): void {
  804. let done = () => {
  805. try {
  806. if (this.onTaskSuccess) {
  807. this.onTaskSuccess(task);
  808. }
  809. this.onTaskSuccessObservable.notifyObservers(task);
  810. this._decreaseWaitingTasksCount(task);
  811. } catch (e) {
  812. error("Error executing task success callbacks", e);
  813. }
  814. }
  815. let error = (message?: string, exception?: any) => {
  816. task._setErrorObject(message, exception);
  817. if (this.onTaskError) {
  818. this.onTaskError(task);
  819. }
  820. this.onTaskErrorObservable.notifyObservers(task);
  821. this._decreaseWaitingTasksCount(task);
  822. }
  823. task.run(this._scene, done, error);
  824. }
  825. /**
  826. * Reset the {BABYLON.AssetsManager} and remove all tasks
  827. * @return the current instance of the {BABYLON.AssetsManager}
  828. */
  829. public reset(): AssetsManager {
  830. this._isLoading = false;
  831. this._tasks = new Array<AbstractAssetTask>();
  832. return this;
  833. }
  834. /**
  835. * Start the loading process
  836. * @return the current instance of the {BABYLON.AssetsManager}
  837. */
  838. public load(): AssetsManager {
  839. if (this._isLoading) {
  840. return this;
  841. }
  842. this._isLoading = true;
  843. this._waitingTasksCount = this._tasks.length;
  844. this._totalTasksCount = this._tasks.length;
  845. if (this._waitingTasksCount === 0) {
  846. this._isLoading = false;
  847. if (this.onFinish) {
  848. this.onFinish(this._tasks);
  849. }
  850. this.onTasksDoneObservable.notifyObservers(this._tasks);
  851. return this;
  852. }
  853. if (this.useDefaultLoadingScreen) {
  854. this._scene.getEngine().displayLoadingUI();
  855. }
  856. for (var index = 0; index < this._tasks.length; index++) {
  857. var task = this._tasks[index];
  858. if (task.taskState === AssetTaskState.INIT) {
  859. this._runTask(task);
  860. }
  861. }
  862. return this;
  863. }
  864. }
  865. }