babylon.multiMaterial.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. module BABYLON {
  2. export class MultiMaterial extends Material {
  3. private _subMaterials: Nullable<Material>[];
  4. public get subMaterials(): Nullable<Material>[] {
  5. return this._subMaterials;
  6. }
  7. public set subMaterials(value: Nullable<Material>[]) {
  8. this._subMaterials = value;
  9. this._hookArray(value);
  10. }
  11. constructor(name: string, scene: Scene) {
  12. super(name, scene, true);
  13. scene.multiMaterials.push(this);
  14. this.subMaterials = new Array<Material>();
  15. this.storeEffectOnSubMeshes = true; // multimaterial is considered like a push material
  16. }
  17. private _hookArray(array: Nullable<Material>[]): void {
  18. var oldPush = array.push;
  19. array.push = (...items: Nullable<Material>[]) => {
  20. var result = oldPush.apply(array, items);
  21. this._markAllSubMeshesAsTexturesDirty();
  22. return result;
  23. }
  24. var oldSplice = array.splice;
  25. array.splice = (index: number, deleteCount?: number) => {
  26. var deleted = oldSplice.apply(array, [index, deleteCount]);
  27. this._markAllSubMeshesAsTexturesDirty();
  28. return deleted;
  29. }
  30. }
  31. // Properties
  32. public getSubMaterial(index: number): Nullable<Material> {
  33. if (index < 0 || index >= this.subMaterials.length) {
  34. return this.getScene().defaultMaterial;
  35. }
  36. return this.subMaterials[index];
  37. }
  38. public getActiveTextures(): BaseTexture[] {
  39. return super.getActiveTextures().concat(...this.subMaterials.map(subMaterial => {
  40. if (subMaterial) {
  41. return subMaterial.getActiveTextures();
  42. } else {
  43. return [];
  44. }}));
  45. }
  46. // Methods
  47. public getClassName(): string {
  48. return "MultiMaterial";
  49. }
  50. public isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean {
  51. for (var index = 0; index < this.subMaterials.length; index++) {
  52. var subMaterial = this.subMaterials[index];
  53. if (subMaterial) {
  54. if (subMaterial.storeEffectOnSubMeshes) {
  55. if (!subMaterial.isReadyForSubMesh(mesh, subMesh, useInstances)) {
  56. return false;
  57. }
  58. continue;
  59. }
  60. if (!subMaterial.isReady(mesh)) {
  61. return false;
  62. }
  63. }
  64. }
  65. return true;
  66. }
  67. public clone(name: string, cloneChildren?: boolean): MultiMaterial {
  68. var newMultiMaterial = new MultiMaterial(name, this.getScene());
  69. for (var index = 0; index < this.subMaterials.length; index++) {
  70. var subMaterial: Nullable<Material> = null;
  71. let current = this.subMaterials[index];
  72. if (cloneChildren && current) {
  73. subMaterial = current.clone(name + "-" + current.name);
  74. } else {
  75. subMaterial = this.subMaterials[index];
  76. }
  77. newMultiMaterial.subMaterials.push(subMaterial);
  78. }
  79. return newMultiMaterial;
  80. }
  81. public serialize(): any {
  82. var serializationObject: any = {};
  83. serializationObject.name = this.name;
  84. serializationObject.id = this.id;
  85. serializationObject.tags = Tags.GetTags(this);
  86. serializationObject.materials = [];
  87. for (var matIndex = 0; matIndex < this.subMaterials.length; matIndex++) {
  88. var subMat = this.subMaterials[matIndex];
  89. if (subMat) {
  90. serializationObject.materials.push(subMat.id);
  91. } else {
  92. serializationObject.materials.push(null);
  93. }
  94. }
  95. return serializationObject;
  96. }
  97. public dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean): void {
  98. var scene = this.getScene();
  99. if (!scene) {
  100. return;
  101. }
  102. var index = scene.multiMaterials.indexOf(this);
  103. if (index >= 0) {
  104. scene.multiMaterials.splice(index, 1);
  105. }
  106. super.dispose(forceDisposeEffect, forceDisposeTextures);
  107. }
  108. }
  109. }