From 4376181f0065ba9ff7cbe5ccdaae8f7ba76f9443 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Tue, 6 Sep 2022 22:45:16 +0800
Subject: [PATCH 01/25] refactor: export gltf parsers for users

---
 packages/loader/src/gltf/index.ts        |  4 ++++
 packages/loader/src/gltf/parser/index.ts | 11 +++++++++++
 packages/loader/src/index.ts             |  4 ++--
 3 files changed, 17 insertions(+), 2 deletions(-)
 create mode 100644 packages/loader/src/gltf/index.ts
 create mode 100644 packages/loader/src/gltf/parser/index.ts

diff --git a/packages/loader/src/gltf/index.ts b/packages/loader/src/gltf/index.ts
new file mode 100644
index 0000000000..2881cd3325
--- /dev/null
+++ b/packages/loader/src/gltf/index.ts
@@ -0,0 +1,4 @@
+export { GLTFParser } from "./GLTFParser";
+export { GLTFResource } from "./GLTFResource";
+export { GLTFUtil } from "./GLTFUtil";
+export * from "./parser";
diff --git a/packages/loader/src/gltf/parser/index.ts b/packages/loader/src/gltf/parser/index.ts
new file mode 100644
index 0000000000..ed4c5b6fa7
--- /dev/null
+++ b/packages/loader/src/gltf/parser/index.ts
@@ -0,0 +1,11 @@
+export { AnimationParser as GLTFAnimationParser } from "./AnimationParser";
+export { BufferParser as GLTFBufferParser } from "./BufferParser";
+export { EntityParser as GLTFEntityParser } from "./EntityParser";
+export { MaterialParser as GLTFMaterialParser } from "./MaterialParser";
+export { MeshParser as GLTFMeshParser } from "./MeshParser";
+export { Parser } from "./Parser";
+export { SceneParser as GLTFSceneParser } from "./SceneParser";
+export { SkinParser as GLTFSkinParser } from "./SkinParser";
+export { TextureParser as GLTFTextureParser } from "./TextureParser";
+export { Validator as GLTFValidator } from "./Validator";
+
diff --git a/packages/loader/src/index.ts b/packages/loader/src/index.ts
index 4f22eccfe3..effcfa810d 100644
--- a/packages/loader/src/index.ts
+++ b/packages/loader/src/index.ts
@@ -14,6 +14,6 @@ import "./MaterialLoader";
 import "./MeshLoader";
 
 export * from "./resource-deserialize";
-export { GLTFResource } from "./gltf/GLTFResource";
+export * from "./gltf";
 export * from "./SceneLoader";
-export { parseSingleKTX } from "./compressed-texture";
\ No newline at end of file
+export { parseSingleKTX } from "./compressed-texture";

From 62d4416fb341b48f4e92fe7c72ac3e69a663d18a Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Tue, 21 Feb 2023 15:33:23 +0800
Subject: [PATCH 02/25] refactor: export relative variable

---
 packages/loader/src/gltf/extensions/index.ts | 3 +++
 packages/loader/src/gltf/index.ts            | 1 +
 packages/loader/src/gltf/parser/Parser.ts    | 2 +-
 packages/loader/src/gltf/parser/index.ts     | 4 ++--
 packages/loader/src/index.ts                 | 2 --
 5 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/packages/loader/src/gltf/extensions/index.ts b/packages/loader/src/gltf/extensions/index.ts
index a9ee9e029c..2524159a58 100644
--- a/packages/loader/src/gltf/extensions/index.ts
+++ b/packages/loader/src/gltf/extensions/index.ts
@@ -12,3 +12,6 @@ import "./KHR_mesh_quantization";
 import "./KHR_texture_basisu";
 import "./KHR_texture_transform";
 import "./OASIS_materials_remap";
+
+export { ExtensionParser as GLTFExtensionParser } from "./ExtensionParser";
+export * from "./Schema";
diff --git a/packages/loader/src/gltf/index.ts b/packages/loader/src/gltf/index.ts
index 2881cd3325..6cfa708e2e 100644
--- a/packages/loader/src/gltf/index.ts
+++ b/packages/loader/src/gltf/index.ts
@@ -2,3 +2,4 @@ export { GLTFParser } from "./GLTFParser";
 export { GLTFResource } from "./GLTFResource";
 export { GLTFUtil } from "./GLTFUtil";
 export * from "./parser";
+export * from "./extensions/index";
diff --git a/packages/loader/src/gltf/parser/Parser.ts b/packages/loader/src/gltf/parser/Parser.ts
index f838910942..2075411c00 100644
--- a/packages/loader/src/gltf/parser/Parser.ts
+++ b/packages/loader/src/gltf/parser/Parser.ts
@@ -31,7 +31,7 @@ export abstract class Parser {
     const parsers = Parser._extensionParsers[extensionName];
 
     if (parsers?.length) {
-      return parsers[0].createEngineResource(extensionSchema, context, ...extra) as T;
+      return parsers[parsers.length - 1].createEngineResource(extensionSchema, context, ...extra) as T;
     }
   }
 
diff --git a/packages/loader/src/gltf/parser/index.ts b/packages/loader/src/gltf/parser/index.ts
index ed4c5b6fa7..c5c0091078 100644
--- a/packages/loader/src/gltf/parser/index.ts
+++ b/packages/loader/src/gltf/parser/index.ts
@@ -3,9 +3,9 @@ export { BufferParser as GLTFBufferParser } from "./BufferParser";
 export { EntityParser as GLTFEntityParser } from "./EntityParser";
 export { MaterialParser as GLTFMaterialParser } from "./MaterialParser";
 export { MeshParser as GLTFMeshParser } from "./MeshParser";
-export { Parser } from "./Parser";
+export { Parser as GLTFParser, registerExtension as registerGLTFExtension } from "./Parser";
 export { SceneParser as GLTFSceneParser } from "./SceneParser";
 export { SkinParser as GLTFSkinParser } from "./SkinParser";
 export { TextureParser as GLTFTextureParser } from "./TextureParser";
 export { Validator as GLTFValidator } from "./Validator";
-
+export { ParserContext as GLTFParserContext } from "./ParserContext";
diff --git a/packages/loader/src/index.ts b/packages/loader/src/index.ts
index e82f80d729..5e593ad254 100644
--- a/packages/loader/src/index.ts
+++ b/packages/loader/src/index.ts
@@ -2,7 +2,6 @@ import "./AnimatorControllerLoader";
 import "./BufferLoader";
 import "./EnvLoader";
 import "./FontLoader";
-import "./gltf/extensions/index";
 import "./GLTFLoader";
 import "./HDRLoader";
 import "./JSONLoader";
@@ -23,4 +22,3 @@ export * from "./resource-deserialize";
 export * from "./SceneLoader";
 export type { Texture2DParams } from "./Texture2DLoader";
 export * from "./gltf";
-

From 3ec1b17968f0afcb8912ab851b8b0e55361ec389 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Tue, 21 Feb 2023 20:32:27 +0800
Subject: [PATCH 03/25] refactor: support custom material parser

---
 .../loader/src/gltf/parser/MaterialParser.ts  | 269 +++++++++---------
 packages/loader/src/gltf/parser/Parser.ts     |   6 +-
 .../loader/src/gltf/parser/SceneParser.ts     |  26 +-
 packages/loader/src/gltf/parser/Validator.ts  |   5 +-
 4 files changed, 148 insertions(+), 158 deletions(-)

diff --git a/packages/loader/src/gltf/parser/MaterialParser.ts b/packages/loader/src/gltf/parser/MaterialParser.ts
index d98340f6a0..619aa10757 100644
--- a/packages/loader/src/gltf/parser/MaterialParser.ts
+++ b/packages/loader/src/gltf/parser/MaterialParser.ts
@@ -1,7 +1,9 @@
 import {
   AssetPromise,
+  BaseMaterial,
   Logger,
   Material,
+  PBRBaseMaterial,
   PBRMaterial,
   PBRSpecularMaterial,
   RenderFace,
@@ -9,7 +11,7 @@ import {
   UnlitMaterial
 } from "@oasis-engine/core";
 import { Color } from "@oasis-engine/math";
-import { ITextureInfo, MaterialAlphaMode } from "../Schema";
+import { IMaterial, ITextureInfo, MaterialAlphaMode } from "../Schema";
 import { Parser } from "./Parser";
 import { ParserContext } from "./ParserContext";
 
@@ -24,163 +26,168 @@ export class MaterialParser extends Parser {
   }
 
   parse(context: ParserContext): AssetPromise<Material[]> {
-    const { gltf, glTFResource } = context;
-
-    const { engine, textures } = glTFResource;
+    const { gltf, glTFResource, materialsPromiseInfo } = context;
     if (!gltf.materials) return;
 
-    const materialsPromiseInfo = context.materialsPromiseInfo;
-    const materials: Material[] = [];
-
-    for (let i = 0; i < gltf.materials.length; i++) {
-      const {
-        extensions = {},
-        pbrMetallicRoughness,
-        normalTexture,
-        occlusionTexture,
-        emissiveTexture,
-        emissiveFactor,
-        alphaMode,
-        alphaCutoff,
-        doubleSided,
-        name = ""
-      } = gltf.materials[i];
-
-      const {
-        KHR_materials_unlit,
-        KHR_materials_pbrSpecularGlossiness,
-        KHR_materials_clearcoat,
-        OASIS_materials_remap
-      } = extensions;
-
-      let material: UnlitMaterial | PBRMaterial | PBRSpecularMaterial = null;
-
-      if (KHR_materials_unlit) {
-        material = <UnlitMaterial>Parser.createEngineResource("KHR_materials_unlit", KHR_materials_unlit, context);
-      } else if (KHR_materials_pbrSpecularGlossiness) {
-        material = <PBRSpecularMaterial>(
-          Parser.createEngineResource(
-            "KHR_materials_pbrSpecularGlossiness",
-            KHR_materials_pbrSpecularGlossiness,
-            context
-          )
-        );
-      } else {
-        material = new PBRMaterial(engine);
-      }
-
-      material.name = name;
-
-      if (KHR_materials_clearcoat) {
-        Parser.parseEngineResource("KHR_materials_clearcoat", KHR_materials_clearcoat, material, context);
-      }
+    const { engine } = glTFResource;
 
-      if (pbrMetallicRoughness) {
-        const { baseColorFactor, baseColorTexture, metallicFactor, roughnessFactor, metallicRoughnessTexture } =
-          pbrMetallicRoughness;
+    let promises = [];
 
-        if (baseColorFactor) {
-          material.baseColor = new Color(
-            Color.linearToGammaSpace(baseColorFactor[0]),
-            Color.linearToGammaSpace(baseColorFactor[1]),
-            Color.linearToGammaSpace(baseColorFactor[2]),
-            baseColorFactor[3]
-          );
-        }
-        if (baseColorTexture) {
-          material.baseTexture = textures[baseColorTexture.index];
-          const KHR_texture_transform = baseColorTexture.extensions?.KHR_texture_transform;
-          if (KHR_texture_transform) {
-            Parser.parseEngineResource("KHR_texture_transform", KHR_texture_transform, material, context);
+    for (let i = 0; i < gltf.materials.length; i++) {
+      const materialInfo = gltf.materials[i];
+      const { extensions = {}, name = "" } = materialInfo;
+
+      const { KHR_materials_unlit, KHR_materials_pbrSpecularGlossiness, KHR_materials_clearcoat, ...otherExtensions } =
+        extensions;
+      let material: BaseMaterial | Promise<BaseMaterial> = null;
+
+      for (let name in otherExtensions) {
+        if (Parser.hasExtensionParser(name)) {
+          material = <Promise<any>>Parser.createEngineResource(name, otherExtensions[name], context);
+          if (material) {
+            break;
           }
         }
+      }
 
-        if (!KHR_materials_unlit && !KHR_materials_pbrSpecularGlossiness) {
-          const m = material as PBRMaterial;
-          m.metallic = metallicFactor ?? 1;
-          m.roughness = roughnessFactor ?? 1;
-          if (metallicRoughnessTexture) {
-            m.roughnessMetallicTexture = textures[metallicRoughnessTexture.index];
-            MaterialParser._checkOtherTextureTransform(metallicRoughnessTexture, "Roughness metallic");
-          }
+      if (!material) {
+        if (KHR_materials_unlit) {
+          material = <UnlitMaterial>Parser.createEngineResource("KHR_materials_unlit", KHR_materials_unlit, context);
+        } else if (KHR_materials_pbrSpecularGlossiness) {
+          material = <PBRSpecularMaterial>(
+            Parser.createEngineResource(
+              "KHR_materials_pbrSpecularGlossiness",
+              KHR_materials_pbrSpecularGlossiness,
+              context
+            )
+          );
+        } else {
+          material = new PBRMaterial(engine);
         }
+        material.name = name;
+        this._parseGLTFMaterial(material, materialInfo, context);
       }
 
-      if (!KHR_materials_unlit) {
-        const m = material as PBRMaterial | PBRSpecularMaterial;
+      promises.push(material);
+    }
 
-        if (emissiveTexture) {
-          m.emissiveTexture = textures[emissiveTexture.index];
-          MaterialParser._checkOtherTextureTransform(emissiveTexture, "Emissive");
-        }
+    return AssetPromise.all(promises).then((materials) => {
+      glTFResource.materials = materials;
+      materialsPromiseInfo.resolve(materials);
+      return materialsPromiseInfo.promise;
+    });
+  }
 
-        if (emissiveFactor) {
-          m.emissiveColor = new Color(
-            Color.linearToGammaSpace(emissiveFactor[0]),
-            Color.linearToGammaSpace(emissiveFactor[1]),
-            Color.linearToGammaSpace(emissiveFactor[2])
-          );
-        }
+  private _parseGLTFMaterial(material: BaseMaterial, materialInfo: IMaterial, context: ParserContext) {
+    const { textures } = context.glTFResource;
+    const {
+      extensions = {},
+      pbrMetallicRoughness,
+      normalTexture,
+      occlusionTexture,
+      emissiveTexture,
+      emissiveFactor,
+      alphaMode,
+      alphaCutoff,
+      doubleSided
+    } = materialInfo;
+
+    const { KHR_materials_unlit, KHR_materials_pbrSpecularGlossiness, KHR_materials_clearcoat } = extensions;
+
+    if (KHR_materials_clearcoat) {
+      Parser.parseEngineResource("KHR_materials_clearcoat", KHR_materials_clearcoat, material, context);
+    }
 
-        if (normalTexture) {
-          const { index, scale } = normalTexture;
-          m.normalTexture = textures[index];
-          MaterialParser._checkOtherTextureTransform(normalTexture, "Normal");
+    if (pbrMetallicRoughness) {
+      const m = material as PBRBaseMaterial;
+      const { baseColorFactor, baseColorTexture, metallicFactor, roughnessFactor, metallicRoughnessTexture } =
+        pbrMetallicRoughness;
+
+      if (baseColorFactor) {
+        m.baseColor = new Color(
+          Color.linearToGammaSpace(baseColorFactor[0]),
+          Color.linearToGammaSpace(baseColorFactor[1]),
+          Color.linearToGammaSpace(baseColorFactor[2]),
+          baseColorFactor[3]
+        );
+      }
+      if (baseColorTexture) {
+        m.baseTexture = textures[baseColorTexture.index];
+        const KHR_texture_transform = baseColorTexture.extensions?.KHR_texture_transform;
+        if (KHR_texture_transform) {
+          Parser.parseEngineResource("KHR_texture_transform", KHR_texture_transform, material, context);
+        }
+      }
 
-          if (scale !== undefined) {
-            m.normalTextureIntensity = scale;
-          }
+      if (!KHR_materials_unlit && !KHR_materials_pbrSpecularGlossiness) {
+        const m = material as PBRMaterial;
+        m.metallic = metallicFactor ?? 1;
+        m.roughness = roughnessFactor ?? 1;
+        if (metallicRoughnessTexture) {
+          m.roughnessMetallicTexture = textures[metallicRoughnessTexture.index];
+          MaterialParser._checkOtherTextureTransform(metallicRoughnessTexture, "Roughness metallic");
         }
+      }
+    }
 
-        if (occlusionTexture) {
-          const { index, strength, texCoord } = occlusionTexture;
-          m.occlusionTexture = textures[index];
-          MaterialParser._checkOtherTextureTransform(occlusionTexture, "Occlusion");
+    if (!KHR_materials_unlit) {
+      const m = material as PBRBaseMaterial;
 
-          if (strength !== undefined) {
-            m.occlusionTextureIntensity = strength;
-          }
-          if (texCoord === TextureCoordinate.UV1) {
-            m.occlusionTextureCoord = TextureCoordinate.UV1;
-          } else if (texCoord > TextureCoordinate.UV1) {
-            Logger.warn("Occlusion texture uv coordinate must be UV0 or UV1.");
-          }
-        }
+      if (emissiveTexture) {
+        m.emissiveTexture = textures[emissiveTexture.index];
+        MaterialParser._checkOtherTextureTransform(emissiveTexture, "Emissive");
       }
 
-      if (OASIS_materials_remap) {
-        gltf.extensions = gltf.extensions ?? {};
-        gltf.extensions["OASIS_materials_remap"] = gltf.extensions["OASIS_materials_remap"] ?? {};
-        gltf.extensions["OASIS_materials_remap"][i] = Parser.createEngineResource(
-          "OASIS_materials_remap",
-          OASIS_materials_remap,
-          context
+      if (emissiveFactor) {
+        m.emissiveColor = new Color(
+          Color.linearToGammaSpace(emissiveFactor[0]),
+          Color.linearToGammaSpace(emissiveFactor[1]),
+          Color.linearToGammaSpace(emissiveFactor[2])
         );
       }
 
-      if (doubleSided) {
-        material.renderFace = RenderFace.Double;
-      } else {
-        material.renderFace = RenderFace.Front;
+      if (normalTexture) {
+        const { index, scale } = normalTexture;
+        m.normalTexture = textures[index];
+        MaterialParser._checkOtherTextureTransform(normalTexture, "Normal");
+
+        if (scale !== undefined) {
+          m.normalTextureIntensity = scale;
+        }
       }
 
-      switch (alphaMode) {
-        case MaterialAlphaMode.OPAQUE:
-          material.isTransparent = false;
-          break;
-        case MaterialAlphaMode.BLEND:
-          material.isTransparent = true;
-          break;
-        case MaterialAlphaMode.MASK:
-          material.alphaCutoff = alphaCutoff ?? 0.5;
-          break;
+      if (occlusionTexture) {
+        const { index, strength, texCoord } = occlusionTexture;
+        m.occlusionTexture = textures[index];
+        MaterialParser._checkOtherTextureTransform(occlusionTexture, "Occlusion");
+
+        if (strength !== undefined) {
+          m.occlusionTextureIntensity = strength;
+        }
+        if (texCoord === TextureCoordinate.UV1) {
+          m.occlusionTextureCoord = TextureCoordinate.UV1;
+        } else if (texCoord > TextureCoordinate.UV1) {
+          Logger.warn("Occlusion texture uv coordinate must be UV0 or UV1.");
+        }
       }
+    }
 
-      materials[i] = material;
+    if (doubleSided) {
+      material.renderFace = RenderFace.Double;
+    } else {
+      material.renderFace = RenderFace.Front;
     }
 
-    glTFResource.materials = materials;
-    materialsPromiseInfo.resolve(materials);
-    return materialsPromiseInfo.promise;
+    switch (alphaMode) {
+      case MaterialAlphaMode.OPAQUE:
+        material.isTransparent = false;
+        break;
+      case MaterialAlphaMode.BLEND:
+        material.isTransparent = true;
+        break;
+      case MaterialAlphaMode.MASK:
+        material.alphaCutoff = alphaCutoff ?? 0.5;
+        break;
+    }
   }
 }
diff --git a/packages/loader/src/gltf/parser/Parser.ts b/packages/loader/src/gltf/parser/Parser.ts
index 2075411c00..493f1d6717 100644
--- a/packages/loader/src/gltf/parser/Parser.ts
+++ b/packages/loader/src/gltf/parser/Parser.ts
@@ -22,16 +22,16 @@ export abstract class Parser {
     }
   }
 
-  static createEngineResource<T extends EngineObject>(
+  static createEngineResource(
     extensionName: string,
     extensionSchema: ExtensionSchema,
     context: ParserContext,
     ...extra
-  ): T | Promise<T> {
+  ): EngineObject | Promise<EngineObject> {
     const parsers = Parser._extensionParsers[extensionName];
 
     if (parsers?.length) {
-      return parsers[parsers.length - 1].createEngineResource(extensionSchema, context, ...extra) as T;
+      return parsers[parsers.length - 1].createEngineResource(extensionSchema, context, ...extra);
     }
   }
 
diff --git a/packages/loader/src/gltf/parser/SceneParser.ts b/packages/loader/src/gltf/parser/SceneParser.ts
index bec4fd40a9..4d808552b8 100644
--- a/packages/loader/src/gltf/parser/SceneParser.ts
+++ b/packages/loader/src/gltf/parser/SceneParser.ts
@@ -3,7 +3,6 @@ import {
   AnimatorController,
   AnimatorControllerLayer,
   AnimatorStateMachine,
-  AssetPromise,
   BlinnPhongMaterial,
   Camera,
   Engine,
@@ -36,8 +35,6 @@ export class SceneParser extends Parser {
     if (!nodes) return;
     const defaultSceneRootPromiseInfo = context.defaultSceneRootPromiseInfo;
 
-    const promises = [];
-
     for (let i = 0; i < nodes.length; i++) {
       const gltfNode = nodes[i];
       const { camera: cameraID, mesh: meshID, extensions = {} } = gltfNode;
@@ -49,7 +46,7 @@ export class SceneParser extends Parser {
       }
 
       if (meshID !== undefined) {
-        promises.push(this._createRenderer(context, gltfNode, entity));
+        this._createRenderer(context, gltfNode, entity);
       }
 
       if (KHR_lights_punctual) {
@@ -64,11 +61,7 @@ export class SceneParser extends Parser {
       this._createAnimator(context);
     }
 
-    gltf.extensions && delete gltf.extensions["OASIS_materials_remap"];
-
-    AssetPromise.all(promises)
-      .then(() => defaultSceneRootPromiseInfo.resolve(glTFResource.defaultSceneRoot))
-      .catch(defaultSceneRootPromiseInfo.reject);
+    defaultSceneRootPromiseInfo.resolve(glTFResource.defaultSceneRoot);
 
     return defaultSceneRootPromiseInfo.promise;
   }
@@ -123,7 +116,6 @@ export class SceneParser extends Parser {
     const gltfMeshPrimitives = glTFMesh.primitives;
     const blendShapeWeights = gltfNode.weights || glTFMesh.weights;
 
-    const promises = [];
     for (let i = 0; i < gltfMeshPrimitives.length; i++) {
       const mesh = meshes[meshID][i];
       let renderer: MeshRenderer | SkinnedMeshRenderer;
@@ -145,17 +137,8 @@ export class SceneParser extends Parser {
       }
 
       const materialIndex = gltfMeshPrimitives[i].material;
-      const remapMaterials = gltf.extensions && gltf.extensions["OASIS_materials_remap"];
-      if (remapMaterials && remapMaterials[materialIndex]) {
-        promises.push(
-          remapMaterials[materialIndex].then((mtl) => {
-            renderer.setMaterial(mtl);
-          })
-        );
-      } else {
-        const material = materials?.[materialIndex] || SceneParser._getDefaultMaterial(engine);
-        renderer.setMaterial(material);
-      }
+      const material = materials?.[materialIndex] || SceneParser._getDefaultMaterial(engine);
+      renderer.setMaterial(material);
 
       const { extensions = {} } = gltfMeshPrimitives[i];
       const { KHR_materials_variants } = extensions;
@@ -163,7 +146,6 @@ export class SceneParser extends Parser {
         Parser.parseEngineResource("KHR_materials_variants", KHR_materials_variants, renderer, context);
       }
     }
-    return Promise.all(promises);
   }
 
   private _createAnimator(context: ParserContext): void {
diff --git a/packages/loader/src/gltf/parser/Validator.ts b/packages/loader/src/gltf/parser/Validator.ts
index 4dc49907f2..74208673e6 100644
--- a/packages/loader/src/gltf/parser/Validator.ts
+++ b/packages/loader/src/gltf/parser/Validator.ts
@@ -18,8 +18,9 @@ export class Validator extends Parser {
     if (extensionsUsed) {
       Logger.info("extensionsUsed: ", extensionsUsed);
       for (let i = 0; i < extensionsUsed.length; i++) {
-        if (!Parser.hasExtensionParser(extensionsUsed[i])) {
-          Logger.warn(`Extension ${extensionsUsed[i]} is not implemented, you can customize this extension in gltf.`);
+        const extensionUsed = extensionsUsed[i];
+        if (!Parser.hasExtensionParser(extensionUsed)) {
+          Logger.warn(`Extension ${extensionUsed} is not implemented, you can customize this extension in gltf.`);
         }
       }
     }

From f47f0020d54641d93c18a043f61cd234c3096771 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Tue, 21 Feb 2023 20:41:45 +0800
Subject: [PATCH 04/25] refactor: export pipeline

---
 packages/loader/src/GLTFLoader.ts      | 5 +++--
 packages/loader/src/gltf/GLTFParser.ts | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/packages/loader/src/GLTFLoader.ts b/packages/loader/src/GLTFLoader.ts
index 01141543d7..acc428374c 100644
--- a/packages/loader/src/GLTFLoader.ts
+++ b/packages/loader/src/GLTFLoader.ts
@@ -7,12 +7,13 @@ import { ParserContext } from "./gltf/parser/ParserContext";
 export class GLTFLoader extends Loader<GLTFResource> {
   load(item: LoadItem, resourceManager: ResourceManager): Record<string, AssetPromise<any>> {
     const url = item.url;
+    const { keepMeshData = false, pipeline } = item.params || {};
     const context = new ParserContext(url);
     const glTFResource = new GLTFResource(resourceManager.engine, url);
     const masterPromiseInfo = context.masterPromiseInfo;
 
     context.glTFResource = glTFResource;
-    context.keepMeshData = item.params?.keepMeshData ?? false;
+    context.keepMeshData = keepMeshData;
 
     masterPromiseInfo.onCancel(() => {
       const { chainPromises } = context;
@@ -21,7 +22,7 @@ export class GLTFLoader extends Loader<GLTFResource> {
       }
     });
 
-    GLTFParser.defaultPipeline
+    (pipeline || GLTFParser.defaultPipeline)
       .parse(context)
       .then(masterPromiseInfo.resolve)
       .catch((e) => {
diff --git a/packages/loader/src/gltf/GLTFParser.ts b/packages/loader/src/gltf/GLTFParser.ts
index 18514c41b2..a85d6d41da 100644
--- a/packages/loader/src/gltf/GLTFParser.ts
+++ b/packages/loader/src/gltf/GLTFParser.ts
@@ -27,7 +27,7 @@ export class GLTFParser {
 
   private _pipes: Parser[] = [];
 
-  private constructor(pipes: (new () => Parser)[]) {
+  constructor(pipes: (new () => Parser)[]) {
     pipes.forEach((pipe: new () => Parser, index: number) => {
       this._pipes[index] = new pipe();
     });

From e9a5c8be4304dfa6ae3f52a4c554e76def4cc2e6 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Mon, 27 Feb 2023 13:42:44 +0800
Subject: [PATCH 05/25] refactor: rename

---
 packages/loader/src/GLTFLoader.ts             |  8 +--
 packages/loader/src/gltf/GLTFParser.ts        | 63 -------------------
 packages/loader/src/gltf/GLTFPipeline.ts      | 63 +++++++++++++++++++
 packages/loader/src/gltf/GLTFUtil.ts          |  4 +-
 ...ensionParser.ts => GLTFExtensionParser.ts} |  8 +--
 .../extensions/KHR_draco_mesh_compression.ts  | 12 ++--
 .../gltf/extensions/KHR_lights_punctual.ts    | 12 ++--
 .../extensions/KHR_materials_clearcoat.ts     | 20 +++---
 .../KHR_materials_pbrSpecularGlossiness.ts    | 18 +++---
 .../gltf/extensions/KHR_materials_unlit.ts    | 12 ++--
 .../gltf/extensions/KHR_materials_variants.ts | 12 ++--
 .../gltf/extensions/KHR_mesh_quantization.ts  |  8 +--
 .../gltf/extensions/KHR_texture_transform.ts  | 12 ++--
 .../gltf/extensions/OASIS_materials_remap.ts  | 12 ++--
 packages/loader/src/gltf/extensions/index.ts  |  2 +-
 packages/loader/src/gltf/index.ts             |  2 +-
 ...mationParser.ts => GLTFAnimationParser.ts} |  8 +--
 .../{BufferParser.ts => GLTFBufferParser.ts}  |  8 +--
 .../{EntityParser.ts => GLTFEntityParser.ts}  | 14 ++---
 ...aterialParser.ts => GLTFMaterialParser.ts} | 30 ++++-----
 .../{MeshParser.ts => GLTFMeshParser.ts}      | 16 ++---
 .../gltf/parser/{Parser.ts => GLTFParser.ts}  | 36 +++++------
 ...{ParserContext.ts => GLTFParserContext.ts} |  2 +-
 .../{SceneParser.ts => GLTFSceneParser.ts}    | 24 +++----
 .../{SkinParser.ts => GLTFSkinParser.ts}      |  8 +--
 ...{TextureParser.ts => GLTFTextureParser.ts} | 12 ++--
 .../parser/{Validator.ts => GLTFValidator.ts} | 14 ++---
 packages/loader/src/gltf/parser/index.ts      | 22 +++----
 28 files changed, 231 insertions(+), 231 deletions(-)
 delete mode 100644 packages/loader/src/gltf/GLTFParser.ts
 create mode 100644 packages/loader/src/gltf/GLTFPipeline.ts
 rename packages/loader/src/gltf/extensions/{ExtensionParser.ts => GLTFExtensionParser.ts} (68%)
 rename packages/loader/src/gltf/parser/{AnimationParser.ts => GLTFAnimationParser.ts} (97%)
 rename packages/loader/src/gltf/parser/{BufferParser.ts => GLTFBufferParser.ts} (83%)
 rename packages/loader/src/gltf/parser/{EntityParser.ts => GLTFEntityParser.ts} (82%)
 rename packages/loader/src/gltf/parser/{MaterialParser.ts => GLTFMaterialParser.ts} (81%)
 rename packages/loader/src/gltf/parser/{MeshParser.ts => GLTFMeshParser.ts} (97%)
 rename packages/loader/src/gltf/parser/{Parser.ts => GLTFParser.ts} (54%)
 rename packages/loader/src/gltf/parser/{ParserContext.ts => GLTFParserContext.ts} (98%)
 rename packages/loader/src/gltf/parser/{SceneParser.ts => GLTFSceneParser.ts} (86%)
 rename packages/loader/src/gltf/parser/{SkinParser.ts => GLTFSkinParser.ts} (92%)
 rename packages/loader/src/gltf/parser/{TextureParser.ts => GLTFTextureParser.ts} (90%)
 rename packages/loader/src/gltf/parser/{Validator.ts => GLTFValidator.ts} (72%)

diff --git a/packages/loader/src/GLTFLoader.ts b/packages/loader/src/GLTFLoader.ts
index acc428374c..4c674c5a4e 100644
--- a/packages/loader/src/GLTFLoader.ts
+++ b/packages/loader/src/GLTFLoader.ts
@@ -1,14 +1,14 @@
 import { AssetPromise, AssetType, Loader, LoadItem, resourceLoader, ResourceManager } from "@oasis-engine/core";
-import { GLTFParser } from "./gltf/GLTFParser";
+import { GLTFPipeline } from "./gltf/GLTFPipeline";
 import { GLTFResource } from "./gltf/GLTFResource";
-import { ParserContext } from "./gltf/parser/ParserContext";
+import { GLTFParserContext } from "./gltf/parser/GLTFParserContext";
 
 @resourceLoader(AssetType.Prefab, ["gltf", "glb"])
 export class GLTFLoader extends Loader<GLTFResource> {
   load(item: LoadItem, resourceManager: ResourceManager): Record<string, AssetPromise<any>> {
     const url = item.url;
     const { keepMeshData = false, pipeline } = item.params || {};
-    const context = new ParserContext(url);
+    const context = new GLTFParserContext(url);
     const glTFResource = new GLTFResource(resourceManager.engine, url);
     const masterPromiseInfo = context.masterPromiseInfo;
 
@@ -22,7 +22,7 @@ export class GLTFLoader extends Loader<GLTFResource> {
       }
     });
 
-    (pipeline || GLTFParser.defaultPipeline)
+    (pipeline || GLTFPipeline.defaultPipeline)
       .parse(context)
       .then(masterPromiseInfo.resolve)
       .catch((e) => {
diff --git a/packages/loader/src/gltf/GLTFParser.ts b/packages/loader/src/gltf/GLTFParser.ts
deleted file mode 100644
index a85d6d41da..0000000000
--- a/packages/loader/src/gltf/GLTFParser.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import { AssetPromise } from "@oasis-engine/core";
-import { GLTFResource } from "./GLTFResource";
-import { AnimationParser } from "./parser/AnimationParser";
-import { BufferParser } from "./parser/BufferParser";
-import { EntityParser } from "./parser/EntityParser";
-import { MaterialParser } from "./parser/MaterialParser";
-import { MeshParser } from "./parser/MeshParser";
-import { Parser } from "./parser/Parser";
-import { ParserContext } from "./parser/ParserContext";
-import { SceneParser } from "./parser/SceneParser";
-import { SkinParser } from "./parser/SkinParser";
-import { TextureParser } from "./parser/TextureParser";
-import { Validator } from "./parser/Validator";
-
-export class GLTFParser {
-  static defaultPipeline = new GLTFParser([
-    BufferParser,
-    Validator,
-    TextureParser,
-    MaterialParser,
-    MeshParser,
-    EntityParser,
-    SkinParser,
-    AnimationParser,
-    SceneParser
-  ]);
-
-  private _pipes: Parser[] = [];
-
-  constructor(pipes: (new () => Parser)[]) {
-    pipes.forEach((pipe: new () => Parser, index: number) => {
-      this._pipes[index] = new pipe();
-    });
-  }
-
-  parse(context: ParserContext): AssetPromise<GLTFResource> {
-    const glTFResource = context.glTFResource;
-    let lastPipe;
-
-    return new AssetPromise<GLTFResource>((resolve, reject) => {
-      this._pipes.forEach((parser: Parser) => {
-        if (lastPipe) {
-          lastPipe = lastPipe.then(() => {
-            return parser.parse(context);
-          });
-          if (lastPipe.cancel) {
-            context.chainPromises.push(lastPipe);
-          }
-        } else {
-          lastPipe = parser.parse(context);
-        }
-      });
-
-      if (lastPipe) {
-        lastPipe
-          .then(() => {
-            resolve(glTFResource);
-          })
-          .catch(reject);
-      }
-    });
-  }
-}
diff --git a/packages/loader/src/gltf/GLTFPipeline.ts b/packages/loader/src/gltf/GLTFPipeline.ts
new file mode 100644
index 0000000000..d947328532
--- /dev/null
+++ b/packages/loader/src/gltf/GLTFPipeline.ts
@@ -0,0 +1,63 @@
+import { AssetPromise } from "@oasis-engine/core";
+import { GLTFResource } from "./GLTFResource";
+import { GLTFAnimationParser } from "./parser/GLTFAnimationParser";
+import { GLTFBufferParser } from "./parser/GLTFBufferParser";
+import { GLTFEntityParser } from "./parser/GLTFEntityParser";
+import { GLTFMaterialParser } from "./parser/GLTFMaterialParser";
+import { GLTFMeshParser } from "./parser/GLTFMeshParser";
+import { GLTFParser } from "./parser/GLTFParser";
+import { GLTFParserContext } from "./parser/GLTFParserContext";
+import { GLTFSceneParser } from "./parser/GLTFSceneParser";
+import { GLTFSkinParser } from "./parser/GLTFSkinParser";
+import { GLTFTextureParser } from "./parser/GLTFTextureParser";
+import { GLTFValidator } from "./parser/GLTFValidator";
+
+export class GLTFPipeline {
+  static defaultPipeline = new GLTFPipeline(
+    GLTFBufferParser,
+    GLTFValidator,
+    GLTFTextureParser,
+    GLTFMaterialParser,
+    GLTFMeshParser,
+    GLTFEntityParser,
+    GLTFSkinParser,
+    GLTFAnimationParser,
+    GLTFSceneParser
+  );
+
+  private _parsers: GLTFParser[] = [];
+
+  constructor(...parsers: (new () => GLTFParser)[]) {
+    parsers.forEach((pipe: new () => GLTFParser, index: number) => {
+      this._parsers[index] = new pipe();
+    });
+  }
+
+  parse(context: GLTFParserContext): AssetPromise<GLTFResource> {
+    const glTFResource = context.glTFResource;
+    let lastParser;
+
+    return new AssetPromise<GLTFResource>((resolve, reject) => {
+      this._parsers.forEach((parser: GLTFParser) => {
+        if (lastParser) {
+          lastParser = lastParser.then(() => {
+            return parser.parse(context);
+          });
+          if (lastParser.cancel) {
+            context.chainPromises.push(lastParser);
+          }
+        } else {
+          lastParser = parser.parse(context);
+        }
+      });
+
+      if (lastParser) {
+        lastParser
+          .then(() => {
+            resolve(glTFResource);
+          })
+          .catch(reject);
+      }
+    });
+  }
+}
diff --git a/packages/loader/src/gltf/GLTFUtil.ts b/packages/loader/src/gltf/GLTFUtil.ts
index b363140396..fd976432d6 100644
--- a/packages/loader/src/gltf/GLTFUtil.ts
+++ b/packages/loader/src/gltf/GLTFUtil.ts
@@ -1,6 +1,6 @@
 import { IndexFormat, TypedArray, VertexElementFormat } from "@oasis-engine/core";
 import { Color, Vector2, Vector3, Vector4 } from "@oasis-engine/math";
-import { BufferInfo, ParserContext } from "./parser/ParserContext";
+import { BufferInfo, GLTFParserContext } from "./parser/GLTFParserContext";
 import { AccessorComponentType, AccessorType, IAccessor, IBufferView, IGLTF } from "./Schema";
 
 const charCodeOfDot = ".".charCodeAt(0);
@@ -147,7 +147,7 @@ export class GLTFUtil {
     }
   }
 
-  static getAccessorBuffer(context: ParserContext, gltf: IGLTF, accessor: IAccessor): BufferInfo {
+  static getAccessorBuffer(context: GLTFParserContext, gltf: IGLTF, accessor: IAccessor): BufferInfo {
     const { buffers } = context;
     const bufferViews = gltf.bufferViews;
 
diff --git a/packages/loader/src/gltf/extensions/ExtensionParser.ts b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
similarity index 68%
rename from packages/loader/src/gltf/extensions/ExtensionParser.ts
rename to packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
index 57358e433a..d1324b6913 100644
--- a/packages/loader/src/gltf/extensions/ExtensionParser.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
@@ -1,20 +1,20 @@
 import { EngineObject } from "@oasis-engine/core";
-import { ParserContext } from "../parser/ParserContext";
+import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { ExtensionSchema } from "./Schema";
 
-export abstract class ExtensionParser {
+export abstract class GLTFExtensionParser {
   initialize(): void {}
 
   parseEngineResource(
     schema: ExtensionSchema,
     parseResource: EngineObject,
-    context: ParserContext,
+    context: GLTFParserContext,
     ...extra
   ): void | Promise<void> {}
 
   createEngineResource(
     schema: ExtensionSchema,
-    context: ParserContext,
+    context: GLTFParserContext,
     ...extra
   ): EngineObject | Promise<EngineObject> {
     return null;
diff --git a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
index 2e5667c2f8..7c42eb0795 100644
--- a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
+++ b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
@@ -1,13 +1,13 @@
 import { DRACODecoder } from "@oasis-engine/draco";
 import { GLTFUtil } from "../GLTFUtil";
-import { registerExtension } from "../parser/Parser";
-import { ParserContext } from "../parser/ParserContext";
+import { registerGLTFExtension } from "../parser/GLTFParser";
+import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { IMeshPrimitive } from "../Schema";
-import { ExtensionParser } from "./ExtensionParser";
+import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRDracoMeshCompression } from "./Schema";
 
-@registerExtension("KHR_draco_mesh_compression")
-class KHR_draco_mesh_compression extends ExtensionParser {
+@registerGLTFExtension("KHR_draco_mesh_compression")
+class KHR_draco_mesh_compression extends GLTFExtensionParser {
   private static _decoder: DRACODecoder;
 
   initialize(): void {
@@ -16,7 +16,7 @@ class KHR_draco_mesh_compression extends ExtensionParser {
     }
   }
 
-  createEngineResource(schema: IKHRDracoMeshCompression, context: ParserContext, gltfPrimitive: IMeshPrimitive) {
+  createEngineResource(schema: IKHRDracoMeshCompression, context: GLTFParserContext, gltfPrimitive: IMeshPrimitive) {
     const { gltf, buffers } = context;
     const { bufferViews, accessors } = gltf;
     const { bufferView: bufferViewIndex, attributes: gltfAttributeMap } = schema;
diff --git a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
index 67364b0cd2..293324cbec 100644
--- a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
+++ b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
@@ -1,12 +1,12 @@
 import { DirectLight, Entity, PointLight, SpotLight } from "@oasis-engine/core";
-import { registerExtension } from "../parser/Parser";
-import { ParserContext } from "../parser/ParserContext";
-import { ExtensionParser } from "./ExtensionParser";
+import { registerGLTFExtension } from "../parser/GLTFParser";
+import { GLTFParserContext } from "../parser/GLTFParserContext";
+import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRLightsPunctual_Light } from "./Schema";
 
-@registerExtension("KHR_lights_punctual")
-class KHR_lights_punctual extends ExtensionParser {
-  parseEngineResource(schema: IKHRLightsPunctual_Light, entity: Entity, context: ParserContext): void {
+@registerGLTFExtension("KHR_lights_punctual")
+class KHR_lights_punctual extends GLTFExtensionParser {
+  parseEngineResource(schema: IKHRLightsPunctual_Light, entity: Entity, context: GLTFParserContext): void {
     const { color, intensity = 1, type, range, spot } = schema;
     const glTFResource = context.glTFResource;
     let light: DirectLight | PointLight | SpotLight;
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
index 8d1ad21f6b..548ab820f7 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
@@ -1,13 +1,13 @@
 import { PBRMaterial } from "@oasis-engine/core";
-import { MaterialParser } from "../parser/MaterialParser";
-import { registerExtension } from "../parser/Parser";
-import { ParserContext } from "../parser/ParserContext";
-import { ExtensionParser } from "./ExtensionParser";
+import { GLTFMaterialParser } from "../parser/GLTFMaterialParser";
+import { registerGLTFExtension } from "../parser/GLTFParser";
+import { GLTFParserContext } from "../parser/GLTFParserContext";
+import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialsClearcoat } from "./Schema";
 
-@registerExtension("KHR_materials_clearcoat")
-class KHR_materials_clearcoat extends ExtensionParser {
-  parseEngineResource(schema: IKHRMaterialsClearcoat, material: PBRMaterial, context: ParserContext): void {
+@registerGLTFExtension("KHR_materials_clearcoat")
+class KHR_materials_clearcoat extends GLTFExtensionParser {
+  parseEngineResource(schema: IKHRMaterialsClearcoat, material: PBRMaterial, context: GLTFParserContext): void {
     const { textures } = context.glTFResource;
     const {
       clearcoatFactor = 0,
@@ -22,15 +22,15 @@ class KHR_materials_clearcoat extends ExtensionParser {
 
     if (clearcoatTexture) {
       material.clearCoatTexture = textures[clearcoatTexture.index];
-      MaterialParser._checkOtherTextureTransform(clearcoatTexture, "Clear coat");
+      GLTFMaterialParser._checkOtherTextureTransform(clearcoatTexture, "Clear coat");
     }
     if (clearcoatRoughnessTexture) {
       material.clearCoatRoughnessTexture = textures[clearcoatRoughnessTexture.index];
-      MaterialParser._checkOtherTextureTransform(clearcoatRoughnessTexture, "Clear coat roughness");
+      GLTFMaterialParser._checkOtherTextureTransform(clearcoatRoughnessTexture, "Clear coat roughness");
     }
     if (clearcoatNormalTexture) {
       material.clearCoatNormalTexture = textures[clearcoatNormalTexture.index];
-      MaterialParser._checkOtherTextureTransform(clearcoatNormalTexture, "Clear coat normal");
+      GLTFMaterialParser._checkOtherTextureTransform(clearcoatNormalTexture, "Clear coat normal");
     }
   }
 }
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
index f339e3a6a6..5647ea6991 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
@@ -1,14 +1,14 @@
 import { PBRSpecularMaterial } from "@oasis-engine/core";
 import { Color } from "@oasis-engine/math";
-import { MaterialParser } from "../parser/MaterialParser";
-import { Parser, registerExtension } from "../parser/Parser";
-import { ParserContext } from "../parser/ParserContext";
-import { ExtensionParser } from "./ExtensionParser";
+import { GLTFMaterialParser } from "../parser/GLTFMaterialParser";
+import { GLTFParser, registerGLTFExtension } from "../parser/GLTFParser";
+import { GLTFParserContext } from "../parser/GLTFParserContext";
+import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialsPbrSpecularGlossiness } from "./Schema";
 
-@registerExtension("KHR_materials_pbrSpecularGlossiness")
-class KHR_materials_pbrSpecularGlossiness extends ExtensionParser {
-  createEngineResource(schema: IKHRMaterialsPbrSpecularGlossiness, context: ParserContext): PBRSpecularMaterial {
+@registerGLTFExtension("KHR_materials_pbrSpecularGlossiness")
+class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser {
+  createEngineResource(schema: IKHRMaterialsPbrSpecularGlossiness, context: GLTFParserContext): PBRSpecularMaterial {
     const { engine, textures } = context.glTFResource;
     const material = new PBRSpecularMaterial(engine);
     const { diffuseFactor, diffuseTexture, specularFactor, glossinessFactor, specularGlossinessTexture } = schema;
@@ -26,7 +26,7 @@ class KHR_materials_pbrSpecularGlossiness extends ExtensionParser {
       material.baseTexture = textures[diffuseTexture.index];
       const KHR_texture_transform = diffuseTexture.extensions?.KHR_texture_transform;
       if (KHR_texture_transform) {
-        Parser.parseEngineResource("KHR_texture_transform", KHR_texture_transform, material, context);
+        GLTFParser.parseEngineResource("KHR_texture_transform", KHR_texture_transform, material, context);
       }
     }
 
@@ -44,7 +44,7 @@ class KHR_materials_pbrSpecularGlossiness extends ExtensionParser {
 
     if (specularGlossinessTexture) {
       material.specularGlossinessTexture = textures[specularGlossinessTexture.index];
-      MaterialParser._checkOtherTextureTransform(specularGlossinessTexture, "Specular glossiness");
+      GLTFMaterialParser._checkOtherTextureTransform(specularGlossinessTexture, "Specular glossiness");
     }
 
     return material;
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
index f27ed6a8e8..8a7bcd1537 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
@@ -1,12 +1,12 @@
 import { UnlitMaterial } from "@oasis-engine/core";
-import { registerExtension } from "../parser/Parser";
-import { ParserContext } from "../parser/ParserContext";
-import { ExtensionParser } from "./ExtensionParser";
+import { registerGLTFExtension } from "../parser/GLTFParser";
+import { GLTFParserContext } from "../parser/GLTFParserContext";
+import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialsUnlit } from "./Schema";
 
-@registerExtension("KHR_materials_unlit")
-class KHR_materials_unlit extends ExtensionParser {
-  createEngineResource(schema: IKHRMaterialsUnlit, context: ParserContext): UnlitMaterial {
+@registerGLTFExtension("KHR_materials_unlit")
+class KHR_materials_unlit extends GLTFExtensionParser {
+  createEngineResource(schema: IKHRMaterialsUnlit, context: GLTFParserContext): UnlitMaterial {
     const { engine } = context.glTFResource;
     const material = new UnlitMaterial(engine);
 
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
index 7f542af3d2..a04b187aea 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
@@ -1,12 +1,12 @@
 import { Renderer } from "@oasis-engine/core";
-import { registerExtension } from "../parser/Parser";
-import { ParserContext } from "../parser/ParserContext";
-import { ExtensionParser } from "./ExtensionParser";
+import { registerGLTFExtension } from "../parser/GLTFParser";
+import { GLTFParserContext } from "../parser/GLTFParserContext";
+import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialVariants_Mapping } from "./Schema";
 
-@registerExtension("KHR_materials_variants")
-class KHR_materials_variants extends ExtensionParser {
-  parseEngineResource(schema: IKHRMaterialVariants_Mapping, renderer: Renderer, context: ParserContext): void {
+@registerGLTFExtension("KHR_materials_variants")
+class KHR_materials_variants extends GLTFExtensionParser {
+  parseEngineResource(schema: IKHRMaterialVariants_Mapping, renderer: Renderer, context: GLTFParserContext): void {
     const {
       gltf: {
         extensions: {
diff --git a/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts b/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts
index bf5bcbab2f..28ac4127d0 100644
--- a/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts
+++ b/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts
@@ -1,5 +1,5 @@
-import { registerExtension } from "../parser/Parser";
-import { ExtensionParser } from "./ExtensionParser";
+import { registerGLTFExtension } from "../parser/GLTFParser";
+import { GLTFExtensionParser } from "./GLTFExtensionParser";
 
-@registerExtension("KHR_mesh_quantization")
-class KHR_mesh_quantization extends ExtensionParser {}
+@registerGLTFExtension("KHR_mesh_quantization")
+class KHR_mesh_quantization extends GLTFExtensionParser {}
diff --git a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
index ec2b7facb1..6d07723859 100644
--- a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
+++ b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
@@ -1,15 +1,15 @@
 import { Logger, PBRBaseMaterial, UnlitMaterial } from "@oasis-engine/core";
-import { registerExtension } from "../parser/Parser";
-import { ParserContext } from "../parser/ParserContext";
-import { ExtensionParser } from "./ExtensionParser";
+import { registerGLTFExtension } from "../parser/GLTFParser";
+import { GLTFParserContext } from "../parser/GLTFParserContext";
+import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRTextureTransform } from "./Schema";
 
-@registerExtension("KHR_texture_transform")
-class KHR_texture_transform extends ExtensionParser {
+@registerGLTFExtension("KHR_texture_transform")
+class KHR_texture_transform extends GLTFExtensionParser {
   parseEngineResource(
     schema: IKHRTextureTransform,
     material: PBRBaseMaterial | UnlitMaterial,
-    context: ParserContext
+    context: GLTFParserContext
   ): void {
     const { offset, rotation, scale, texCoord } = schema;
 
diff --git a/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts b/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
index d653028800..923f3523d6 100644
--- a/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
+++ b/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
@@ -1,12 +1,12 @@
 import { Material } from "@oasis-engine/core";
-import { registerExtension } from "../parser/Parser";
-import { ParserContext } from "../parser/ParserContext";
-import { ExtensionParser } from "./ExtensionParser";
+import { registerGLTFExtension } from "../parser/GLTFParser";
+import { GLTFParserContext } from "../parser/GLTFParserContext";
+import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IOasisMaterialRemap } from "./Schema";
 
-@registerExtension("OASIS_materials_remap")
-class OasisMaterialsRemap extends ExtensionParser {
-  createEngineResource(schema: IOasisMaterialRemap, context: ParserContext): Promise<Material> {
+@registerGLTFExtension("OASIS_materials_remap")
+class OasisMaterialsRemap extends GLTFExtensionParser {
+  createEngineResource(schema: IOasisMaterialRemap, context: GLTFParserContext): Promise<Material> {
     const { engine } = context.glTFResource;
     // @ts-ignore
     return engine.resourceManager.getResourceByRef<Material>(schema);
diff --git a/packages/loader/src/gltf/extensions/index.ts b/packages/loader/src/gltf/extensions/index.ts
index 2524159a58..0f6461bdd5 100644
--- a/packages/loader/src/gltf/extensions/index.ts
+++ b/packages/loader/src/gltf/extensions/index.ts
@@ -13,5 +13,5 @@ import "./KHR_texture_basisu";
 import "./KHR_texture_transform";
 import "./OASIS_materials_remap";
 
-export { ExtensionParser as GLTFExtensionParser } from "./ExtensionParser";
+export { GLTFExtensionParser } from "./GLTFExtensionParser";
 export * from "./Schema";
diff --git a/packages/loader/src/gltf/index.ts b/packages/loader/src/gltf/index.ts
index 6cfa708e2e..32ab0a24f0 100644
--- a/packages/loader/src/gltf/index.ts
+++ b/packages/loader/src/gltf/index.ts
@@ -1,4 +1,4 @@
-export { GLTFParser } from "./GLTFParser";
+export { GLTFPipeline } from "./GLTFPipeline";
 export { GLTFResource } from "./GLTFResource";
 export { GLTFUtil } from "./GLTFUtil";
 export * from "./parser";
diff --git a/packages/loader/src/gltf/parser/AnimationParser.ts b/packages/loader/src/gltf/parser/GLTFAnimationParser.ts
similarity index 97%
rename from packages/loader/src/gltf/parser/AnimationParser.ts
rename to packages/loader/src/gltf/parser/GLTFAnimationParser.ts
index fa6556f674..518967491e 100644
--- a/packages/loader/src/gltf/parser/AnimationParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFAnimationParser.ts
@@ -15,11 +15,11 @@ import {
 import { Quaternion, Vector3, Vector4 } from "@oasis-engine/math";
 import { GLTFUtil } from "../GLTFUtil";
 import { AccessorType, AnimationChannelTargetPath, AnimationSamplerInterpolation, IAnimationChannel } from "../Schema";
-import { Parser } from "./Parser";
-import { ParserContext } from "./ParserContext";
+import { GLTFParser } from "./GLTFParser";
+import { GLTFParserContext } from "./GLTFParserContext";
 
-export class AnimationParser extends Parser {
-  parse(context: ParserContext): AssetPromise<AnimationClip[]> {
+export class GLTFAnimationParser extends GLTFParser {
+  parse(context: GLTFParserContext): AssetPromise<AnimationClip[]> {
     const { gltf, buffers, glTFResource } = context;
     const { entities } = glTFResource;
     const { animations, accessors } = gltf;
diff --git a/packages/loader/src/gltf/parser/BufferParser.ts b/packages/loader/src/gltf/parser/GLTFBufferParser.ts
similarity index 83%
rename from packages/loader/src/gltf/parser/BufferParser.ts
rename to packages/loader/src/gltf/parser/GLTFBufferParser.ts
index 92ceeb4cee..ebb328e5b9 100644
--- a/packages/loader/src/gltf/parser/BufferParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFBufferParser.ts
@@ -1,11 +1,11 @@
 import { AssetPromise, request } from "@oasis-engine/core";
 import { GLTFUtil } from "../GLTFUtil";
 import { IBuffer, IGLTF } from "../Schema";
-import { Parser } from "./Parser";
-import { ParserContext } from "./ParserContext";
+import { GLTFParser } from "./GLTFParser";
+import { GLTFParserContext } from "./GLTFParserContext";
 
-export class BufferParser extends Parser {
-  parse(context: ParserContext): AssetPromise<void> {
+export class GLTFBufferParser extends GLTFParser {
+  parse(context: GLTFParserContext): AssetPromise<void> {
     const glTFResource = context.glTFResource;
     const { url } = glTFResource;
 
diff --git a/packages/loader/src/gltf/parser/EntityParser.ts b/packages/loader/src/gltf/parser/GLTFEntityParser.ts
similarity index 82%
rename from packages/loader/src/gltf/parser/EntityParser.ts
rename to packages/loader/src/gltf/parser/GLTFEntityParser.ts
index cdc1ec079c..b5e9dfd6d4 100644
--- a/packages/loader/src/gltf/parser/EntityParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFEntityParser.ts
@@ -1,13 +1,13 @@
 import { Entity } from "@oasis-engine/core";
 import { GLTFResource } from "../GLTFResource";
-import { Parser } from "./Parser";
-import { ParserContext } from "./ParserContext";
+import { GLTFParser } from "./GLTFParser";
+import { GLTFParserContext } from "./GLTFParserContext";
 
-export class EntityParser extends Parser {
+export class GLTFEntityParser extends GLTFParser {
   /** @internal */
   static _defaultName: String = "_GLTF_ENTITY_";
 
-  parse(context: ParserContext): void {
+  parse(context: GLTFParserContext): void {
     const {
       glTFResource,
       gltf: { nodes }
@@ -22,7 +22,7 @@ export class EntityParser extends Parser {
     for (let i = 0; i < nodes.length; i++) {
       const gltfNode = nodes[i];
       const { matrix, translation, rotation, scale } = gltfNode;
-      const entity = new Entity(engine, gltfNode.name || `${EntityParser._defaultName}${i}`);
+      const entity = new Entity(engine, gltfNode.name || `${GLTFEntityParser._defaultName}${i}`);
 
       const { transform } = entity;
       if (matrix) {
@@ -49,7 +49,7 @@ export class EntityParser extends Parser {
     this._createSceneRoots(context, glTFResource);
   }
 
-  private _buildEntityTree(context: ParserContext, glTFResource: GLTFResource): void {
+  private _buildEntityTree(context: GLTFParserContext, glTFResource: GLTFResource): void {
     const {
       gltf: { nodes }
     } = context;
@@ -69,7 +69,7 @@ export class EntityParser extends Parser {
     }
   }
 
-  private _createSceneRoots(context: ParserContext, glTFResource: GLTFResource): void {
+  private _createSceneRoots(context: GLTFParserContext, glTFResource: GLTFResource): void {
     const { scene: sceneID = 0, scenes } = context.gltf;
     const { engine, entities } = glTFResource;
 
diff --git a/packages/loader/src/gltf/parser/MaterialParser.ts b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
similarity index 81%
rename from packages/loader/src/gltf/parser/MaterialParser.ts
rename to packages/loader/src/gltf/parser/GLTFMaterialParser.ts
index 619aa10757..be3df5a802 100644
--- a/packages/loader/src/gltf/parser/MaterialParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
@@ -12,10 +12,10 @@ import {
 } from "@oasis-engine/core";
 import { Color } from "@oasis-engine/math";
 import { IMaterial, ITextureInfo, MaterialAlphaMode } from "../Schema";
-import { Parser } from "./Parser";
-import { ParserContext } from "./ParserContext";
+import { GLTFParser } from "./GLTFParser";
+import { GLTFParserContext } from "./GLTFParserContext";
 
-export class MaterialParser extends Parser {
+export class GLTFMaterialParser extends GLTFParser {
   /**
    * @internal
    */
@@ -25,7 +25,7 @@ export class MaterialParser extends Parser {
     }
   }
 
-  parse(context: ParserContext): AssetPromise<Material[]> {
+  parse(context: GLTFParserContext): AssetPromise<Material[]> {
     const { gltf, glTFResource, materialsPromiseInfo } = context;
     if (!gltf.materials) return;
 
@@ -42,8 +42,8 @@ export class MaterialParser extends Parser {
       let material: BaseMaterial | Promise<BaseMaterial> = null;
 
       for (let name in otherExtensions) {
-        if (Parser.hasExtensionParser(name)) {
-          material = <Promise<any>>Parser.createEngineResource(name, otherExtensions[name], context);
+        if (GLTFParser.hasExtensionParser(name)) {
+          material = <Promise<any>>GLTFParser.createEngineResource(name, otherExtensions[name], context);
           if (material) {
             break;
           }
@@ -52,10 +52,10 @@ export class MaterialParser extends Parser {
 
       if (!material) {
         if (KHR_materials_unlit) {
-          material = <UnlitMaterial>Parser.createEngineResource("KHR_materials_unlit", KHR_materials_unlit, context);
+          material = <UnlitMaterial>GLTFParser.createEngineResource("KHR_materials_unlit", KHR_materials_unlit, context);
         } else if (KHR_materials_pbrSpecularGlossiness) {
           material = <PBRSpecularMaterial>(
-            Parser.createEngineResource(
+            GLTFParser.createEngineResource(
               "KHR_materials_pbrSpecularGlossiness",
               KHR_materials_pbrSpecularGlossiness,
               context
@@ -78,7 +78,7 @@ export class MaterialParser extends Parser {
     });
   }
 
-  private _parseGLTFMaterial(material: BaseMaterial, materialInfo: IMaterial, context: ParserContext) {
+  private _parseGLTFMaterial(material: BaseMaterial, materialInfo: IMaterial, context: GLTFParserContext) {
     const { textures } = context.glTFResource;
     const {
       extensions = {},
@@ -95,7 +95,7 @@ export class MaterialParser extends Parser {
     const { KHR_materials_unlit, KHR_materials_pbrSpecularGlossiness, KHR_materials_clearcoat } = extensions;
 
     if (KHR_materials_clearcoat) {
-      Parser.parseEngineResource("KHR_materials_clearcoat", KHR_materials_clearcoat, material, context);
+      GLTFParser.parseEngineResource("KHR_materials_clearcoat", KHR_materials_clearcoat, material, context);
     }
 
     if (pbrMetallicRoughness) {
@@ -115,7 +115,7 @@ export class MaterialParser extends Parser {
         m.baseTexture = textures[baseColorTexture.index];
         const KHR_texture_transform = baseColorTexture.extensions?.KHR_texture_transform;
         if (KHR_texture_transform) {
-          Parser.parseEngineResource("KHR_texture_transform", KHR_texture_transform, material, context);
+          GLTFParser.parseEngineResource("KHR_texture_transform", KHR_texture_transform, material, context);
         }
       }
 
@@ -125,7 +125,7 @@ export class MaterialParser extends Parser {
         m.roughness = roughnessFactor ?? 1;
         if (metallicRoughnessTexture) {
           m.roughnessMetallicTexture = textures[metallicRoughnessTexture.index];
-          MaterialParser._checkOtherTextureTransform(metallicRoughnessTexture, "Roughness metallic");
+          GLTFMaterialParser._checkOtherTextureTransform(metallicRoughnessTexture, "Roughness metallic");
         }
       }
     }
@@ -135,7 +135,7 @@ export class MaterialParser extends Parser {
 
       if (emissiveTexture) {
         m.emissiveTexture = textures[emissiveTexture.index];
-        MaterialParser._checkOtherTextureTransform(emissiveTexture, "Emissive");
+        GLTFMaterialParser._checkOtherTextureTransform(emissiveTexture, "Emissive");
       }
 
       if (emissiveFactor) {
@@ -149,7 +149,7 @@ export class MaterialParser extends Parser {
       if (normalTexture) {
         const { index, scale } = normalTexture;
         m.normalTexture = textures[index];
-        MaterialParser._checkOtherTextureTransform(normalTexture, "Normal");
+        GLTFMaterialParser._checkOtherTextureTransform(normalTexture, "Normal");
 
         if (scale !== undefined) {
           m.normalTextureIntensity = scale;
@@ -159,7 +159,7 @@ export class MaterialParser extends Parser {
       if (occlusionTexture) {
         const { index, strength, texCoord } = occlusionTexture;
         m.occlusionTexture = textures[index];
-        MaterialParser._checkOtherTextureTransform(occlusionTexture, "Occlusion");
+        GLTFMaterialParser._checkOtherTextureTransform(occlusionTexture, "Occlusion");
 
         if (strength !== undefined) {
           m.occlusionTextureIntensity = strength;
diff --git a/packages/loader/src/gltf/parser/MeshParser.ts b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
similarity index 97%
rename from packages/loader/src/gltf/parser/MeshParser.ts
rename to packages/loader/src/gltf/parser/GLTFMeshParser.ts
index 8795bf03f8..50304fb14a 100644
--- a/packages/loader/src/gltf/parser/MeshParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
@@ -12,13 +12,13 @@ import {
 import { Vector3 } from "@oasis-engine/math";
 import { GLTFUtil } from "../GLTFUtil";
 import { AccessorType, IGLTF, IMesh, IMeshPrimitive } from "../Schema";
-import { Parser } from "./Parser";
-import { ParserContext } from "./ParserContext";
+import { GLTFParser } from "./GLTFParser";
+import { GLTFParserContext } from "./GLTFParserContext";
 
-export class MeshParser extends Parser {
+export class GLTFMeshParser extends GLTFParser {
   private static _tempVector3 = new Vector3();
 
-  parse(context: ParserContext) {
+  parse(context: GLTFParserContext) {
     const { gltf, buffers, glTFResource } = context;
     const { engine } = glTFResource;
     if (!gltf.meshes) return;
@@ -40,7 +40,7 @@ export class MeshParser extends Parser {
 
           if (KHR_draco_mesh_compression) {
             (<Promise<EngineObject>>(
-              Parser.createEngineResource(
+              GLTFParser.createEngineResource(
                 "KHR_draco_mesh_compression",
                 KHR_draco_mesh_compression,
                 context,
@@ -115,7 +115,7 @@ export class MeshParser extends Parser {
   }
 
   private _parseMeshFromGLTFPrimitive(
-    context: ParserContext,
+    context: GLTFParserContext,
     mesh: ModelMesh,
     gltfMesh: IMesh,
     gltfPrimitive: IMeshPrimitive,
@@ -182,7 +182,7 @@ export class MeshParser extends Parser {
           min.copyFromArray(accessor.min);
           max.copyFromArray(accessor.max);
         } else {
-          const position = MeshParser._tempVector3;
+          const position = GLTFMeshParser._tempVector3;
           min.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
           max.set(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
 
@@ -274,7 +274,7 @@ export class MeshParser extends Parser {
       bounds.min.copyFromArray(accessor.min);
       bounds.max.copyFromArray(accessor.max);
     } else {
-      const position = MeshParser._tempVector3;
+      const position = GLTFMeshParser._tempVector3;
       const { min, max } = bounds;
 
       min.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
diff --git a/packages/loader/src/gltf/parser/Parser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
similarity index 54%
rename from packages/loader/src/gltf/parser/Parser.ts
rename to packages/loader/src/gltf/parser/GLTFParser.ts
index 493f1d6717..677a49ddd1 100644
--- a/packages/loader/src/gltf/parser/Parser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -1,19 +1,19 @@
 import { AnimationClip, AssetPromise, EngineObject, Material, Mesh } from "@oasis-engine/core";
-import { ExtensionParser } from "../extensions/ExtensionParser";
+import { GLTFExtensionParser } from "../extensions/GLTFExtensionParser";
 import { ExtensionSchema } from "../extensions/Schema";
-import { ParserContext } from "./ParserContext";
+import { GLTFParserContext } from "./GLTFParserContext";
 
-export abstract class Parser {
-  private static _extensionParsers: Record<string, ExtensionParser[]> = {};
+export abstract class GLTFParser {
+  private static _extensionParsers: Record<string, GLTFExtensionParser[]> = {};
 
   static parseEngineResource(
     extensionName: string,
     extensionSchema: ExtensionSchema,
     parseResource: EngineObject,
-    context: ParserContext,
+    context: GLTFParserContext,
     ...extra
   ): void {
-    const parsers = Parser._extensionParsers[extensionName];
+    const parsers = GLTFParser._extensionParsers[extensionName];
 
     if (parsers?.length) {
       for (let i = 0; i < parsers.length; i++) {
@@ -25,10 +25,10 @@ export abstract class Parser {
   static createEngineResource(
     extensionName: string,
     extensionSchema: ExtensionSchema,
-    context: ParserContext,
+    context: GLTFParserContext,
     ...extra
   ): EngineObject | Promise<EngineObject> {
-    const parsers = Parser._extensionParsers[extensionName];
+    const parsers = GLTFParser._extensionParsers[extensionName];
 
     if (parsers?.length) {
       return parsers[parsers.length - 1].createEngineResource(extensionSchema, context, ...extra);
@@ -36,12 +36,12 @@ export abstract class Parser {
   }
 
   static hasExtensionParser(extensionName: string): boolean {
-    const parsers = Parser._extensionParsers[extensionName];
+    const parsers = GLTFParser._extensionParsers[extensionName];
     return !!parsers?.length;
   }
 
   static initialize(extensionName: string) {
-    const parsers = Parser._extensionParsers[extensionName];
+    const parsers = GLTFParser._extensionParsers[extensionName];
 
     if (parsers?.length) {
       for (let i = 0; i < parsers.length; i++) {
@@ -53,24 +53,24 @@ export abstract class Parser {
   /**
    * @internal
    */
-  static _addExtensionParser(extensionName: string, extensionParser: ExtensionParser) {
-    if (!Parser._extensionParsers[extensionName]) {
-      Parser._extensionParsers[extensionName] = [];
+  static _addExtensionParser(extensionName: string, extensionParser: GLTFExtensionParser) {
+    if (!GLTFParser._extensionParsers[extensionName]) {
+      GLTFParser._extensionParsers[extensionName] = [];
     }
-    Parser._extensionParsers[extensionName].push(extensionParser);
+    GLTFParser._extensionParsers[extensionName].push(extensionParser);
   }
 
-  abstract parse(context: ParserContext): AssetPromise<any> | void | Material | AnimationClip | Mesh;
+  abstract parse(context: GLTFParserContext): AssetPromise<any> | void | Material | AnimationClip | Mesh;
 }
 
 /**
  * Declare ExtensionParser's decorator.
  * @param extensionName - Extension name
  */
-export function registerExtension(extensionName: string) {
-  return (parser: new () => ExtensionParser) => {
+export function registerGLTFExtension(extensionName: string) {
+  return (parser: new () => GLTFExtensionParser) => {
     const extensionParser = new parser();
 
-    Parser._addExtensionParser(extensionName, extensionParser);
+    GLTFParser._addExtensionParser(extensionName, extensionParser);
   };
 }
diff --git a/packages/loader/src/gltf/parser/ParserContext.ts b/packages/loader/src/gltf/parser/GLTFParserContext.ts
similarity index 98%
rename from packages/loader/src/gltf/parser/ParserContext.ts
rename to packages/loader/src/gltf/parser/GLTFParserContext.ts
index 3b8c1a4620..b3f311d810 100644
--- a/packages/loader/src/gltf/parser/ParserContext.ts
+++ b/packages/loader/src/gltf/parser/GLTFParserContext.ts
@@ -14,7 +14,7 @@ import { IGLTF } from "../Schema";
 /**
  * @internal
  */
-export class ParserContext {
+export class GLTFParserContext {
   gltf: IGLTF;
   buffers: ArrayBuffer[];
   glTFResource: GLTFResource;
diff --git a/packages/loader/src/gltf/parser/SceneParser.ts b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
similarity index 86%
rename from packages/loader/src/gltf/parser/SceneParser.ts
rename to packages/loader/src/gltf/parser/GLTFSceneParser.ts
index 4d808552b8..284642711a 100644
--- a/packages/loader/src/gltf/parser/SceneParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
@@ -13,21 +13,21 @@ import {
 import { IKHRLightsPunctual, IKHRLightsPunctual_LightNode } from "../extensions/Schema";
 import { GLTFResource } from "../GLTFResource";
 import { CameraType, ICamera, INode } from "../Schema";
-import { Parser } from "./Parser";
-import { ParserContext } from "./ParserContext";
+import { GLTFParser } from "./GLTFParser";
+import { GLTFParserContext } from "./GLTFParserContext";
 
-export class SceneParser extends Parser {
+export class GLTFSceneParser extends GLTFParser {
   private static _defaultMaterial: BlinnPhongMaterial;
 
   private static _getDefaultMaterial(engine: Engine): BlinnPhongMaterial {
-    if (!SceneParser._defaultMaterial) {
-      SceneParser._defaultMaterial = new BlinnPhongMaterial(engine);
+    if (!GLTFSceneParser._defaultMaterial) {
+      GLTFSceneParser._defaultMaterial = new BlinnPhongMaterial(engine);
     }
 
-    return SceneParser._defaultMaterial;
+    return GLTFSceneParser._defaultMaterial;
   }
 
-  parse(context: ParserContext) {
+  parse(context: GLTFParserContext) {
     const { glTFResource, gltf } = context;
     const { entities } = glTFResource;
     const { nodes, cameras: gltfCameras } = gltf;
@@ -53,7 +53,7 @@ export class SceneParser extends Parser {
         const lightIndex = KHR_lights_punctual.light;
         const lights = (gltf.extensions.KHR_lights_punctual as IKHRLightsPunctual).lights;
 
-        Parser.parseEngineResource("KHR_lights_punctual", lights[lightIndex], entity, context);
+        GLTFParser.parseEngineResource("KHR_lights_punctual", lights[lightIndex], entity, context);
       }
     }
 
@@ -106,7 +106,7 @@ export class SceneParser extends Parser {
     camera.enabled = false;
   }
 
-  private _createRenderer(context: ParserContext, gltfNode: INode, entity: Entity) {
+  private _createRenderer(context: GLTFParserContext, gltfNode: INode, entity: Entity) {
     const { glTFResource, gltf } = context;
     const { meshes: gltfMeshes } = gltf;
 
@@ -137,18 +137,18 @@ export class SceneParser extends Parser {
       }
 
       const materialIndex = gltfMeshPrimitives[i].material;
-      const material = materials?.[materialIndex] || SceneParser._getDefaultMaterial(engine);
+      const material = materials?.[materialIndex] || GLTFSceneParser._getDefaultMaterial(engine);
       renderer.setMaterial(material);
 
       const { extensions = {} } = gltfMeshPrimitives[i];
       const { KHR_materials_variants } = extensions;
       if (KHR_materials_variants) {
-        Parser.parseEngineResource("KHR_materials_variants", KHR_materials_variants, renderer, context);
+        GLTFParser.parseEngineResource("KHR_materials_variants", KHR_materials_variants, renderer, context);
       }
     }
   }
 
-  private _createAnimator(context: ParserContext): void {
+  private _createAnimator(context: GLTFParserContext): void {
     if (!context.hasSkinned && !context.glTFResource.animations) {
       return;
     }
diff --git a/packages/loader/src/gltf/parser/SkinParser.ts b/packages/loader/src/gltf/parser/GLTFSkinParser.ts
similarity index 92%
rename from packages/loader/src/gltf/parser/SkinParser.ts
rename to packages/loader/src/gltf/parser/GLTFSkinParser.ts
index 58d57d3787..ac7ad15b53 100644
--- a/packages/loader/src/gltf/parser/SkinParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFSkinParser.ts
@@ -1,11 +1,11 @@
 import { Entity, Skin } from "@oasis-engine/core";
 import { Matrix } from "@oasis-engine/math";
 import { GLTFUtil } from "../GLTFUtil";
-import { Parser } from "./Parser";
-import { ParserContext } from "./ParserContext";
+import { GLTFParser } from "./GLTFParser";
+import { GLTFParserContext } from "./GLTFParserContext";
 
-export class SkinParser extends Parser {
-  parse(context: ParserContext): void {
+export class GLTFSkinParser extends GLTFParser {
+  parse(context: GLTFParserContext): void {
     const { glTFResource, gltf, buffers } = context;
     const { entities } = glTFResource;
     const gltfSkins = gltf.skins;
diff --git a/packages/loader/src/gltf/parser/TextureParser.ts b/packages/loader/src/gltf/parser/GLTFTextureParser.ts
similarity index 90%
rename from packages/loader/src/gltf/parser/TextureParser.ts
rename to packages/loader/src/gltf/parser/GLTFTextureParser.ts
index 3c52d9d34c..6af310ce02 100644
--- a/packages/loader/src/gltf/parser/TextureParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFTextureParser.ts
@@ -1,17 +1,17 @@
 import { AssetPromise, AssetType, Texture2D, TextureFilterMode, TextureWrapMode } from "@oasis-engine/core";
 import { GLTFUtil } from "../GLTFUtil";
 import { ISampler, TextureMagFilter, TextureMinFilter, TextureWrapMode as GLTFTextureWrapMode } from "../Schema";
-import { Parser } from "./Parser";
-import { ParserContext } from "./ParserContext";
+import { GLTFParser } from "./GLTFParser";
+import { GLTFParserContext } from "./GLTFParserContext";
 
-export class TextureParser extends Parser {
+export class GLTFTextureParser extends GLTFParser {
   private static _wrapMap = {
     [GLTFTextureWrapMode.CLAMP_TO_EDGE]: TextureWrapMode.Clamp,
     [GLTFTextureWrapMode.MIRRORED_REPEAT]: TextureWrapMode.Mirror,
     [GLTFTextureWrapMode.REPEAT]: TextureWrapMode.Repeat
   };
 
-  parse(context: ParserContext): AssetPromise<Texture2D[]> {
+  parse(context: GLTFParserContext): AssetPromise<Texture2D[]> {
     const { glTFResource, gltf, buffers } = context;
     const { engine, url } = glTFResource;
 
@@ -78,11 +78,11 @@ export class TextureParser extends Parser {
     }
 
     if (wrapS) {
-      texture.wrapModeU = TextureParser._wrapMap[wrapS];
+      texture.wrapModeU = GLTFTextureParser._wrapMap[wrapS];
     }
 
     if (wrapT) {
-      texture.wrapModeV = TextureParser._wrapMap[wrapT];
+      texture.wrapModeV = GLTFTextureParser._wrapMap[wrapT];
     }
   }
 }
diff --git a/packages/loader/src/gltf/parser/Validator.ts b/packages/loader/src/gltf/parser/GLTFValidator.ts
similarity index 72%
rename from packages/loader/src/gltf/parser/Validator.ts
rename to packages/loader/src/gltf/parser/GLTFValidator.ts
index 74208673e6..47bc17f6ab 100644
--- a/packages/loader/src/gltf/parser/Validator.ts
+++ b/packages/loader/src/gltf/parser/GLTFValidator.ts
@@ -1,9 +1,9 @@
 import { Logger } from "@oasis-engine/core";
-import { Parser } from "./Parser";
-import { ParserContext } from "./ParserContext";
+import { GLTFParser } from "./GLTFParser";
+import { GLTFParserContext } from "./GLTFParserContext";
 
-export class Validator extends Parser {
-  parse(context: ParserContext): void {
+export class GLTFValidator extends GLTFParser {
+  parse(context: GLTFParserContext): void {
     const {
       asset: { version },
       extensionsUsed,
@@ -19,7 +19,7 @@ export class Validator extends Parser {
       Logger.info("extensionsUsed: ", extensionsUsed);
       for (let i = 0; i < extensionsUsed.length; i++) {
         const extensionUsed = extensionsUsed[i];
-        if (!Parser.hasExtensionParser(extensionUsed)) {
+        if (!GLTFParser.hasExtensionParser(extensionUsed)) {
           Logger.warn(`Extension ${extensionUsed} is not implemented, you can customize this extension in gltf.`);
         }
       }
@@ -30,10 +30,10 @@ export class Validator extends Parser {
       for (let i = 0; i < extensionsRequired.length; i++) {
         const extensionRequired = extensionsRequired[i];
 
-        if (!Parser.hasExtensionParser(extensionRequired)) {
+        if (!GLTFParser.hasExtensionParser(extensionRequired)) {
           Logger.error(`GLTF parser has not supported required extension ${extensionRequired}.`);
         } else {
-          Parser.initialize(extensionRequired);
+          GLTFParser.initialize(extensionRequired);
         }
       }
     }
diff --git a/packages/loader/src/gltf/parser/index.ts b/packages/loader/src/gltf/parser/index.ts
index c5c0091078..f016b6b5f9 100644
--- a/packages/loader/src/gltf/parser/index.ts
+++ b/packages/loader/src/gltf/parser/index.ts
@@ -1,11 +1,11 @@
-export { AnimationParser as GLTFAnimationParser } from "./AnimationParser";
-export { BufferParser as GLTFBufferParser } from "./BufferParser";
-export { EntityParser as GLTFEntityParser } from "./EntityParser";
-export { MaterialParser as GLTFMaterialParser } from "./MaterialParser";
-export { MeshParser as GLTFMeshParser } from "./MeshParser";
-export { Parser as GLTFParser, registerExtension as registerGLTFExtension } from "./Parser";
-export { SceneParser as GLTFSceneParser } from "./SceneParser";
-export { SkinParser as GLTFSkinParser } from "./SkinParser";
-export { TextureParser as GLTFTextureParser } from "./TextureParser";
-export { Validator as GLTFValidator } from "./Validator";
-export { ParserContext as GLTFParserContext } from "./ParserContext";
+export { GLTFAnimationParser } from "./GLTFAnimationParser";
+export { GLTFBufferParser } from "./GLTFBufferParser";
+export { GLTFEntityParser } from "./GLTFEntityParser";
+export { GLTFMaterialParser } from "./GLTFMaterialParser";
+export { GLTFMeshParser } from "./GLTFMeshParser";
+export { GLTFParser, registerGLTFExtension } from "./GLTFParser";
+export { GLTFSceneParser } from "./GLTFSceneParser";
+export { GLTFSkinParser } from "./GLTFSkinParser";
+export { GLTFTextureParser } from "./GLTFTextureParser";
+export { GLTFValidator } from "./GLTFValidator";
+export { GLTFParserContext } from "./GLTFParserContext";

From d5a892d74875db89fc11f663f09cedfef5baf828 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Mon, 27 Feb 2023 14:26:16 +0800
Subject: [PATCH 06/25] refactor: add warning

---
 packages/loader/src/gltf/parser/GLTFParser.ts | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index 677a49ddd1..ecaaf2b49d 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -1,4 +1,4 @@
-import { AnimationClip, AssetPromise, EngineObject, Material, Mesh } from "@oasis-engine/core";
+import { AnimationClip, AssetPromise, EngineObject, Logger, Material, Mesh } from "@oasis-engine/core";
 import { GLTFExtensionParser } from "../extensions/GLTFExtensionParser";
 import { ExtensionSchema } from "../extensions/Schema";
 import { GLTFParserContext } from "./GLTFParserContext";
@@ -14,11 +14,13 @@ export abstract class GLTFParser {
     ...extra
   ): void {
     const parsers = GLTFParser._extensionParsers[extensionName];
+    const length = parsers?.length;
 
-    if (parsers?.length) {
-      for (let i = 0; i < parsers.length; i++) {
-        parsers[i].parseEngineResource(extensionSchema, parseResource, context, ...extra);
+    if (length) {
+      if (length > 1) {
+        Logger.warn(`plugin:${extensionName} has been overridden`);
       }
+      parsers[length - 1].parseEngineResource(extensionSchema, parseResource, context, ...extra);
     }
   }
 
@@ -29,9 +31,13 @@ export abstract class GLTFParser {
     ...extra
   ): EngineObject | Promise<EngineObject> {
     const parsers = GLTFParser._extensionParsers[extensionName];
+    const length = parsers?.length;
 
-    if (parsers?.length) {
-      return parsers[parsers.length - 1].createEngineResource(extensionSchema, context, ...extra);
+    if (length) {
+      if (length > 1) {
+        Logger.warn(`plugin:${extensionName} has been overridden`);
+      }
+      return parsers[length - 1].createEngineResource(extensionSchema, context, ...extra);
     }
   }
 

From d825f2231817b691d903e169f9b31095d2e11846 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Mon, 27 Feb 2023 15:20:19 +0800
Subject: [PATCH 07/25] refactor: rename

---
 packages/loader/src/gltf/{Schema.ts => GLTFSchema.ts}         | 0
 packages/loader/src/gltf/GLTFUtil.ts                          | 2 +-
 packages/loader/src/gltf/extensions/GLTFExtensionParser.ts    | 2 +-
 .../src/gltf/extensions/{Schema.ts => GLTFExtensionSchema.ts} | 2 +-
 .../loader/src/gltf/extensions/KHR_draco_mesh_compression.ts  | 4 ++--
 packages/loader/src/gltf/extensions/KHR_lights_punctual.ts    | 2 +-
 .../loader/src/gltf/extensions/KHR_materials_clearcoat.ts     | 2 +-
 .../gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts    | 2 +-
 packages/loader/src/gltf/extensions/KHR_materials_unlit.ts    | 2 +-
 packages/loader/src/gltf/extensions/KHR_materials_variants.ts | 2 +-
 packages/loader/src/gltf/extensions/KHR_texture_transform.ts  | 2 +-
 packages/loader/src/gltf/extensions/OASIS_materials_remap.ts  | 2 +-
 packages/loader/src/gltf/extensions/index.ts                  | 2 +-
 packages/loader/src/gltf/parser/GLTFAnimationParser.ts        | 2 +-
 packages/loader/src/gltf/parser/GLTFBufferParser.ts           | 2 +-
 packages/loader/src/gltf/parser/GLTFMaterialParser.ts         | 2 +-
 packages/loader/src/gltf/parser/GLTFMeshParser.ts             | 2 +-
 packages/loader/src/gltf/parser/GLTFParser.ts                 | 2 +-
 packages/loader/src/gltf/parser/GLTFParserContext.ts          | 2 +-
 packages/loader/src/gltf/parser/GLTFSceneParser.ts            | 4 ++--
 packages/loader/src/gltf/parser/GLTFTextureParser.ts          | 2 +-
 21 files changed, 22 insertions(+), 22 deletions(-)
 rename packages/loader/src/gltf/{Schema.ts => GLTFSchema.ts} (100%)
 rename packages/loader/src/gltf/extensions/{Schema.ts => GLTFExtensionSchema.ts} (98%)

diff --git a/packages/loader/src/gltf/Schema.ts b/packages/loader/src/gltf/GLTFSchema.ts
similarity index 100%
rename from packages/loader/src/gltf/Schema.ts
rename to packages/loader/src/gltf/GLTFSchema.ts
diff --git a/packages/loader/src/gltf/GLTFUtil.ts b/packages/loader/src/gltf/GLTFUtil.ts
index fd976432d6..9ed0683d66 100644
--- a/packages/loader/src/gltf/GLTFUtil.ts
+++ b/packages/loader/src/gltf/GLTFUtil.ts
@@ -1,7 +1,7 @@
 import { IndexFormat, TypedArray, VertexElementFormat } from "@oasis-engine/core";
 import { Color, Vector2, Vector3, Vector4 } from "@oasis-engine/math";
 import { BufferInfo, GLTFParserContext } from "./parser/GLTFParserContext";
-import { AccessorComponentType, AccessorType, IAccessor, IBufferView, IGLTF } from "./Schema";
+import { AccessorComponentType, AccessorType, IAccessor, IBufferView, IGLTF } from "./GLTFSchema";
 
 const charCodeOfDot = ".".charCodeAt(0);
 const reEscapeChar = /\\(\\)?/g;
diff --git a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
index d1324b6913..536659c624 100644
--- a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
@@ -1,6 +1,6 @@
 import { EngineObject } from "@oasis-engine/core";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
-import { ExtensionSchema } from "./Schema";
+import { ExtensionSchema } from "./GLTFExtensionSchema";
 
 export abstract class GLTFExtensionParser {
   initialize(): void {}
diff --git a/packages/loader/src/gltf/extensions/Schema.ts b/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts
similarity index 98%
rename from packages/loader/src/gltf/extensions/Schema.ts
rename to packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts
index 53793d5462..bb73b0ad43 100644
--- a/packages/loader/src/gltf/extensions/Schema.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts
@@ -1,4 +1,4 @@
-import { IMaterialNormalTextureInfo, ITextureInfo } from "../Schema";
+import { IMaterialNormalTextureInfo, ITextureInfo } from "../GLTFSchema";
 
 /**
  * Interfaces from the KHR_lights_punctual extension
diff --git a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
index 7c42eb0795..139fc5209c 100644
--- a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
+++ b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
@@ -2,9 +2,9 @@ import { DRACODecoder } from "@oasis-engine/draco";
 import { GLTFUtil } from "../GLTFUtil";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
-import { IMeshPrimitive } from "../Schema";
+import { IMeshPrimitive } from "../GLTFSchema";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
-import { IKHRDracoMeshCompression } from "./Schema";
+import { IKHRDracoMeshCompression } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_draco_mesh_compression")
 class KHR_draco_mesh_compression extends GLTFExtensionParser {
diff --git a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
index 293324cbec..f012805e3f 100644
--- a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
+++ b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
@@ -2,7 +2,7 @@ import { DirectLight, Entity, PointLight, SpotLight } from "@oasis-engine/core";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
-import { IKHRLightsPunctual_Light } from "./Schema";
+import { IKHRLightsPunctual_Light } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_lights_punctual")
 class KHR_lights_punctual extends GLTFExtensionParser {
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
index 548ab820f7..508b31597f 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
@@ -3,7 +3,7 @@ import { GLTFMaterialParser } from "../parser/GLTFMaterialParser";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
-import { IKHRMaterialsClearcoat } from "./Schema";
+import { IKHRMaterialsClearcoat } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_clearcoat")
 class KHR_materials_clearcoat extends GLTFExtensionParser {
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
index 5647ea6991..9631d6ddba 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
@@ -4,7 +4,7 @@ import { GLTFMaterialParser } from "../parser/GLTFMaterialParser";
 import { GLTFParser, registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
-import { IKHRMaterialsPbrSpecularGlossiness } from "./Schema";
+import { IKHRMaterialsPbrSpecularGlossiness } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_pbrSpecularGlossiness")
 class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser {
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
index 8a7bcd1537..98ba806b17 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
@@ -2,7 +2,7 @@ import { UnlitMaterial } from "@oasis-engine/core";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
-import { IKHRMaterialsUnlit } from "./Schema";
+import { IKHRMaterialsUnlit } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_unlit")
 class KHR_materials_unlit extends GLTFExtensionParser {
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
index a04b187aea..c5b3982c9a 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
@@ -2,7 +2,7 @@ import { Renderer } from "@oasis-engine/core";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
-import { IKHRMaterialVariants_Mapping } from "./Schema";
+import { IKHRMaterialVariants_Mapping } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_variants")
 class KHR_materials_variants extends GLTFExtensionParser {
diff --git a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
index 6d07723859..83de2abb2c 100644
--- a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
+++ b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
@@ -2,7 +2,7 @@ import { Logger, PBRBaseMaterial, UnlitMaterial } from "@oasis-engine/core";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
-import { IKHRTextureTransform } from "./Schema";
+import { IKHRTextureTransform } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_texture_transform")
 class KHR_texture_transform extends GLTFExtensionParser {
diff --git a/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts b/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
index 923f3523d6..3b4251755c 100644
--- a/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
+++ b/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
@@ -2,7 +2,7 @@ import { Material } from "@oasis-engine/core";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
-import { IOasisMaterialRemap } from "./Schema";
+import { IOasisMaterialRemap } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("OASIS_materials_remap")
 class OasisMaterialsRemap extends GLTFExtensionParser {
diff --git a/packages/loader/src/gltf/extensions/index.ts b/packages/loader/src/gltf/extensions/index.ts
index 0f6461bdd5..cd43cfac78 100644
--- a/packages/loader/src/gltf/extensions/index.ts
+++ b/packages/loader/src/gltf/extensions/index.ts
@@ -14,4 +14,4 @@ import "./KHR_texture_transform";
 import "./OASIS_materials_remap";
 
 export { GLTFExtensionParser } from "./GLTFExtensionParser";
-export * from "./Schema";
+export * from "./GLTFExtensionSchema";
diff --git a/packages/loader/src/gltf/parser/GLTFAnimationParser.ts b/packages/loader/src/gltf/parser/GLTFAnimationParser.ts
index 518967491e..00e94930d9 100644
--- a/packages/loader/src/gltf/parser/GLTFAnimationParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFAnimationParser.ts
@@ -14,7 +14,7 @@ import {
 } from "@oasis-engine/core";
 import { Quaternion, Vector3, Vector4 } from "@oasis-engine/math";
 import { GLTFUtil } from "../GLTFUtil";
-import { AccessorType, AnimationChannelTargetPath, AnimationSamplerInterpolation, IAnimationChannel } from "../Schema";
+import { AccessorType, AnimationChannelTargetPath, AnimationSamplerInterpolation, IAnimationChannel } from "../GLTFSchema";
 import { GLTFParser } from "./GLTFParser";
 import { GLTFParserContext } from "./GLTFParserContext";
 
diff --git a/packages/loader/src/gltf/parser/GLTFBufferParser.ts b/packages/loader/src/gltf/parser/GLTFBufferParser.ts
index ebb328e5b9..a92a6fdf2e 100644
--- a/packages/loader/src/gltf/parser/GLTFBufferParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFBufferParser.ts
@@ -1,6 +1,6 @@
 import { AssetPromise, request } from "@oasis-engine/core";
 import { GLTFUtil } from "../GLTFUtil";
-import { IBuffer, IGLTF } from "../Schema";
+import { IBuffer, IGLTF } from "../GLTFSchema";
 import { GLTFParser } from "./GLTFParser";
 import { GLTFParserContext } from "./GLTFParserContext";
 
diff --git a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
index be3df5a802..ba95898cf7 100644
--- a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
@@ -11,7 +11,7 @@ import {
   UnlitMaterial
 } from "@oasis-engine/core";
 import { Color } from "@oasis-engine/math";
-import { IMaterial, ITextureInfo, MaterialAlphaMode } from "../Schema";
+import { IMaterial, ITextureInfo, MaterialAlphaMode } from "../GLTFSchema";
 import { GLTFParser } from "./GLTFParser";
 import { GLTFParserContext } from "./GLTFParserContext";
 
diff --git a/packages/loader/src/gltf/parser/GLTFMeshParser.ts b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
index 50304fb14a..fbebf87799 100644
--- a/packages/loader/src/gltf/parser/GLTFMeshParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
@@ -11,7 +11,7 @@ import {
 } from "@oasis-engine/core";
 import { Vector3 } from "@oasis-engine/math";
 import { GLTFUtil } from "../GLTFUtil";
-import { AccessorType, IGLTF, IMesh, IMeshPrimitive } from "../Schema";
+import { AccessorType, IGLTF, IMesh, IMeshPrimitive } from "../GLTFSchema";
 import { GLTFParser } from "./GLTFParser";
 import { GLTFParserContext } from "./GLTFParserContext";
 
diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index ecaaf2b49d..7a7cdb71fd 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -1,6 +1,6 @@
 import { AnimationClip, AssetPromise, EngineObject, Logger, Material, Mesh } from "@oasis-engine/core";
 import { GLTFExtensionParser } from "../extensions/GLTFExtensionParser";
-import { ExtensionSchema } from "../extensions/Schema";
+import { ExtensionSchema } from "../extensions/GLTFExtensionSchema";
 import { GLTFParserContext } from "./GLTFParserContext";
 
 export abstract class GLTFParser {
diff --git a/packages/loader/src/gltf/parser/GLTFParserContext.ts b/packages/loader/src/gltf/parser/GLTFParserContext.ts
index b3f311d810..8159b4374c 100644
--- a/packages/loader/src/gltf/parser/GLTFParserContext.ts
+++ b/packages/loader/src/gltf/parser/GLTFParserContext.ts
@@ -9,7 +9,7 @@ import {
   TypedArray
 } from "@oasis-engine/core";
 import { GLTFResource } from "../GLTFResource";
-import { IGLTF } from "../Schema";
+import { IGLTF } from "../GLTFSchema";
 
 /**
  * @internal
diff --git a/packages/loader/src/gltf/parser/GLTFSceneParser.ts b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
index 284642711a..e394774c64 100644
--- a/packages/loader/src/gltf/parser/GLTFSceneParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
@@ -10,9 +10,9 @@ import {
   MeshRenderer,
   SkinnedMeshRenderer
 } from "@oasis-engine/core";
-import { IKHRLightsPunctual, IKHRLightsPunctual_LightNode } from "../extensions/Schema";
+import { IKHRLightsPunctual, IKHRLightsPunctual_LightNode } from "../extensions/GLTFExtensionSchema";
 import { GLTFResource } from "../GLTFResource";
-import { CameraType, ICamera, INode } from "../Schema";
+import { CameraType, ICamera, INode } from "../GLTFSchema";
 import { GLTFParser } from "./GLTFParser";
 import { GLTFParserContext } from "./GLTFParserContext";
 
diff --git a/packages/loader/src/gltf/parser/GLTFTextureParser.ts b/packages/loader/src/gltf/parser/GLTFTextureParser.ts
index 6af310ce02..543f8e4d0e 100644
--- a/packages/loader/src/gltf/parser/GLTFTextureParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFTextureParser.ts
@@ -1,6 +1,6 @@
 import { AssetPromise, AssetType, Texture2D, TextureFilterMode, TextureWrapMode } from "@oasis-engine/core";
 import { GLTFUtil } from "../GLTFUtil";
-import { ISampler, TextureMagFilter, TextureMinFilter, TextureWrapMode as GLTFTextureWrapMode } from "../Schema";
+import { ISampler, TextureMagFilter, TextureMinFilter, TextureWrapMode as GLTFTextureWrapMode } from "../GLTFSchema";
 import { GLTFParser } from "./GLTFParser";
 import { GLTFParserContext } from "./GLTFParserContext";
 

From ef8e1dd23fb46ecdd56bd43be5199511bf197865 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Mon, 27 Feb 2023 15:22:33 +0800
Subject: [PATCH 08/25] refactor: rename

---
 packages/loader/src/gltf/extensions/GLTFExtensionParser.ts | 6 +++---
 packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts | 2 +-
 packages/loader/src/gltf/parser/GLTFParser.ts              | 6 +++---
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
index 536659c624..27b7d6c971 100644
--- a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
@@ -1,19 +1,19 @@
 import { EngineObject } from "@oasis-engine/core";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
-import { ExtensionSchema } from "./GLTFExtensionSchema";
+import { GLTFExtensionSchema } from "./GLTFExtensionSchema";
 
 export abstract class GLTFExtensionParser {
   initialize(): void {}
 
   parseEngineResource(
-    schema: ExtensionSchema,
+    schema: GLTFExtensionSchema,
     parseResource: EngineObject,
     context: GLTFParserContext,
     ...extra
   ): void | Promise<void> {}
 
   createEngineResource(
-    schema: ExtensionSchema,
+    schema: GLTFExtensionSchema,
     context: GLTFParserContext,
     ...extra
   ): EngineObject | Promise<EngineObject> {
diff --git a/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts b/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts
index bb73b0ad43..e032532ad9 100644
--- a/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts
@@ -159,7 +159,7 @@ export interface IOasisMaterialRemap {
   isClone?: boolean;
 }
 
-export type ExtensionSchema =
+export type GLTFExtensionSchema =
   | IKHRLightsPunctual_Light
   | IKHRDracoMeshCompression
   | IKHRMaterialsClearcoat
diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index 7a7cdb71fd..af5bbf09a9 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -1,6 +1,6 @@
 import { AnimationClip, AssetPromise, EngineObject, Logger, Material, Mesh } from "@oasis-engine/core";
 import { GLTFExtensionParser } from "../extensions/GLTFExtensionParser";
-import { ExtensionSchema } from "../extensions/GLTFExtensionSchema";
+import { GLTFExtensionSchema } from "../extensions/GLTFExtensionSchema";
 import { GLTFParserContext } from "./GLTFParserContext";
 
 export abstract class GLTFParser {
@@ -8,7 +8,7 @@ export abstract class GLTFParser {
 
   static parseEngineResource(
     extensionName: string,
-    extensionSchema: ExtensionSchema,
+    extensionSchema: GLTFExtensionSchema,
     parseResource: EngineObject,
     context: GLTFParserContext,
     ...extra
@@ -26,7 +26,7 @@ export abstract class GLTFParser {
 
   static createEngineResource(
     extensionName: string,
-    extensionSchema: ExtensionSchema,
+    extensionSchema: GLTFExtensionSchema,
     context: GLTFParserContext,
     ...extra
   ): EngineObject | Promise<EngineObject> {

From 0b36e5d0e36b381907624748b2b89fea79a5dc75 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Mon, 27 Feb 2023 17:18:35 +0800
Subject: [PATCH 09/25] refactor: add resourceIndex to use customization

---
 .../gltf/extensions/GLTFExtensionParser.ts    |  2 ++
 .../extensions/KHR_draco_mesh_compression.ts  |  8 ++++-
 .../KHR_materials_pbrSpecularGlossiness.ts    |  8 ++++-
 .../gltf/extensions/KHR_texture_transform.ts  |  7 +---
 .../src/gltf/parser/GLTFMaterialParser.ts     | 34 +++++++++++++++----
 .../loader/src/gltf/parser/GLTFMeshParser.ts  |  2 ++
 packages/loader/src/gltf/parser/GLTFParser.ts |  6 ++--
 .../loader/src/gltf/parser/GLTFSceneParser.ts |  4 +--
 8 files changed, 52 insertions(+), 19 deletions(-)

diff --git a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
index 27b7d6c971..7c1e060937 100644
--- a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
@@ -9,12 +9,14 @@ export abstract class GLTFExtensionParser {
     schema: GLTFExtensionSchema,
     parseResource: EngineObject,
     context: GLTFParserContext,
+    resourceIndex: number,
     ...extra
   ): void | Promise<void> {}
 
   createEngineResource(
     schema: GLTFExtensionSchema,
     context: GLTFParserContext,
+    resourceIndex: number,
     ...extra
   ): EngineObject | Promise<EngineObject> {
     return null;
diff --git a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
index 139fc5209c..d51d0982d8 100644
--- a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
+++ b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
@@ -16,7 +16,13 @@ class KHR_draco_mesh_compression extends GLTFExtensionParser {
     }
   }
 
-  createEngineResource(schema: IKHRDracoMeshCompression, context: GLTFParserContext, gltfPrimitive: IMeshPrimitive) {
+  createEngineResource(
+    schema: IKHRDracoMeshCompression,
+    context: GLTFParserContext,
+    meshIndex: number,
+    primitiveIndex: number,
+    gltfPrimitive: IMeshPrimitive
+  ) {
     const { gltf, buffers } = context;
     const { bufferViews, accessors } = gltf;
     const { bufferView: bufferViewIndex, attributes: gltfAttributeMap } = schema;
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
index 9631d6ddba..e5eb0397db 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
@@ -26,7 +26,13 @@ class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser {
       material.baseTexture = textures[diffuseTexture.index];
       const KHR_texture_transform = diffuseTexture.extensions?.KHR_texture_transform;
       if (KHR_texture_transform) {
-        GLTFParser.parseEngineResource("KHR_texture_transform", KHR_texture_transform, material, context);
+        GLTFParser.parseEngineResource(
+          "KHR_texture_transform",
+          KHR_texture_transform,
+          material,
+          context,
+          diffuseTexture.index
+        );
       }
     }
 
diff --git a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
index 83de2abb2c..e11bb1acbd 100644
--- a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
+++ b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
@@ -1,16 +1,11 @@
 import { Logger, PBRBaseMaterial, UnlitMaterial } from "@oasis-engine/core";
 import { registerGLTFExtension } from "../parser/GLTFParser";
-import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRTextureTransform } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_texture_transform")
 class KHR_texture_transform extends GLTFExtensionParser {
-  parseEngineResource(
-    schema: IKHRTextureTransform,
-    material: PBRBaseMaterial | UnlitMaterial,
-    context: GLTFParserContext
-  ): void {
+  parseEngineResource(schema: IKHRTextureTransform, material: PBRBaseMaterial | UnlitMaterial): void {
     const { offset, rotation, scale, texCoord } = schema;
 
     if (offset) {
diff --git a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
index ba95898cf7..6762168439 100644
--- a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
@@ -43,7 +43,7 @@ export class GLTFMaterialParser extends GLTFParser {
 
       for (let name in otherExtensions) {
         if (GLTFParser.hasExtensionParser(name)) {
-          material = <Promise<any>>GLTFParser.createEngineResource(name, otherExtensions[name], context);
+          material = <Promise<any>>GLTFParser.createEngineResource(name, otherExtensions[name], context, i);
           if (material) {
             break;
           }
@@ -52,20 +52,23 @@ export class GLTFMaterialParser extends GLTFParser {
 
       if (!material) {
         if (KHR_materials_unlit) {
-          material = <UnlitMaterial>GLTFParser.createEngineResource("KHR_materials_unlit", KHR_materials_unlit, context);
+          material = <UnlitMaterial>(
+            GLTFParser.createEngineResource("KHR_materials_unlit", KHR_materials_unlit, context, i)
+          );
         } else if (KHR_materials_pbrSpecularGlossiness) {
           material = <PBRSpecularMaterial>(
             GLTFParser.createEngineResource(
               "KHR_materials_pbrSpecularGlossiness",
               KHR_materials_pbrSpecularGlossiness,
-              context
+              context,
+              i
             )
           );
         } else {
           material = new PBRMaterial(engine);
         }
         material.name = name;
-        this._parseGLTFMaterial(material, materialInfo, context);
+        this._parseGLTFMaterial(material, materialInfo, context, i);
       }
 
       promises.push(material);
@@ -78,7 +81,12 @@ export class GLTFMaterialParser extends GLTFParser {
     });
   }
 
-  private _parseGLTFMaterial(material: BaseMaterial, materialInfo: IMaterial, context: GLTFParserContext) {
+  private _parseGLTFMaterial(
+    material: BaseMaterial,
+    materialInfo: IMaterial,
+    context: GLTFParserContext,
+    resourceIndex: number
+  ) {
     const { textures } = context.glTFResource;
     const {
       extensions = {},
@@ -95,7 +103,13 @@ export class GLTFMaterialParser extends GLTFParser {
     const { KHR_materials_unlit, KHR_materials_pbrSpecularGlossiness, KHR_materials_clearcoat } = extensions;
 
     if (KHR_materials_clearcoat) {
-      GLTFParser.parseEngineResource("KHR_materials_clearcoat", KHR_materials_clearcoat, material, context);
+      GLTFParser.parseEngineResource(
+        "KHR_materials_clearcoat",
+        KHR_materials_clearcoat,
+        material,
+        context,
+        resourceIndex
+      );
     }
 
     if (pbrMetallicRoughness) {
@@ -115,7 +129,13 @@ export class GLTFMaterialParser extends GLTFParser {
         m.baseTexture = textures[baseColorTexture.index];
         const KHR_texture_transform = baseColorTexture.extensions?.KHR_texture_transform;
         if (KHR_texture_transform) {
-          GLTFParser.parseEngineResource("KHR_texture_transform", KHR_texture_transform, material, context);
+          GLTFParser.parseEngineResource(
+            "KHR_texture_transform",
+            KHR_texture_transform,
+            material,
+            context,
+            baseColorTexture.index
+          );
         }
       }
 
diff --git a/packages/loader/src/gltf/parser/GLTFMeshParser.ts b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
index fbebf87799..3775ddd26e 100644
--- a/packages/loader/src/gltf/parser/GLTFMeshParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
@@ -44,6 +44,8 @@ export class GLTFMeshParser extends GLTFParser {
                 "KHR_draco_mesh_compression",
                 KHR_draco_mesh_compression,
                 context,
+                i,
+                j,
                 gltfPrimitive
               )
             ))
diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index af5bbf09a9..7af3ca14ca 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -11,6 +11,7 @@ export abstract class GLTFParser {
     extensionSchema: GLTFExtensionSchema,
     parseResource: EngineObject,
     context: GLTFParserContext,
+    resourceIndex: number,
     ...extra
   ): void {
     const parsers = GLTFParser._extensionParsers[extensionName];
@@ -20,7 +21,7 @@ export abstract class GLTFParser {
       if (length > 1) {
         Logger.warn(`plugin:${extensionName} has been overridden`);
       }
-      parsers[length - 1].parseEngineResource(extensionSchema, parseResource, context, ...extra);
+      parsers[length - 1].parseEngineResource(extensionSchema, parseResource, context, resourceIndex, ...extra);
     }
   }
 
@@ -28,6 +29,7 @@ export abstract class GLTFParser {
     extensionName: string,
     extensionSchema: GLTFExtensionSchema,
     context: GLTFParserContext,
+    resourceIndex: number,
     ...extra
   ): EngineObject | Promise<EngineObject> {
     const parsers = GLTFParser._extensionParsers[extensionName];
@@ -37,7 +39,7 @@ export abstract class GLTFParser {
       if (length > 1) {
         Logger.warn(`plugin:${extensionName} has been overridden`);
       }
-      return parsers[length - 1].createEngineResource(extensionSchema, context, ...extra);
+      return parsers[length - 1].createEngineResource(extensionSchema, context, resourceIndex, ...extra);
     }
   }
 
diff --git a/packages/loader/src/gltf/parser/GLTFSceneParser.ts b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
index e394774c64..30fd270b27 100644
--- a/packages/loader/src/gltf/parser/GLTFSceneParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
@@ -53,7 +53,7 @@ export class GLTFSceneParser extends GLTFParser {
         const lightIndex = KHR_lights_punctual.light;
         const lights = (gltf.extensions.KHR_lights_punctual as IKHRLightsPunctual).lights;
 
-        GLTFParser.parseEngineResource("KHR_lights_punctual", lights[lightIndex], entity, context);
+        GLTFParser.parseEngineResource("KHR_lights_punctual", lights[lightIndex], entity, context, lightIndex);
       }
     }
 
@@ -143,7 +143,7 @@ export class GLTFSceneParser extends GLTFParser {
       const { extensions = {} } = gltfMeshPrimitives[i];
       const { KHR_materials_variants } = extensions;
       if (KHR_materials_variants) {
-        GLTFParser.parseEngineResource("KHR_materials_variants", KHR_materials_variants, renderer, context);
+        GLTFParser.parseEngineResource("KHR_materials_variants", KHR_materials_variants, renderer, context, i);
       }
     }
   }

From a9b9f86b2eb5bd8ffdb9fbb6928b8d538c856121 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Mon, 27 Feb 2023 19:00:58 +0800
Subject: [PATCH 10/25] refactor: extend resource

---
 packages/loader/src/gltf/GLTFSchema.ts        |  2 ++
 .../gltf/extensions/GLTFExtensionParser.ts    | 15 +++++-----
 .../extensions/KHR_draco_mesh_compression.ts  | 10 ++-----
 .../gltf/extensions/KHR_lights_punctual.ts    |  5 ++--
 .../extensions/KHR_materials_clearcoat.ts     |  5 ++--
 .../KHR_materials_pbrSpecularGlossiness.ts    | 11 +++----
 .../gltf/extensions/KHR_materials_unlit.ts    |  6 ++--
 .../gltf/extensions/KHR_materials_variants.ts |  5 ++--
 .../gltf/extensions/KHR_mesh_quantization.ts  |  2 +-
 .../gltf/extensions/KHR_texture_transform.ts  | 10 +++++--
 .../gltf/extensions/OASIS_materials_remap.ts  |  5 ++--
 packages/loader/src/gltf/index.ts             |  1 +
 .../src/gltf/parser/GLTFMaterialParser.ts     | 29 ++++++++-----------
 .../loader/src/gltf/parser/GLTFMeshParser.ts  |  4 +--
 packages/loader/src/gltf/parser/GLTFParser.ts | 23 +++++++--------
 .../loader/src/gltf/parser/GLTFSceneParser.ts | 15 +++++++---
 16 files changed, 77 insertions(+), 71 deletions(-)

diff --git a/packages/loader/src/gltf/GLTFSchema.ts b/packages/loader/src/gltf/GLTFSchema.ts
index 9a6e33e94f..14f4ac324e 100644
--- a/packages/loader/src/gltf/GLTFSchema.ts
+++ b/packages/loader/src/gltf/GLTFSchema.ts
@@ -853,3 +853,5 @@ export interface IGLTF extends IProperty {
    */
   textures?: ITexture[];
 }
+
+export type ExtensibleResource = IMeshPrimitive | IMaterial | ITexture | INode;
diff --git a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
index 7c1e060937..571c1547fb 100644
--- a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
@@ -1,23 +1,22 @@
 import { EngineObject } from "@oasis-engine/core";
+import { ExtensibleResource } from "../GLTFSchema";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionSchema } from "./GLTFExtensionSchema";
 
-export abstract class GLTFExtensionParser {
+export abstract class GLTFExtensionParser<T extends ExtensibleResource> {
   initialize(): void {}
 
   parseEngineResource(
-    schema: GLTFExtensionSchema,
-    parseResource: EngineObject,
     context: GLTFParserContext,
-    resourceIndex: number,
-    ...extra
+    parseResource: EngineObject,
+    extensionSchema: GLTFExtensionSchema,
+    resourceInfo: T
   ): void | Promise<void> {}
 
   createEngineResource(
-    schema: GLTFExtensionSchema,
     context: GLTFParserContext,
-    resourceIndex: number,
-    ...extra
+    extensionSchema: GLTFExtensionSchema,
+    resourceInfo: T
   ): EngineObject | Promise<EngineObject> {
     return null;
   }
diff --git a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
index d51d0982d8..e615671f87 100644
--- a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
+++ b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
@@ -7,7 +7,7 @@ import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRDracoMeshCompression } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_draco_mesh_compression")
-class KHR_draco_mesh_compression extends GLTFExtensionParser {
+class KHR_draco_mesh_compression extends GLTFExtensionParser<IMeshPrimitive> {
   private static _decoder: DRACODecoder;
 
   initialize(): void {
@@ -16,13 +16,7 @@ class KHR_draco_mesh_compression extends GLTFExtensionParser {
     }
   }
 
-  createEngineResource(
-    schema: IKHRDracoMeshCompression,
-    context: GLTFParserContext,
-    meshIndex: number,
-    primitiveIndex: number,
-    gltfPrimitive: IMeshPrimitive
-  ) {
+  createEngineResource(context: GLTFParserContext, schema: IKHRDracoMeshCompression, gltfPrimitive: IMeshPrimitive) {
     const { gltf, buffers } = context;
     const { bufferViews, accessors } = gltf;
     const { bufferView: bufferViewIndex, attributes: gltfAttributeMap } = schema;
diff --git a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
index f012805e3f..84c03d2a48 100644
--- a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
+++ b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
@@ -1,12 +1,13 @@
 import { DirectLight, Entity, PointLight, SpotLight } from "@oasis-engine/core";
+import { INode } from "../GLTFSchema";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRLightsPunctual_Light } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_lights_punctual")
-class KHR_lights_punctual extends GLTFExtensionParser {
-  parseEngineResource(schema: IKHRLightsPunctual_Light, entity: Entity, context: GLTFParserContext): void {
+class KHR_lights_punctual extends GLTFExtensionParser<INode> {
+  parseEngineResource(context: GLTFParserContext, entity: Entity, schema: IKHRLightsPunctual_Light): void {
     const { color, intensity = 1, type, range, spot } = schema;
     const glTFResource = context.glTFResource;
     let light: DirectLight | PointLight | SpotLight;
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
index 508b31597f..f6242e88b7 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
@@ -1,4 +1,5 @@
 import { PBRMaterial } from "@oasis-engine/core";
+import { IMaterial } from "../GLTFSchema";
 import { GLTFMaterialParser } from "../parser/GLTFMaterialParser";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
@@ -6,8 +7,8 @@ import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialsClearcoat } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_clearcoat")
-class KHR_materials_clearcoat extends GLTFExtensionParser {
-  parseEngineResource(schema: IKHRMaterialsClearcoat, material: PBRMaterial, context: GLTFParserContext): void {
+class KHR_materials_clearcoat extends GLTFExtensionParser<IMaterial> {
+  parseEngineResource(context: GLTFParserContext, material: PBRMaterial, schema: IKHRMaterialsClearcoat): void {
     const { textures } = context.glTFResource;
     const {
       clearcoatFactor = 0,
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
index e5eb0397db..30a80d95e7 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
@@ -1,5 +1,6 @@
 import { PBRSpecularMaterial } from "@oasis-engine/core";
 import { Color } from "@oasis-engine/math";
+import { IMaterial } from "../GLTFSchema";
 import { GLTFMaterialParser } from "../parser/GLTFMaterialParser";
 import { GLTFParser, registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
@@ -7,8 +8,8 @@ import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialsPbrSpecularGlossiness } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_pbrSpecularGlossiness")
-class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser {
-  createEngineResource(schema: IKHRMaterialsPbrSpecularGlossiness, context: GLTFParserContext): PBRSpecularMaterial {
+class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser<IMaterial> {
+  createEngineResource(context: GLTFParserContext, schema: IKHRMaterialsPbrSpecularGlossiness): PBRSpecularMaterial {
     const { engine, textures } = context.glTFResource;
     const material = new PBRSpecularMaterial(engine);
     const { diffuseFactor, diffuseTexture, specularFactor, glossinessFactor, specularGlossinessTexture } = schema;
@@ -28,10 +29,10 @@ class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser {
       if (KHR_texture_transform) {
         GLTFParser.parseEngineResource(
           "KHR_texture_transform",
-          KHR_texture_transform,
-          material,
           context,
-          diffuseTexture.index
+          material,
+          KHR_texture_transform,
+          diffuseTexture
         );
       }
     }
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
index 98ba806b17..24fea1a078 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
@@ -1,12 +1,12 @@
 import { UnlitMaterial } from "@oasis-engine/core";
+import { IMaterial } from "../GLTFSchema";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
-import { IKHRMaterialsUnlit } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_unlit")
-class KHR_materials_unlit extends GLTFExtensionParser {
-  createEngineResource(schema: IKHRMaterialsUnlit, context: GLTFParserContext): UnlitMaterial {
+class KHR_materials_unlit extends GLTFExtensionParser<IMaterial> {
+  createEngineResource(context: GLTFParserContext): UnlitMaterial {
     const { engine } = context.glTFResource;
     const material = new UnlitMaterial(engine);
 
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
index c5b3982c9a..c46dfdf13c 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
@@ -1,12 +1,13 @@
 import { Renderer } from "@oasis-engine/core";
+import { IMeshPrimitive } from "../GLTFSchema";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialVariants_Mapping } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_variants")
-class KHR_materials_variants extends GLTFExtensionParser {
-  parseEngineResource(schema: IKHRMaterialVariants_Mapping, renderer: Renderer, context: GLTFParserContext): void {
+class KHR_materials_variants extends GLTFExtensionParser<IMeshPrimitive> {
+  parseEngineResource(context: GLTFParserContext, renderer: Renderer, schema: IKHRMaterialVariants_Mapping): void {
     const {
       gltf: {
         extensions: {
diff --git a/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts b/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts
index 28ac4127d0..43765abf0b 100644
--- a/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts
+++ b/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts
@@ -2,4 +2,4 @@ import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
 
 @registerGLTFExtension("KHR_mesh_quantization")
-class KHR_mesh_quantization extends GLTFExtensionParser {}
+class KHR_mesh_quantization extends GLTFExtensionParser<any> {}
diff --git a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
index e11bb1acbd..f9e3205588 100644
--- a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
+++ b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
@@ -1,11 +1,17 @@
 import { Logger, PBRBaseMaterial, UnlitMaterial } from "@oasis-engine/core";
+import { ITextureInfo } from "../GLTFSchema";
 import { registerGLTFExtension } from "../parser/GLTFParser";
+import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRTextureTransform } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_texture_transform")
-class KHR_texture_transform extends GLTFExtensionParser {
-  parseEngineResource(schema: IKHRTextureTransform, material: PBRBaseMaterial | UnlitMaterial): void {
+class KHR_texture_transform extends GLTFExtensionParser<ITextureInfo> {
+  parseEngineResource(
+    context: GLTFParserContext,
+    material: PBRBaseMaterial | UnlitMaterial,
+    schema: IKHRTextureTransform
+  ): void {
     const { offset, rotation, scale, texCoord } = schema;
 
     if (offset) {
diff --git a/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts b/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
index 3b4251755c..3a772173f4 100644
--- a/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
+++ b/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
@@ -1,12 +1,13 @@
 import { Material } from "@oasis-engine/core";
+import { IMaterial } from "../GLTFSchema";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IOasisMaterialRemap } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("OASIS_materials_remap")
-class OasisMaterialsRemap extends GLTFExtensionParser {
-  createEngineResource(schema: IOasisMaterialRemap, context: GLTFParserContext): Promise<Material> {
+class OasisMaterialsRemap extends GLTFExtensionParser<IMaterial> {
+  createEngineResource(context: GLTFParserContext, schema: IOasisMaterialRemap): Promise<Material> {
     const { engine } = context.glTFResource;
     // @ts-ignore
     return engine.resourceManager.getResourceByRef<Material>(schema);
diff --git a/packages/loader/src/gltf/index.ts b/packages/loader/src/gltf/index.ts
index 32ab0a24f0..91d3279aac 100644
--- a/packages/loader/src/gltf/index.ts
+++ b/packages/loader/src/gltf/index.ts
@@ -3,3 +3,4 @@ export { GLTFResource } from "./GLTFResource";
 export { GLTFUtil } from "./GLTFUtil";
 export * from "./parser";
 export * from "./extensions/index";
+export { IMaterial, IMeshPrimitive, ITextureInfo, INode } from "./GLTFSchema";
diff --git a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
index 6762168439..34aff24455 100644
--- a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
@@ -43,7 +43,7 @@ export class GLTFMaterialParser extends GLTFParser {
 
       for (let name in otherExtensions) {
         if (GLTFParser.hasExtensionParser(name)) {
-          material = <Promise<any>>GLTFParser.createEngineResource(name, otherExtensions[name], context, i);
+          material = <Promise<any>>GLTFParser.createEngineResource(name, context, otherExtensions[name], materialInfo);
           if (material) {
             break;
           }
@@ -53,22 +53,22 @@ export class GLTFMaterialParser extends GLTFParser {
       if (!material) {
         if (KHR_materials_unlit) {
           material = <UnlitMaterial>(
-            GLTFParser.createEngineResource("KHR_materials_unlit", KHR_materials_unlit, context, i)
+            GLTFParser.createEngineResource("KHR_materials_unlit", context, KHR_materials_unlit, materialInfo)
           );
         } else if (KHR_materials_pbrSpecularGlossiness) {
           material = <PBRSpecularMaterial>(
             GLTFParser.createEngineResource(
               "KHR_materials_pbrSpecularGlossiness",
-              KHR_materials_pbrSpecularGlossiness,
               context,
-              i
+              KHR_materials_pbrSpecularGlossiness,
+              materialInfo
             )
           );
         } else {
           material = new PBRMaterial(engine);
         }
         material.name = name;
-        this._parseGLTFMaterial(material, materialInfo, context, i);
+        this._parseGLTFMaterial(material, materialInfo, context);
       }
 
       promises.push(material);
@@ -81,12 +81,7 @@ export class GLTFMaterialParser extends GLTFParser {
     });
   }
 
-  private _parseGLTFMaterial(
-    material: BaseMaterial,
-    materialInfo: IMaterial,
-    context: GLTFParserContext,
-    resourceIndex: number
-  ) {
+  private _parseGLTFMaterial(material: BaseMaterial, materialInfo: IMaterial, context: GLTFParserContext) {
     const { textures } = context.glTFResource;
     const {
       extensions = {},
@@ -105,10 +100,10 @@ export class GLTFMaterialParser extends GLTFParser {
     if (KHR_materials_clearcoat) {
       GLTFParser.parseEngineResource(
         "KHR_materials_clearcoat",
-        KHR_materials_clearcoat,
-        material,
         context,
-        resourceIndex
+        material,
+        KHR_materials_clearcoat,
+        materialInfo
       );
     }
 
@@ -131,10 +126,10 @@ export class GLTFMaterialParser extends GLTFParser {
         if (KHR_texture_transform) {
           GLTFParser.parseEngineResource(
             "KHR_texture_transform",
-            KHR_texture_transform,
-            material,
             context,
-            baseColorTexture.index
+            material,
+            KHR_texture_transform,
+            materialInfo
           );
         }
       }
diff --git a/packages/loader/src/gltf/parser/GLTFMeshParser.ts b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
index 3775ddd26e..3e6bc78b84 100644
--- a/packages/loader/src/gltf/parser/GLTFMeshParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
@@ -42,10 +42,8 @@ export class GLTFMeshParser extends GLTFParser {
             (<Promise<EngineObject>>(
               GLTFParser.createEngineResource(
                 "KHR_draco_mesh_compression",
-                KHR_draco_mesh_compression,
                 context,
-                i,
-                j,
+                KHR_draco_mesh_compression,
                 gltfPrimitive
               )
             ))
diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index 7af3ca14ca..576992e507 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -1,18 +1,18 @@
 import { AnimationClip, AssetPromise, EngineObject, Logger, Material, Mesh } from "@oasis-engine/core";
 import { GLTFExtensionParser } from "../extensions/GLTFExtensionParser";
 import { GLTFExtensionSchema } from "../extensions/GLTFExtensionSchema";
+import { ExtensibleResource } from "../GLTFSchema";
 import { GLTFParserContext } from "./GLTFParserContext";
 
 export abstract class GLTFParser {
-  private static _extensionParsers: Record<string, GLTFExtensionParser[]> = {};
+  private static _extensionParsers: Record<string, GLTFExtensionParser<ExtensibleResource>[]> = {};
 
   static parseEngineResource(
     extensionName: string,
-    extensionSchema: GLTFExtensionSchema,
-    parseResource: EngineObject,
     context: GLTFParserContext,
-    resourceIndex: number,
-    ...extra
+    parseResource: EngineObject,
+    extensionSchema: GLTFExtensionSchema,
+    resourceInfo: ExtensibleResource
   ): void {
     const parsers = GLTFParser._extensionParsers[extensionName];
     const length = parsers?.length;
@@ -21,16 +21,15 @@ export abstract class GLTFParser {
       if (length > 1) {
         Logger.warn(`plugin:${extensionName} has been overridden`);
       }
-      parsers[length - 1].parseEngineResource(extensionSchema, parseResource, context, resourceIndex, ...extra);
+      parsers[length - 1].parseEngineResource(context, parseResource, extensionSchema, resourceInfo);
     }
   }
 
   static createEngineResource(
     extensionName: string,
-    extensionSchema: GLTFExtensionSchema,
     context: GLTFParserContext,
-    resourceIndex: number,
-    ...extra
+    extensionSchema: GLTFExtensionSchema,
+    resourceInfo: ExtensibleResource
   ): EngineObject | Promise<EngineObject> {
     const parsers = GLTFParser._extensionParsers[extensionName];
     const length = parsers?.length;
@@ -39,7 +38,7 @@ export abstract class GLTFParser {
       if (length > 1) {
         Logger.warn(`plugin:${extensionName} has been overridden`);
       }
-      return parsers[length - 1].createEngineResource(extensionSchema, context, resourceIndex, ...extra);
+      return parsers[length - 1].createEngineResource(context, extensionSchema, resourceInfo);
     }
   }
 
@@ -61,7 +60,7 @@ export abstract class GLTFParser {
   /**
    * @internal
    */
-  static _addExtensionParser(extensionName: string, extensionParser: GLTFExtensionParser) {
+  static _addExtensionParser(extensionName: string, extensionParser: GLTFExtensionParser<ExtensibleResource>) {
     if (!GLTFParser._extensionParsers[extensionName]) {
       GLTFParser._extensionParsers[extensionName] = [];
     }
@@ -76,7 +75,7 @@ export abstract class GLTFParser {
  * @param extensionName - Extension name
  */
 export function registerGLTFExtension(extensionName: string) {
-  return (parser: new () => GLTFExtensionParser) => {
+  return (parser: new () => GLTFExtensionParser<ExtensibleResource>) => {
     const extensionParser = new parser();
 
     GLTFParser._addExtensionParser(extensionName, extensionParser);
diff --git a/packages/loader/src/gltf/parser/GLTFSceneParser.ts b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
index 30fd270b27..ebc82333a9 100644
--- a/packages/loader/src/gltf/parser/GLTFSceneParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
@@ -53,7 +53,7 @@ export class GLTFSceneParser extends GLTFParser {
         const lightIndex = KHR_lights_punctual.light;
         const lights = (gltf.extensions.KHR_lights_punctual as IKHRLightsPunctual).lights;
 
-        GLTFParser.parseEngineResource("KHR_lights_punctual", lights[lightIndex], entity, context, lightIndex);
+        GLTFParser.parseEngineResource("KHR_lights_punctual", context, entity, lights[lightIndex], gltfNode);
       }
     }
 
@@ -117,6 +117,7 @@ export class GLTFSceneParser extends GLTFParser {
     const blendShapeWeights = gltfNode.weights || glTFMesh.weights;
 
     for (let i = 0; i < gltfMeshPrimitives.length; i++) {
+      const gltfPrimitive = gltfMeshPrimitives[i];
       const mesh = meshes[meshID][i];
       let renderer: MeshRenderer | SkinnedMeshRenderer;
 
@@ -136,14 +137,20 @@ export class GLTFSceneParser extends GLTFParser {
         renderer.mesh = mesh;
       }
 
-      const materialIndex = gltfMeshPrimitives[i].material;
+      const materialIndex = gltfPrimitive.material;
       const material = materials?.[materialIndex] || GLTFSceneParser._getDefaultMaterial(engine);
       renderer.setMaterial(material);
 
-      const { extensions = {} } = gltfMeshPrimitives[i];
+      const { extensions = {} } = gltfPrimitive;
       const { KHR_materials_variants } = extensions;
       if (KHR_materials_variants) {
-        GLTFParser.parseEngineResource("KHR_materials_variants", KHR_materials_variants, renderer, context, i);
+        GLTFParser.parseEngineResource(
+          "KHR_materials_variants",
+          context,
+          renderer,
+          KHR_materials_variants,
+          gltfPrimitive
+        );
       }
     }
   }

From a7d1ad7ffb2f6f9c6cd9970ecba507669cd15c32 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Tue, 28 Feb 2023 18:31:28 +0800
Subject: [PATCH 11/25] refactor:  extension mode

---
 packages/loader/src/gltf/GLTFSchema.ts        |  2 +-
 .../gltf/extensions/GLTFExtensionParser.ts    | 65 ++++++++++++---
 .../gltf/extensions/GLTFExtensionSchema.ts    |  3 +-
 .../extensions/KHR_draco_mesh_compression.ts  | 10 ++-
 .../gltf/extensions/KHR_lights_punctual.ts    |  9 ++-
 .../extensions/KHR_materials_clearcoat.ts     |  9 ++-
 .../KHR_materials_pbrSpecularGlossiness.ts    | 22 +++---
 .../gltf/extensions/KHR_materials_unlit.ts    | 11 ++-
 .../gltf/extensions/KHR_materials_variants.ts |  9 ++-
 .../gltf/extensions/KHR_mesh_quantization.ts  |  6 +-
 .../gltf/extensions/KHR_texture_transform.ts  |  9 ++-
 .../gltf/extensions/OASIS_materials_remap.ts  |  9 ++-
 packages/loader/src/gltf/extensions/index.ts  |  2 +-
 packages/loader/src/gltf/index.ts             |  2 +-
 .../src/gltf/parser/GLTFMaterialParser.ts     | 79 +++++++------------
 .../loader/src/gltf/parser/GLTFMeshParser.ts  |  2 +-
 packages/loader/src/gltf/parser/GLTFParser.ts | 69 ++++++++--------
 .../loader/src/gltf/parser/GLTFSceneParser.ts |  4 +-
 .../loader/src/gltf/parser/GLTFValidator.ts   | 10 ++-
 19 files changed, 190 insertions(+), 142 deletions(-)

diff --git a/packages/loader/src/gltf/GLTFSchema.ts b/packages/loader/src/gltf/GLTFSchema.ts
index 14f4ac324e..67b3d2dd38 100644
--- a/packages/loader/src/gltf/GLTFSchema.ts
+++ b/packages/loader/src/gltf/GLTFSchema.ts
@@ -854,4 +854,4 @@ export interface IGLTF extends IProperty {
   textures?: ITexture[];
 }
 
-export type ExtensibleResource = IMeshPrimitive | IMaterial | ITexture | INode;
+export type GLTFExtensionOwnerSchema = IMeshPrimitive | IMaterial | ITextureInfo | INode;
diff --git a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
index 571c1547fb..d157e229fb 100644
--- a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
@@ -1,23 +1,66 @@
 import { EngineObject } from "@oasis-engine/core";
-import { ExtensibleResource } from "../GLTFSchema";
+import { GLTFExtensionOwnerSchema } from "../GLTFSchema";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionSchema } from "./GLTFExtensionSchema";
 
-export abstract class GLTFExtensionParser<T extends ExtensibleResource> {
-  initialize(): void {}
+/**
+ * Base class of glTF extension parser.
+ */
+export abstract class GLTFExtensionParser {
+  /** The extension mode. */
+  abstract readonly mode: GLTFExtensionMode;
 
-  parseEngineResource(
+  /**
+   * Some plugins require initialization.
+   */
+  initialize(): void | Promise<void> {}
+
+  /**
+   * Create a resource instance.
+   * @remarks This method overrides the default resource creation
+   * @param context - The parser context
+   * @param extensionSchema - The extension schema
+   * @param ownerSchema - The extension owner schema
+   * @returns The resource or promise
+   */
+  createAndParse(
     context: GLTFParserContext,
-    parseResource: EngineObject,
     extensionSchema: GLTFExtensionSchema,
-    resourceInfo: T
-  ): void | Promise<void> {}
+    ownerSchema: GLTFExtensionOwnerSchema
+  ): EngineObject | Promise<EngineObject> {
+    throw "Not implemented.";
+  }
 
-  createEngineResource(
+  /**
+   * Additive parse to the resource.
+   * @param context - The parser context
+   * @param resource - The resource
+   * @param extensionSchema - The extension schema
+   * @param ownerSchema - The extension owner schema
+   * @returns The void or promise
+   */
+  additiveParse(
     context: GLTFParserContext,
+    resource: EngineObject,
     extensionSchema: GLTFExtensionSchema,
-    resourceInfo: T
-  ): EngineObject | Promise<EngineObject> {
-    return null;
+    ownerSchema: GLTFExtensionOwnerSchema
+  ): void | Promise<void> {
+    throw "Not implemented.";
   }
 }
+
+/**
+ * glTF Extension mode.
+ */
+export enum GLTFExtensionMode {
+  /**
+   * Cerate instance and parse mode.
+   * @remarks
+   * If the glTF property has multiple extensions of `CreateAndParse` mode, only execute the last one.
+   * If this method is registered, the default pipeline processing will be ignored.
+   */
+  CreateAndParse,
+
+  /** Additive parse mode. */
+  AdditiveParse
+}
diff --git a/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts b/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts
index e032532ad9..477914ed8c 100644
--- a/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts
@@ -175,4 +175,5 @@ export type GLTFExtensionSchema =
   | IKHRTextureBasisU
   | IKHRTextureTransform
   | IKHRXmp
-  | IKHRXmp_Node;
+  | IKHRXmp_Node
+  | Object;
diff --git a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
index e615671f87..128dd824f5 100644
--- a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
+++ b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
@@ -1,13 +1,15 @@
 import { DRACODecoder } from "@oasis-engine/draco";
+import { IMeshPrimitive } from "../GLTFSchema";
 import { GLTFUtil } from "../GLTFUtil";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
-import { IMeshPrimitive } from "../GLTFSchema";
-import { GLTFExtensionParser } from "./GLTFExtensionParser";
+import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRDracoMeshCompression } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_draco_mesh_compression")
-class KHR_draco_mesh_compression extends GLTFExtensionParser<IMeshPrimitive> {
+class KHR_draco_mesh_compression extends GLTFExtensionParser {
+  mode = GLTFExtensionMode.CreateAndParse;
+
   private static _decoder: DRACODecoder;
 
   initialize(): void {
@@ -16,7 +18,7 @@ class KHR_draco_mesh_compression extends GLTFExtensionParser<IMeshPrimitive> {
     }
   }
 
-  createEngineResource(context: GLTFParserContext, schema: IKHRDracoMeshCompression, gltfPrimitive: IMeshPrimitive) {
+  createAndParse(context: GLTFParserContext, schema: IKHRDracoMeshCompression, gltfPrimitive: IMeshPrimitive) {
     const { gltf, buffers } = context;
     const { bufferViews, accessors } = gltf;
     const { bufferView: bufferViewIndex, attributes: gltfAttributeMap } = schema;
diff --git a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
index 84c03d2a48..6524feea51 100644
--- a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
+++ b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
@@ -1,13 +1,14 @@
 import { DirectLight, Entity, PointLight, SpotLight } from "@oasis-engine/core";
-import { INode } from "../GLTFSchema";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
-import { GLTFExtensionParser } from "./GLTFExtensionParser";
+import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRLightsPunctual_Light } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_lights_punctual")
-class KHR_lights_punctual extends GLTFExtensionParser<INode> {
-  parseEngineResource(context: GLTFParserContext, entity: Entity, schema: IKHRLightsPunctual_Light): void {
+class KHR_lights_punctual extends GLTFExtensionParser {
+  mode = GLTFExtensionMode.AdditiveParse;
+
+  additiveParse(context: GLTFParserContext, entity: Entity, schema: IKHRLightsPunctual_Light): void {
     const { color, intensity = 1, type, range, spot } = schema;
     const glTFResource = context.glTFResource;
     let light: DirectLight | PointLight | SpotLight;
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
index f6242e88b7..0f0334833c 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
@@ -1,14 +1,15 @@
 import { PBRMaterial } from "@oasis-engine/core";
-import { IMaterial } from "../GLTFSchema";
 import { GLTFMaterialParser } from "../parser/GLTFMaterialParser";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
-import { GLTFExtensionParser } from "./GLTFExtensionParser";
+import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialsClearcoat } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_clearcoat")
-class KHR_materials_clearcoat extends GLTFExtensionParser<IMaterial> {
-  parseEngineResource(context: GLTFParserContext, material: PBRMaterial, schema: IKHRMaterialsClearcoat): void {
+class KHR_materials_clearcoat extends GLTFExtensionParser {
+  mode = GLTFExtensionMode.AdditiveParse;
+
+  additiveParse(context: GLTFParserContext, material: PBRMaterial, schema: IKHRMaterialsClearcoat): void {
     const { textures } = context.glTFResource;
     const {
       clearcoatFactor = 0,
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
index 30a80d95e7..6429a6ba5d 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
@@ -4,12 +4,18 @@ import { IMaterial } from "../GLTFSchema";
 import { GLTFMaterialParser } from "../parser/GLTFMaterialParser";
 import { GLTFParser, registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
-import { GLTFExtensionParser } from "./GLTFExtensionParser";
+import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialsPbrSpecularGlossiness } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_pbrSpecularGlossiness")
-class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser<IMaterial> {
-  createEngineResource(context: GLTFParserContext, schema: IKHRMaterialsPbrSpecularGlossiness): PBRSpecularMaterial {
+class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser {
+  mode = GLTFExtensionMode.CreateAndParse;
+
+  createAndParse(
+    context: GLTFParserContext,
+    schema: IKHRMaterialsPbrSpecularGlossiness,
+    ownerSchema: IMaterial
+  ): PBRSpecularMaterial {
     const { engine, textures } = context.glTFResource;
     const material = new PBRSpecularMaterial(engine);
     const { diffuseFactor, diffuseTexture, specularFactor, glossinessFactor, specularGlossinessTexture } = schema;
@@ -27,13 +33,7 @@ class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser<IMaterial>
       material.baseTexture = textures[diffuseTexture.index];
       const KHR_texture_transform = diffuseTexture.extensions?.KHR_texture_transform;
       if (KHR_texture_transform) {
-        GLTFParser.parseEngineResource(
-          "KHR_texture_transform",
-          context,
-          material,
-          KHR_texture_transform,
-          diffuseTexture
-        );
+        GLTFParser.additiveParse("KHR_texture_transform", context, material, KHR_texture_transform, diffuseTexture);
       }
     }
 
@@ -54,6 +54,8 @@ class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser<IMaterial>
       GLTFMaterialParser._checkOtherTextureTransform(specularGlossinessTexture, "Specular glossiness");
     }
 
+    material.name = ownerSchema.name;
+    GLTFMaterialParser._parseGLTFMaterial(context, material, ownerSchema);
     return material;
   }
 }
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
index 24fea1a078..b2b29f3d35 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
@@ -1,15 +1,20 @@
 import { UnlitMaterial } from "@oasis-engine/core";
 import { IMaterial } from "../GLTFSchema";
+import { GLTFMaterialParser } from "../parser/GLTFMaterialParser";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
-import { GLTFExtensionParser } from "./GLTFExtensionParser";
+import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 
 @registerGLTFExtension("KHR_materials_unlit")
-class KHR_materials_unlit extends GLTFExtensionParser<IMaterial> {
-  createEngineResource(context: GLTFParserContext): UnlitMaterial {
+class KHR_materials_unlit extends GLTFExtensionParser {
+  mode = GLTFExtensionMode.CreateAndParse;
+
+  createAndParse(context: GLTFParserContext, _, ownerSchema: IMaterial): UnlitMaterial {
     const { engine } = context.glTFResource;
     const material = new UnlitMaterial(engine);
+    material.name = ownerSchema.name;
 
+    GLTFMaterialParser._parseGLTFMaterial(context, material, ownerSchema);
     return material;
   }
 }
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
index c46dfdf13c..eab77aa2e8 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
@@ -1,13 +1,14 @@
 import { Renderer } from "@oasis-engine/core";
-import { IMeshPrimitive } from "../GLTFSchema";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
-import { GLTFExtensionParser } from "./GLTFExtensionParser";
+import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialVariants_Mapping } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_variants")
-class KHR_materials_variants extends GLTFExtensionParser<IMeshPrimitive> {
-  parseEngineResource(context: GLTFParserContext, renderer: Renderer, schema: IKHRMaterialVariants_Mapping): void {
+class KHR_materials_variants extends GLTFExtensionParser {
+  mode = GLTFExtensionMode.AdditiveParse;
+
+  additiveParse(context: GLTFParserContext, renderer: Renderer, schema: IKHRMaterialVariants_Mapping): void {
     const {
       gltf: {
         extensions: {
diff --git a/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts b/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts
index 43765abf0b..ca9835b6ca 100644
--- a/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts
+++ b/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts
@@ -1,5 +1,7 @@
 import { registerGLTFExtension } from "../parser/GLTFParser";
-import { GLTFExtensionParser } from "./GLTFExtensionParser";
+import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 
 @registerGLTFExtension("KHR_mesh_quantization")
-class KHR_mesh_quantization extends GLTFExtensionParser<any> {}
+class KHR_mesh_quantization extends GLTFExtensionParser {
+  mode = GLTFExtensionMode.AdditiveParse;
+}
diff --git a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
index f9e3205588..c5ccaeb69c 100644
--- a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
+++ b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
@@ -1,13 +1,14 @@
 import { Logger, PBRBaseMaterial, UnlitMaterial } from "@oasis-engine/core";
-import { ITextureInfo } from "../GLTFSchema";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
-import { GLTFExtensionParser } from "./GLTFExtensionParser";
+import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRTextureTransform } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_texture_transform")
-class KHR_texture_transform extends GLTFExtensionParser<ITextureInfo> {
-  parseEngineResource(
+class KHR_texture_transform extends GLTFExtensionParser {
+  mode = GLTFExtensionMode.AdditiveParse;
+
+  additiveParse(
     context: GLTFParserContext,
     material: PBRBaseMaterial | UnlitMaterial,
     schema: IKHRTextureTransform
diff --git a/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts b/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
index 3a772173f4..d7f7f785bc 100644
--- a/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
+++ b/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
@@ -1,13 +1,14 @@
 import { Material } from "@oasis-engine/core";
-import { IMaterial } from "../GLTFSchema";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
-import { GLTFExtensionParser } from "./GLTFExtensionParser";
+import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IOasisMaterialRemap } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("OASIS_materials_remap")
-class OasisMaterialsRemap extends GLTFExtensionParser<IMaterial> {
-  createEngineResource(context: GLTFParserContext, schema: IOasisMaterialRemap): Promise<Material> {
+class OasisMaterialsRemap extends GLTFExtensionParser {
+  mode = GLTFExtensionMode.CreateAndParse;
+
+  createAndParse(context: GLTFParserContext, schema: IOasisMaterialRemap): Promise<Material> {
     const { engine } = context.glTFResource;
     // @ts-ignore
     return engine.resourceManager.getResourceByRef<Material>(schema);
diff --git a/packages/loader/src/gltf/extensions/index.ts b/packages/loader/src/gltf/extensions/index.ts
index cd43cfac78..f0ccf5c5eb 100644
--- a/packages/loader/src/gltf/extensions/index.ts
+++ b/packages/loader/src/gltf/extensions/index.ts
@@ -13,5 +13,5 @@ import "./KHR_texture_basisu";
 import "./KHR_texture_transform";
 import "./OASIS_materials_remap";
 
-export { GLTFExtensionParser } from "./GLTFExtensionParser";
+export { GLTFExtensionParser, GLTFExtensionMode } from "./GLTFExtensionParser";
 export * from "./GLTFExtensionSchema";
diff --git a/packages/loader/src/gltf/index.ts b/packages/loader/src/gltf/index.ts
index 91d3279aac..b6e80c4e0c 100644
--- a/packages/loader/src/gltf/index.ts
+++ b/packages/loader/src/gltf/index.ts
@@ -3,4 +3,4 @@ export { GLTFResource } from "./GLTFResource";
 export { GLTFUtil } from "./GLTFUtil";
 export * from "./parser";
 export * from "./extensions/index";
-export { IMaterial, IMeshPrimitive, ITextureInfo, INode } from "./GLTFSchema";
+export { IMaterial, IMeshPrimitive, ITextureInfo, INode, GLTFExtensionOwnerSchema } from "./GLTFSchema";
diff --git a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
index 34aff24455..ad4b6ac489 100644
--- a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
@@ -5,10 +5,8 @@ import {
   Material,
   PBRBaseMaterial,
   PBRMaterial,
-  PBRSpecularMaterial,
   RenderFace,
-  TextureCoordinate,
-  UnlitMaterial
+  TextureCoordinate
 } from "@oasis-engine/core";
 import { Color } from "@oasis-engine/math";
 import { IMaterial, ITextureInfo, MaterialAlphaMode } from "../GLTFSchema";
@@ -31,57 +29,56 @@ export class GLTFMaterialParser extends GLTFParser {
 
     const { engine } = glTFResource;
 
-    let promises = [];
+    let materialPromises = [];
 
     for (let i = 0; i < gltf.materials.length; i++) {
       const materialInfo = gltf.materials[i];
       const { extensions = {}, name = "" } = materialInfo;
 
-      const { KHR_materials_unlit, KHR_materials_pbrSpecularGlossiness, KHR_materials_clearcoat, ...otherExtensions } =
-        extensions;
       let material: BaseMaterial | Promise<BaseMaterial> = null;
 
-      for (let name in otherExtensions) {
-        if (GLTFParser.hasExtensionParser(name)) {
-          material = <Promise<any>>GLTFParser.createEngineResource(name, context, otherExtensions[name], materialInfo);
-          if (material) {
-            break;
-          }
+      const extensionArray = Object.keys(extensions);
+      for (let i = extensionArray.length - 1; i >= 0; --i) {
+        const extensionName = extensionArray[i];
+        const extensionSchema = extensions[extensionName];
+
+        material = <Promise<BaseMaterial> | BaseMaterial>(
+          GLTFParser.createAndParse(extensionName, context, extensionSchema, materialInfo)
+        );
+        if (material) {
+          break;
         }
       }
 
       if (!material) {
-        if (KHR_materials_unlit) {
-          material = <UnlitMaterial>(
-            GLTFParser.createEngineResource("KHR_materials_unlit", context, KHR_materials_unlit, materialInfo)
-          );
-        } else if (KHR_materials_pbrSpecularGlossiness) {
-          material = <PBRSpecularMaterial>(
-            GLTFParser.createEngineResource(
-              "KHR_materials_pbrSpecularGlossiness",
-              context,
-              KHR_materials_pbrSpecularGlossiness,
-              materialInfo
-            )
-          );
-        } else {
-          material = new PBRMaterial(engine);
-        }
+        material = new PBRMaterial(engine);
         material.name = name;
-        this._parseGLTFMaterial(material, materialInfo, context);
+        GLTFMaterialParser._parseGLTFMaterial(context, material, materialInfo);
       }
 
-      promises.push(material);
+      materialPromises.push(material);
     }
 
-    return AssetPromise.all(promises).then((materials) => {
+    return AssetPromise.all(materialPromises).then((materials) => {
       glTFResource.materials = materials;
+      for (let i = 0; i < gltf.materials.length; i++) {
+        const materialInfo = gltf.materials[i];
+        const material = materials[i];
+        const { extensions } = materialInfo;
+        for (let extensionName in extensions) {
+          const extensionSchema = extensions[extensionName];
+          GLTFParser.additiveParse(extensionName, context, material, extensionSchema, materialInfo);
+        }
+      }
       materialsPromiseInfo.resolve(materials);
       return materialsPromiseInfo.promise;
     });
   }
 
-  private _parseGLTFMaterial(material: BaseMaterial, materialInfo: IMaterial, context: GLTFParserContext) {
+  /**
+   * @internal
+   */
+  static _parseGLTFMaterial(context: GLTFParserContext, material: BaseMaterial, materialInfo: IMaterial) {
     const { textures } = context.glTFResource;
     const {
       extensions = {},
@@ -97,16 +94,6 @@ export class GLTFMaterialParser extends GLTFParser {
 
     const { KHR_materials_unlit, KHR_materials_pbrSpecularGlossiness, KHR_materials_clearcoat } = extensions;
 
-    if (KHR_materials_clearcoat) {
-      GLTFParser.parseEngineResource(
-        "KHR_materials_clearcoat",
-        context,
-        material,
-        KHR_materials_clearcoat,
-        materialInfo
-      );
-    }
-
     if (pbrMetallicRoughness) {
       const m = material as PBRBaseMaterial;
       const { baseColorFactor, baseColorTexture, metallicFactor, roughnessFactor, metallicRoughnessTexture } =
@@ -124,13 +111,7 @@ export class GLTFMaterialParser extends GLTFParser {
         m.baseTexture = textures[baseColorTexture.index];
         const KHR_texture_transform = baseColorTexture.extensions?.KHR_texture_transform;
         if (KHR_texture_transform) {
-          GLTFParser.parseEngineResource(
-            "KHR_texture_transform",
-            context,
-            material,
-            KHR_texture_transform,
-            materialInfo
-          );
+          GLTFParser.additiveParse("KHR_texture_transform", context, material, KHR_texture_transform, materialInfo);
         }
       }
 
diff --git a/packages/loader/src/gltf/parser/GLTFMeshParser.ts b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
index 3e6bc78b84..1295738923 100644
--- a/packages/loader/src/gltf/parser/GLTFMeshParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
@@ -40,7 +40,7 @@ export class GLTFMeshParser extends GLTFParser {
 
           if (KHR_draco_mesh_compression) {
             (<Promise<EngineObject>>(
-              GLTFParser.createEngineResource(
+              GLTFParser.createAndParse(
                 "KHR_draco_mesh_compression",
                 context,
                 KHR_draco_mesh_compression,
diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index 576992e507..96b868a96e 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -1,58 +1,63 @@
-import { AnimationClip, AssetPromise, EngineObject, Logger, Material, Mesh } from "@oasis-engine/core";
-import { GLTFExtensionParser } from "../extensions/GLTFExtensionParser";
+import { AnimationClip, AssetPromise, EngineObject, Material, Mesh } from "@oasis-engine/core";
+import { GLTFExtensionMode, GLTFExtensionParser } from "../extensions/GLTFExtensionParser";
 import { GLTFExtensionSchema } from "../extensions/GLTFExtensionSchema";
-import { ExtensibleResource } from "../GLTFSchema";
+import { GLTFExtensionOwnerSchema } from "../GLTFSchema";
 import { GLTFParserContext } from "./GLTFParserContext";
 
 export abstract class GLTFParser {
-  private static _extensionParsers: Record<string, GLTFExtensionParser<ExtensibleResource>[]> = {};
+  private static readonly _extensionParsers: Record<string, GLTFExtensionParser[]> = {};
 
-  static parseEngineResource(
-    extensionName: string,
-    context: GLTFParserContext,
-    parseResource: EngineObject,
-    extensionSchema: GLTFExtensionSchema,
-    resourceInfo: ExtensibleResource
-  ): void {
+  static initialize(extensionName: string): void | Promise<void> {
     const parsers = GLTFParser._extensionParsers[extensionName];
     const length = parsers?.length;
 
     if (length) {
-      if (length > 1) {
-        Logger.warn(`plugin:${extensionName} has been overridden`);
-      }
-      parsers[length - 1].parseEngineResource(context, parseResource, extensionSchema, resourceInfo);
+      return parsers[length - 1].initialize();
     }
   }
 
-  static createEngineResource(
+  static createAndParse(
     extensionName: string,
     context: GLTFParserContext,
     extensionSchema: GLTFExtensionSchema,
-    resourceInfo: ExtensibleResource
+    ownerSchema: GLTFExtensionOwnerSchema
   ): EngineObject | Promise<EngineObject> {
-    const parsers = GLTFParser._extensionParsers[extensionName];
-    const length = parsers?.length;
+    const parser = GLTFParser.getExtensionParser(extensionName, GLTFExtensionMode.CreateAndParse);
+    
+    if (parser) {
+      return parser.createAndParse(context, extensionSchema, ownerSchema);
+    }
+  }
 
-    if (length) {
-      if (length > 1) {
-        Logger.warn(`plugin:${extensionName} has been overridden`);
-      }
-      return parsers[length - 1].createEngineResource(context, extensionSchema, resourceInfo);
+  static additiveParse(
+    extensionName: string,
+    context: GLTFParserContext,
+    parseResource: EngineObject,
+    extensionSchema: GLTFExtensionSchema,
+    ownerSchema: GLTFExtensionOwnerSchema
+  ): void {
+    const parser = GLTFParser.getExtensionParser(extensionName, GLTFExtensionMode.AdditiveParse);
+
+    if (parser) {
+      parser.additiveParse(context, parseResource, extensionSchema, ownerSchema);
     }
   }
 
   static hasExtensionParser(extensionName: string): boolean {
-    const parsers = GLTFParser._extensionParsers[extensionName];
-    return !!parsers?.length;
+    return !!GLTFParser._extensionParsers[extensionName]?.length;
   }
 
-  static initialize(extensionName: string) {
+  static getExtensionParser(extensionName: string, mode: GLTFExtensionMode): GLTFExtensionParser | void {
     const parsers = GLTFParser._extensionParsers[extensionName];
+    const length = parsers?.length;
 
-    if (parsers?.length) {
-      for (let i = 0; i < parsers.length; i++) {
-        parsers[i].initialize();
+    if (length) {
+      // only use the last parser.
+      for (let i = length - 1; i >= 0; --i) {
+        const currentParser = parsers[i];
+        if (currentParser.mode === mode) {
+          return currentParser;
+        }
       }
     }
   }
@@ -60,7 +65,7 @@ export abstract class GLTFParser {
   /**
    * @internal
    */
-  static _addExtensionParser(extensionName: string, extensionParser: GLTFExtensionParser<ExtensibleResource>) {
+  static _addExtensionParser(extensionName: string, extensionParser: GLTFExtensionParser) {
     if (!GLTFParser._extensionParsers[extensionName]) {
       GLTFParser._extensionParsers[extensionName] = [];
     }
@@ -75,7 +80,7 @@ export abstract class GLTFParser {
  * @param extensionName - Extension name
  */
 export function registerGLTFExtension(extensionName: string) {
-  return (parser: new () => GLTFExtensionParser<ExtensibleResource>) => {
+  return (parser: new () => GLTFExtensionParser) => {
     const extensionParser = new parser();
 
     GLTFParser._addExtensionParser(extensionName, extensionParser);
diff --git a/packages/loader/src/gltf/parser/GLTFSceneParser.ts b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
index ebc82333a9..e6de556298 100644
--- a/packages/loader/src/gltf/parser/GLTFSceneParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
@@ -53,7 +53,7 @@ export class GLTFSceneParser extends GLTFParser {
         const lightIndex = KHR_lights_punctual.light;
         const lights = (gltf.extensions.KHR_lights_punctual as IKHRLightsPunctual).lights;
 
-        GLTFParser.parseEngineResource("KHR_lights_punctual", context, entity, lights[lightIndex], gltfNode);
+        GLTFParser.additiveParse("KHR_lights_punctual", context, entity, lights[lightIndex], gltfNode);
       }
     }
 
@@ -144,7 +144,7 @@ export class GLTFSceneParser extends GLTFParser {
       const { extensions = {} } = gltfPrimitive;
       const { KHR_materials_variants } = extensions;
       if (KHR_materials_variants) {
-        GLTFParser.parseEngineResource(
+        GLTFParser.additiveParse(
           "KHR_materials_variants",
           context,
           renderer,
diff --git a/packages/loader/src/gltf/parser/GLTFValidator.ts b/packages/loader/src/gltf/parser/GLTFValidator.ts
index 47bc17f6ab..560ea773f0 100644
--- a/packages/loader/src/gltf/parser/GLTFValidator.ts
+++ b/packages/loader/src/gltf/parser/GLTFValidator.ts
@@ -1,9 +1,9 @@
-import { Logger } from "@oasis-engine/core";
+import { AssetPromise, Logger } from "@oasis-engine/core";
 import { GLTFParser } from "./GLTFParser";
 import { GLTFParserContext } from "./GLTFParserContext";
 
 export class GLTFValidator extends GLTFParser {
-  parse(context: GLTFParserContext): void {
+  parse(context: GLTFParserContext): AssetPromise<void> {
     const {
       asset: { version },
       extensionsUsed,
@@ -14,7 +14,7 @@ export class GLTFValidator extends GLTFParser {
     if (!(gltfVersion >= 2 && gltfVersion < 3)) {
       throw "Only support gltf 2.x.";
     }
-
+    const promises = [];
     if (extensionsUsed) {
       Logger.info("extensionsUsed: ", extensionsUsed);
       for (let i = 0; i < extensionsUsed.length; i++) {
@@ -33,9 +33,11 @@ export class GLTFValidator extends GLTFParser {
         if (!GLTFParser.hasExtensionParser(extensionRequired)) {
           Logger.error(`GLTF parser has not supported required extension ${extensionRequired}.`);
         } else {
-          GLTFParser.initialize(extensionRequired);
+          promises.push(GLTFParser.initialize(extensionRequired));
         }
       }
     }
+
+    return AssetPromise.all(promises).then(null);
   }
 }

From ea1deea7d7f88b3e27b31802c3eb2f2dc9a99a39 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Tue, 28 Feb 2023 18:49:25 +0800
Subject: [PATCH 12/25] refactor: use decorator

---
 .../loader/src/gltf/extensions/GLTFExtensionParser.ts     | 7 +++++--
 .../src/gltf/extensions/KHR_draco_mesh_compression.ts     | 4 +---
 .../loader/src/gltf/extensions/KHR_lights_punctual.ts     | 4 +---
 .../loader/src/gltf/extensions/KHR_materials_clearcoat.ts | 4 +---
 .../extensions/KHR_materials_pbrSpecularGlossiness.ts     | 4 +---
 .../loader/src/gltf/extensions/KHR_materials_unlit.ts     | 4 +---
 .../loader/src/gltf/extensions/KHR_materials_variants.ts  | 4 +---
 .../loader/src/gltf/extensions/KHR_mesh_quantization.ts   | 6 ++----
 .../loader/src/gltf/extensions/KHR_texture_transform.ts   | 4 +---
 .../loader/src/gltf/extensions/OASIS_materials_remap.ts   | 4 +---
 packages/loader/src/gltf/parser/GLTFParser.ts             | 8 ++++----
 11 files changed, 19 insertions(+), 34 deletions(-)

diff --git a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
index d157e229fb..e1c49f57f7 100644
--- a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
@@ -7,8 +7,11 @@ import { GLTFExtensionSchema } from "./GLTFExtensionSchema";
  * Base class of glTF extension parser.
  */
 export abstract class GLTFExtensionParser {
-  /** The extension mode. */
-  abstract readonly mode: GLTFExtensionMode;
+  /**
+   * @internal
+   * The extension mode.
+   */
+  _mode: GLTFExtensionMode;
 
   /**
    * Some plugins require initialization.
diff --git a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
index 128dd824f5..9581410155 100644
--- a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
+++ b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
@@ -6,10 +6,8 @@ import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRDracoMeshCompression } from "./GLTFExtensionSchema";
 
-@registerGLTFExtension("KHR_draco_mesh_compression")
+@registerGLTFExtension("KHR_draco_mesh_compression", GLTFExtensionMode.CreateAndParse)
 class KHR_draco_mesh_compression extends GLTFExtensionParser {
-  mode = GLTFExtensionMode.CreateAndParse;
-
   private static _decoder: DRACODecoder;
 
   initialize(): void {
diff --git a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
index 6524feea51..d65d280cc2 100644
--- a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
+++ b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
@@ -4,10 +4,8 @@ import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRLightsPunctual_Light } from "./GLTFExtensionSchema";
 
-@registerGLTFExtension("KHR_lights_punctual")
+@registerGLTFExtension("KHR_lights_punctual", GLTFExtensionMode.AdditiveParse)
 class KHR_lights_punctual extends GLTFExtensionParser {
-  mode = GLTFExtensionMode.AdditiveParse;
-
   additiveParse(context: GLTFParserContext, entity: Entity, schema: IKHRLightsPunctual_Light): void {
     const { color, intensity = 1, type, range, spot } = schema;
     const glTFResource = context.glTFResource;
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
index 0f0334833c..3888fc8496 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
@@ -5,10 +5,8 @@ import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialsClearcoat } from "./GLTFExtensionSchema";
 
-@registerGLTFExtension("KHR_materials_clearcoat")
+@registerGLTFExtension("KHR_materials_clearcoat", GLTFExtensionMode.AdditiveParse)
 class KHR_materials_clearcoat extends GLTFExtensionParser {
-  mode = GLTFExtensionMode.AdditiveParse;
-
   additiveParse(context: GLTFParserContext, material: PBRMaterial, schema: IKHRMaterialsClearcoat): void {
     const { textures } = context.glTFResource;
     const {
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
index 6429a6ba5d..895a870869 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
@@ -7,10 +7,8 @@ import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialsPbrSpecularGlossiness } from "./GLTFExtensionSchema";
 
-@registerGLTFExtension("KHR_materials_pbrSpecularGlossiness")
+@registerGLTFExtension("KHR_materials_pbrSpecularGlossiness", GLTFExtensionMode.CreateAndParse)
 class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser {
-  mode = GLTFExtensionMode.CreateAndParse;
-
   createAndParse(
     context: GLTFParserContext,
     schema: IKHRMaterialsPbrSpecularGlossiness,
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
index b2b29f3d35..ea1185d490 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
@@ -5,10 +5,8 @@ import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 
-@registerGLTFExtension("KHR_materials_unlit")
+@registerGLTFExtension("KHR_materials_unlit", GLTFExtensionMode.CreateAndParse)
 class KHR_materials_unlit extends GLTFExtensionParser {
-  mode = GLTFExtensionMode.CreateAndParse;
-
   createAndParse(context: GLTFParserContext, _, ownerSchema: IMaterial): UnlitMaterial {
     const { engine } = context.glTFResource;
     const material = new UnlitMaterial(engine);
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
index eab77aa2e8..766f4992c3 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
@@ -4,10 +4,8 @@ import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialVariants_Mapping } from "./GLTFExtensionSchema";
 
-@registerGLTFExtension("KHR_materials_variants")
+@registerGLTFExtension("KHR_materials_variants", GLTFExtensionMode.AdditiveParse)
 class KHR_materials_variants extends GLTFExtensionParser {
-  mode = GLTFExtensionMode.AdditiveParse;
-
   additiveParse(context: GLTFParserContext, renderer: Renderer, schema: IKHRMaterialVariants_Mapping): void {
     const {
       gltf: {
diff --git a/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts b/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts
index ca9835b6ca..789dc4e274 100644
--- a/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts
+++ b/packages/loader/src/gltf/extensions/KHR_mesh_quantization.ts
@@ -1,7 +1,5 @@
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 
-@registerGLTFExtension("KHR_mesh_quantization")
-class KHR_mesh_quantization extends GLTFExtensionParser {
-  mode = GLTFExtensionMode.AdditiveParse;
-}
+@registerGLTFExtension("KHR_mesh_quantization", GLTFExtensionMode.AdditiveParse)
+class KHR_mesh_quantization extends GLTFExtensionParser {}
diff --git a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
index c5ccaeb69c..34f38e4726 100644
--- a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
+++ b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
@@ -4,10 +4,8 @@ import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRTextureTransform } from "./GLTFExtensionSchema";
 
-@registerGLTFExtension("KHR_texture_transform")
+@registerGLTFExtension("KHR_texture_transform", GLTFExtensionMode.AdditiveParse)
 class KHR_texture_transform extends GLTFExtensionParser {
-  mode = GLTFExtensionMode.AdditiveParse;
-
   additiveParse(
     context: GLTFParserContext,
     material: PBRBaseMaterial | UnlitMaterial,
diff --git a/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts b/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
index d7f7f785bc..2ba32ac237 100644
--- a/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
+++ b/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
@@ -4,10 +4,8 @@ import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IOasisMaterialRemap } from "./GLTFExtensionSchema";
 
-@registerGLTFExtension("OASIS_materials_remap")
+@registerGLTFExtension("OASIS_materials_remap", GLTFExtensionMode.CreateAndParse)
 class OasisMaterialsRemap extends GLTFExtensionParser {
-  mode = GLTFExtensionMode.CreateAndParse;
-
   createAndParse(context: GLTFParserContext, schema: IOasisMaterialRemap): Promise<Material> {
     const { engine } = context.glTFResource;
     // @ts-ignore
diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index 96b868a96e..929a2ac1c9 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -23,7 +23,7 @@ export abstract class GLTFParser {
     ownerSchema: GLTFExtensionOwnerSchema
   ): EngineObject | Promise<EngineObject> {
     const parser = GLTFParser.getExtensionParser(extensionName, GLTFExtensionMode.CreateAndParse);
-    
+
     if (parser) {
       return parser.createAndParse(context, extensionSchema, ownerSchema);
     }
@@ -55,7 +55,7 @@ export abstract class GLTFParser {
       // only use the last parser.
       for (let i = length - 1; i >= 0; --i) {
         const currentParser = parsers[i];
-        if (currentParser.mode === mode) {
+        if (currentParser._mode === mode) {
           return currentParser;
         }
       }
@@ -79,10 +79,10 @@ export abstract class GLTFParser {
  * Declare ExtensionParser's decorator.
  * @param extensionName - Extension name
  */
-export function registerGLTFExtension(extensionName: string) {
+export function registerGLTFExtension(extensionName: string, mode: GLTFExtensionMode) {
   return (parser: new () => GLTFExtensionParser) => {
     const extensionParser = new parser();
-
+    extensionParser._mode = mode;
     GLTFParser._addExtensionParser(extensionName, extensionParser);
   };
 }

From 74d2a020ee06b54aa465759d1bd53821915c3d54 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Tue, 28 Feb 2023 19:46:18 +0800
Subject: [PATCH 13/25] refactor: param

---
 .../KHR_materials_pbrSpecularGlossiness.ts    |  2 +-
 .../gltf/extensions/KHR_materials_unlit.ts    |  2 +-
 .../src/gltf/parser/GLTFMaterialParser.ts     | 50 +++++++++----------
 3 files changed, 25 insertions(+), 29 deletions(-)

diff --git a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
index 895a870869..db729ff2bc 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
@@ -53,7 +53,7 @@ class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser {
     }
 
     material.name = ownerSchema.name;
-    GLTFMaterialParser._parseGLTFMaterial(context, material, ownerSchema);
+    GLTFMaterialParser._parseStandardProperty(context, material, ownerSchema);
     return material;
   }
 }
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
index ea1185d490..813d5cf85f 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
@@ -12,7 +12,7 @@ class KHR_materials_unlit extends GLTFExtensionParser {
     const material = new UnlitMaterial(engine);
     material.name = ownerSchema.name;
 
-    GLTFMaterialParser._parseGLTFMaterial(context, material, ownerSchema);
+    GLTFMaterialParser._parseStandardProperty(context, material, ownerSchema);
     return material;
   }
 }
diff --git a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
index ad4b6ac489..f1413934be 100644
--- a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
@@ -3,16 +3,19 @@ import {
   BaseMaterial,
   Logger,
   Material,
-  PBRBaseMaterial,
   PBRMaterial,
+  PBRSpecularMaterial,
   RenderFace,
-  TextureCoordinate
+  TextureCoordinate,
+  UnlitMaterial
 } from "@oasis-engine/core";
 import { Color } from "@oasis-engine/math";
 import { IMaterial, ITextureInfo, MaterialAlphaMode } from "../GLTFSchema";
 import { GLTFParser } from "./GLTFParser";
 import { GLTFParserContext } from "./GLTFParserContext";
 
+type StandMaterialType = UnlitMaterial | PBRMaterial | PBRSpecularMaterial;
+
 export class GLTFMaterialParser extends GLTFParser {
   /**
    * @internal
@@ -35,14 +38,14 @@ export class GLTFMaterialParser extends GLTFParser {
       const materialInfo = gltf.materials[i];
       const { extensions = {}, name = "" } = materialInfo;
 
-      let material: BaseMaterial | Promise<BaseMaterial> = null;
+      let material: StandMaterialType | Promise<BaseMaterial> = null;
 
       const extensionArray = Object.keys(extensions);
       for (let i = extensionArray.length - 1; i >= 0; --i) {
         const extensionName = extensionArray[i];
         const extensionSchema = extensions[extensionName];
 
-        material = <Promise<BaseMaterial> | BaseMaterial>(
+        material = <StandMaterialType | Promise<BaseMaterial>>(
           GLTFParser.createAndParse(extensionName, context, extensionSchema, materialInfo)
         );
         if (material) {
@@ -53,7 +56,7 @@ export class GLTFMaterialParser extends GLTFParser {
       if (!material) {
         material = new PBRMaterial(engine);
         material.name = name;
-        GLTFMaterialParser._parseGLTFMaterial(context, material, materialInfo);
+        GLTFMaterialParser._parseStandardProperty(context, material, materialInfo);
       }
 
       materialPromises.push(material);
@@ -78,10 +81,9 @@ export class GLTFMaterialParser extends GLTFParser {
   /**
    * @internal
    */
-  static _parseGLTFMaterial(context: GLTFParserContext, material: BaseMaterial, materialInfo: IMaterial) {
+  static _parseStandardProperty(context: GLTFParserContext, material: StandMaterialType, materialInfo: IMaterial) {
     const { textures } = context.glTFResource;
     const {
-      extensions = {},
       pbrMetallicRoughness,
       normalTexture,
       occlusionTexture,
@@ -92,15 +94,12 @@ export class GLTFMaterialParser extends GLTFParser {
       doubleSided
     } = materialInfo;
 
-    const { KHR_materials_unlit, KHR_materials_pbrSpecularGlossiness, KHR_materials_clearcoat } = extensions;
-
     if (pbrMetallicRoughness) {
-      const m = material as PBRBaseMaterial;
       const { baseColorFactor, baseColorTexture, metallicFactor, roughnessFactor, metallicRoughnessTexture } =
         pbrMetallicRoughness;
 
       if (baseColorFactor) {
-        m.baseColor = new Color(
+        material.baseColor = new Color(
           Color.linearToGammaSpace(baseColorFactor[0]),
           Color.linearToGammaSpace(baseColorFactor[1]),
           Color.linearToGammaSpace(baseColorFactor[2]),
@@ -108,34 +107,31 @@ export class GLTFMaterialParser extends GLTFParser {
         );
       }
       if (baseColorTexture) {
-        m.baseTexture = textures[baseColorTexture.index];
+        material.baseTexture = textures[baseColorTexture.index];
         const KHR_texture_transform = baseColorTexture.extensions?.KHR_texture_transform;
         if (KHR_texture_transform) {
           GLTFParser.additiveParse("KHR_texture_transform", context, material, KHR_texture_transform, materialInfo);
         }
       }
 
-      if (!KHR_materials_unlit && !KHR_materials_pbrSpecularGlossiness) {
-        const m = material as PBRMaterial;
-        m.metallic = metallicFactor ?? 1;
-        m.roughness = roughnessFactor ?? 1;
+      if (material.constructor === PBRMaterial) {
+        material.metallic = metallicFactor ?? 1;
+        material.roughness = roughnessFactor ?? 1;
         if (metallicRoughnessTexture) {
-          m.roughnessMetallicTexture = textures[metallicRoughnessTexture.index];
+          material.roughnessMetallicTexture = textures[metallicRoughnessTexture.index];
           GLTFMaterialParser._checkOtherTextureTransform(metallicRoughnessTexture, "Roughness metallic");
         }
       }
     }
 
-    if (!KHR_materials_unlit) {
-      const m = material as PBRBaseMaterial;
-
+    if (material.constructor === PBRMaterial || material.constructor === PBRSpecularMaterial) {
       if (emissiveTexture) {
-        m.emissiveTexture = textures[emissiveTexture.index];
+        material.emissiveTexture = textures[emissiveTexture.index];
         GLTFMaterialParser._checkOtherTextureTransform(emissiveTexture, "Emissive");
       }
 
       if (emissiveFactor) {
-        m.emissiveColor = new Color(
+        material.emissiveColor = new Color(
           Color.linearToGammaSpace(emissiveFactor[0]),
           Color.linearToGammaSpace(emissiveFactor[1]),
           Color.linearToGammaSpace(emissiveFactor[2])
@@ -144,24 +140,24 @@ export class GLTFMaterialParser extends GLTFParser {
 
       if (normalTexture) {
         const { index, scale } = normalTexture;
-        m.normalTexture = textures[index];
+        material.normalTexture = textures[index];
         GLTFMaterialParser._checkOtherTextureTransform(normalTexture, "Normal");
 
         if (scale !== undefined) {
-          m.normalTextureIntensity = scale;
+          material.normalTextureIntensity = scale;
         }
       }
 
       if (occlusionTexture) {
         const { index, strength, texCoord } = occlusionTexture;
-        m.occlusionTexture = textures[index];
+        material.occlusionTexture = textures[index];
         GLTFMaterialParser._checkOtherTextureTransform(occlusionTexture, "Occlusion");
 
         if (strength !== undefined) {
-          m.occlusionTextureIntensity = strength;
+          material.occlusionTextureIntensity = strength;
         }
         if (texCoord === TextureCoordinate.UV1) {
-          m.occlusionTextureCoord = TextureCoordinate.UV1;
+          material.occlusionTextureCoord = TextureCoordinate.UV1;
         } else if (texCoord > TextureCoordinate.UV1) {
           Logger.warn("Occlusion texture uv coordinate must be UV0 or UV1.");
         }

From f1e60eb5098269d17bf9a50db954e55c8dc4fb6d Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Wed, 1 Mar 2023 11:56:48 +0800
Subject: [PATCH 14/25] refactor: add extension common parser

---
 .../KHR_materials_pbrSpecularGlossiness.ts    |  5 +--
 .../src/gltf/parser/GLTFMaterialParser.ts     | 29 +++-------------
 packages/loader/src/gltf/parser/GLTFParser.ts | 33 +++++++++++++++++++
 3 files changed, 38 insertions(+), 29 deletions(-)

diff --git a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
index db729ff2bc..f95795a999 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
@@ -29,10 +29,7 @@ class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser {
 
     if (diffuseTexture) {
       material.baseTexture = textures[diffuseTexture.index];
-      const KHR_texture_transform = diffuseTexture.extensions?.KHR_texture_transform;
-      if (KHR_texture_transform) {
-        GLTFParser.additiveParse("KHR_texture_transform", context, material, KHR_texture_transform, diffuseTexture);
-      }
+      GLTFParser.additiveParseFromExtensions(diffuseTexture.extensions, context, material, diffuseTexture);
     }
 
     if (specularFactor) {
diff --git a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
index f1413934be..17f061e351 100644
--- a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
@@ -36,22 +36,9 @@ export class GLTFMaterialParser extends GLTFParser {
 
     for (let i = 0; i < gltf.materials.length; i++) {
       const materialInfo = gltf.materials[i];
-      const { extensions = {}, name = "" } = materialInfo;
+      const { extensions, name = "" } = materialInfo;
 
-      let material: StandMaterialType | Promise<BaseMaterial> = null;
-
-      const extensionArray = Object.keys(extensions);
-      for (let i = extensionArray.length - 1; i >= 0; --i) {
-        const extensionName = extensionArray[i];
-        const extensionSchema = extensions[extensionName];
-
-        material = <StandMaterialType | Promise<BaseMaterial>>(
-          GLTFParser.createAndParse(extensionName, context, extensionSchema, materialInfo)
-        );
-        if (material) {
-          break;
-        }
-      }
+      let material: any = GLTFParser.createAndParseFromExtensions(extensions, context, materialInfo);
 
       if (!material) {
         material = new PBRMaterial(engine);
@@ -66,12 +53,7 @@ export class GLTFMaterialParser extends GLTFParser {
       glTFResource.materials = materials;
       for (let i = 0; i < gltf.materials.length; i++) {
         const materialInfo = gltf.materials[i];
-        const material = materials[i];
-        const { extensions } = materialInfo;
-        for (let extensionName in extensions) {
-          const extensionSchema = extensions[extensionName];
-          GLTFParser.additiveParse(extensionName, context, material, extensionSchema, materialInfo);
-        }
+        GLTFParser.additiveParseFromExtensions(materialInfo.extensions, context, materials[i], materialInfo);
       }
       materialsPromiseInfo.resolve(materials);
       return materialsPromiseInfo.promise;
@@ -108,10 +90,7 @@ export class GLTFMaterialParser extends GLTFParser {
       }
       if (baseColorTexture) {
         material.baseTexture = textures[baseColorTexture.index];
-        const KHR_texture_transform = baseColorTexture.extensions?.KHR_texture_transform;
-        if (KHR_texture_transform) {
-          GLTFParser.additiveParse("KHR_texture_transform", context, material, KHR_texture_transform, materialInfo);
-        }
+        GLTFParser.additiveParseFromExtensions(baseColorTexture.extensions, context, material, baseColorTexture);
       }
 
       if (material.constructor === PBRMaterial) {
diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index 929a2ac1c9..f9a9bc81c6 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -43,6 +43,39 @@ export abstract class GLTFParser {
     }
   }
 
+  static createAndParseFromExtensions(
+    extensions: { [key: string]: any } = {},
+    context: GLTFParserContext,
+    ownerSchema: GLTFExtensionOwnerSchema
+  ): EngineObject | void | Promise<EngineObject | void> {
+    let resource: EngineObject | Promise<EngineObject> = null;
+
+    const extensionArray = Object.keys(extensions);
+    for (let i = extensionArray.length - 1; i >= 0; --i) {
+      const extensionName = extensionArray[i];
+      const extensionSchema = extensions[extensionName];
+
+      resource = <EngineObject | Promise<EngineObject>>(
+        GLTFParser.createAndParse(extensionName, context, extensionSchema, ownerSchema)
+      );
+      if (resource) {
+        return resource;
+      }
+    }
+  }
+
+  static additiveParseFromExtensions(
+    extensions: { [key: string]: any },
+    context: GLTFParserContext,
+    parseResource: EngineObject,
+    ownerSchema: GLTFExtensionOwnerSchema
+  ): void {
+    for (let extensionName in extensions) {
+      const extensionSchema = extensions[extensionName];
+      GLTFParser.additiveParse(extensionName, context, parseResource, extensionSchema, ownerSchema);
+    }
+  }
+
   static hasExtensionParser(extensionName: string): boolean {
     return !!GLTFParser._extensionParsers[extensionName]?.length;
   }

From 9043190835d84cc3c58d111762add6c02e5a54e0 Mon Sep 17 00:00:00 2001
From: ChenMo <gl3336563@163.com>
Date: Wed, 1 Mar 2023 12:12:57 +0800
Subject: [PATCH 15/25] refactor: opt GLTFLoader code (#6)

* refactor: opt GLTFLoader code
---
 packages/loader/src/GLTFLoader.ts                | 12 +++++++-----
 packages/loader/src/gltf/GLTFPipeline.ts         | 15 ++++++++++++++-
 packages/loader/src/gltf/GLTFSchema.ts           |  1 +
 .../src/gltf/extensions/GLTFExtensionParser.ts   | 16 +++++++++-------
 .../extensions/KHR_draco_mesh_compression.ts     |  6 ++++++
 .../src/gltf/extensions/KHR_lights_punctual.ts   |  3 +++
 .../gltf/extensions/KHR_materials_clearcoat.ts   |  3 +++
 .../KHR_materials_pbrSpecularGlossiness.ts       |  4 ++++
 .../src/gltf/extensions/KHR_materials_unlit.ts   |  4 ++++
 .../gltf/extensions/KHR_materials_variants.ts    |  4 ++++
 .../src/gltf/extensions/KHR_texture_transform.ts |  4 ++++
 .../src/gltf/extensions/OASIS_materials_remap.ts |  3 +++
 12 files changed, 62 insertions(+), 13 deletions(-)

diff --git a/packages/loader/src/GLTFLoader.ts b/packages/loader/src/GLTFLoader.ts
index 4c674c5a4e..ad710991eb 100644
--- a/packages/loader/src/GLTFLoader.ts
+++ b/packages/loader/src/GLTFLoader.ts
@@ -6,14 +6,14 @@ import { GLTFParserContext } from "./gltf/parser/GLTFParserContext";
 @resourceLoader(AssetType.Prefab, ["gltf", "glb"])
 export class GLTFLoader extends Loader<GLTFResource> {
   load(item: LoadItem, resourceManager: ResourceManager): Record<string, AssetPromise<any>> {
-    const url = item.url;
-    const { keepMeshData = false, pipeline } = item.params || {};
+    const { url } = item;
+    const params = <GLTFParams>item.params;
     const context = new GLTFParserContext(url);
     const glTFResource = new GLTFResource(resourceManager.engine, url);
     const masterPromiseInfo = context.masterPromiseInfo;
 
     context.glTFResource = glTFResource;
-    context.keepMeshData = keepMeshData;
+    context.keepMeshData = params.keepMeshData ?? false;
 
     masterPromiseInfo.onCancel(() => {
       const { chainPromises } = context;
@@ -22,8 +22,8 @@ export class GLTFLoader extends Loader<GLTFResource> {
       }
     });
 
-    (pipeline || GLTFPipeline.defaultPipeline)
-      .parse(context)
+    (params.pipeline || GLTFPipeline.defaultPipeline)
+      ._parse(context)
       .then(masterPromiseInfo.resolve)
       .catch((e) => {
         console.error(e);
@@ -40,4 +40,6 @@ export class GLTFLoader extends Loader<GLTFResource> {
 export interface GLTFParams {
   /** Keep raw mesh data for glTF parser, default is false. */
   keepMeshData: boolean;
+  /** Custom glTF pipeline. */
+  pipeline: GLTFPipeline;
 }
diff --git a/packages/loader/src/gltf/GLTFPipeline.ts b/packages/loader/src/gltf/GLTFPipeline.ts
index d947328532..b9ae25f638 100644
--- a/packages/loader/src/gltf/GLTFPipeline.ts
+++ b/packages/loader/src/gltf/GLTFPipeline.ts
@@ -12,7 +12,13 @@ import { GLTFSkinParser } from "./parser/GLTFSkinParser";
 import { GLTFTextureParser } from "./parser/GLTFTextureParser";
 import { GLTFValidator } from "./parser/GLTFValidator";
 
+/**
+ * GLTF pipeline.
+ */
 export class GLTFPipeline {
+  /**
+   * Default pipeline.
+   */
   static defaultPipeline = new GLTFPipeline(
     GLTFBufferParser,
     GLTFValidator,
@@ -27,13 +33,20 @@ export class GLTFPipeline {
 
   private _parsers: GLTFParser[] = [];
 
+  /**
+   * Constructor of GLTFPipeline.
+   * @param parsers - Parsers to be executed in order
+   */
   constructor(...parsers: (new () => GLTFParser)[]) {
     parsers.forEach((pipe: new () => GLTFParser, index: number) => {
       this._parsers[index] = new pipe();
     });
   }
 
-  parse(context: GLTFParserContext): AssetPromise<GLTFResource> {
+  /**
+   * @internal
+   */
+  _parse(context: GLTFParserContext): AssetPromise<GLTFResource> {
     const glTFResource = context.glTFResource;
     let lastParser;
 
diff --git a/packages/loader/src/gltf/GLTFSchema.ts b/packages/loader/src/gltf/GLTFSchema.ts
index 67b3d2dd38..5e1f0f9ca2 100644
--- a/packages/loader/src/gltf/GLTFSchema.ts
+++ b/packages/loader/src/gltf/GLTFSchema.ts
@@ -854,4 +854,5 @@ export interface IGLTF extends IProperty {
   textures?: ITexture[];
 }
 
+/** glTF extensible owner schema. */
 export type GLTFExtensionOwnerSchema = IMeshPrimitive | IMaterial | ITextureInfo | INode;
diff --git a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
index e1c49f57f7..2c559fc4e5 100644
--- a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
@@ -14,22 +14,24 @@ export abstract class GLTFExtensionParser {
   _mode: GLTFExtensionMode;
 
   /**
-   * Some plugins require initialization.
+   * Initialize the parser.
+   * @remarks Some plugins require initialization.
+   * @returns The void or promise
    */
   initialize(): void | Promise<void> {}
 
   /**
-   * Create a resource instance.
-   * @remarks This method overrides the default resource creation
+   * Create and parse the resource.
+   * @remarks This method overrides the default resource creation.
    * @param context - The parser context
    * @param extensionSchema - The extension schema
-   * @param ownerSchema - The extension owner schema
+   * @param extensionOwnerSchema - The extension owner schema
    * @returns The resource or promise
    */
   createAndParse(
     context: GLTFParserContext,
     extensionSchema: GLTFExtensionSchema,
-    ownerSchema: GLTFExtensionOwnerSchema
+    extensionOwnerSchema: GLTFExtensionOwnerSchema
   ): EngineObject | Promise<EngineObject> {
     throw "Not implemented.";
   }
@@ -39,14 +41,14 @@ export abstract class GLTFExtensionParser {
    * @param context - The parser context
    * @param resource - The resource
    * @param extensionSchema - The extension schema
-   * @param ownerSchema - The extension owner schema
+   * @param extensionOwnerSchema - The extension owner schema
    * @returns The void or promise
    */
   additiveParse(
     context: GLTFParserContext,
     resource: EngineObject,
     extensionSchema: GLTFExtensionSchema,
-    ownerSchema: GLTFExtensionOwnerSchema
+    extensionOwnerSchema: GLTFExtensionOwnerSchema
   ): void | Promise<void> {
     throw "Not implemented.";
   }
diff --git a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
index 9581410155..65fe1e3ef6 100644
--- a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
+++ b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
@@ -10,12 +10,18 @@ import { IKHRDracoMeshCompression } from "./GLTFExtensionSchema";
 class KHR_draco_mesh_compression extends GLTFExtensionParser {
   private static _decoder: DRACODecoder;
 
+  /**
+   * @override
+   */
   initialize(): void {
     if (!KHR_draco_mesh_compression._decoder) {
       KHR_draco_mesh_compression._decoder = new DRACODecoder();
     }
   }
 
+  /**
+   * @override
+   */
   createAndParse(context: GLTFParserContext, schema: IKHRDracoMeshCompression, gltfPrimitive: IMeshPrimitive) {
     const { gltf, buffers } = context;
     const { bufferViews, accessors } = gltf;
diff --git a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
index d65d280cc2..9a3efccf21 100644
--- a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
+++ b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
@@ -6,6 +6,9 @@ import { IKHRLightsPunctual_Light } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_lights_punctual", GLTFExtensionMode.AdditiveParse)
 class KHR_lights_punctual extends GLTFExtensionParser {
+  /**
+   * @override
+   */
   additiveParse(context: GLTFParserContext, entity: Entity, schema: IKHRLightsPunctual_Light): void {
     const { color, intensity = 1, type, range, spot } = schema;
     const glTFResource = context.glTFResource;
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
index 3888fc8496..8e060fa264 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts
@@ -7,6 +7,9 @@ import { IKHRMaterialsClearcoat } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_clearcoat", GLTFExtensionMode.AdditiveParse)
 class KHR_materials_clearcoat extends GLTFExtensionParser {
+  /**
+   * @override
+   */
   additiveParse(context: GLTFParserContext, material: PBRMaterial, schema: IKHRMaterialsClearcoat): void {
     const { textures } = context.glTFResource;
     const {
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
index f95795a999..43351a8420 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
@@ -9,6 +9,10 @@ import { IKHRMaterialsPbrSpecularGlossiness } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_pbrSpecularGlossiness", GLTFExtensionMode.CreateAndParse)
 class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser {
+  
+  /**
+   * @override
+   */
   createAndParse(
     context: GLTFParserContext,
     schema: IKHRMaterialsPbrSpecularGlossiness,
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
index 813d5cf85f..c7fe542edd 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
@@ -7,6 +7,10 @@ import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 
 @registerGLTFExtension("KHR_materials_unlit", GLTFExtensionMode.CreateAndParse)
 class KHR_materials_unlit extends GLTFExtensionParser {
+  
+  /**
+   * @override
+   */
   createAndParse(context: GLTFParserContext, _, ownerSchema: IMaterial): UnlitMaterial {
     const { engine } = context.glTFResource;
     const material = new UnlitMaterial(engine);
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
index 766f4992c3..00a6cfb9b9 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
@@ -6,6 +6,10 @@ import { IKHRMaterialVariants_Mapping } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_variants", GLTFExtensionMode.AdditiveParse)
 class KHR_materials_variants extends GLTFExtensionParser {
+
+  /**
+   * @override
+   */
   additiveParse(context: GLTFParserContext, renderer: Renderer, schema: IKHRMaterialVariants_Mapping): void {
     const {
       gltf: {
diff --git a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
index 34f38e4726..ccd1a19d35 100644
--- a/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
+++ b/packages/loader/src/gltf/extensions/KHR_texture_transform.ts
@@ -6,6 +6,10 @@ import { IKHRTextureTransform } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_texture_transform", GLTFExtensionMode.AdditiveParse)
 class KHR_texture_transform extends GLTFExtensionParser {
+  
+  /**
+   * @override
+   */
   additiveParse(
     context: GLTFParserContext,
     material: PBRBaseMaterial | UnlitMaterial,
diff --git a/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts b/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
index 2ba32ac237..3c992e8f65 100644
--- a/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
+++ b/packages/loader/src/gltf/extensions/OASIS_materials_remap.ts
@@ -6,6 +6,9 @@ import { IOasisMaterialRemap } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("OASIS_materials_remap", GLTFExtensionMode.CreateAndParse)
 class OasisMaterialsRemap extends GLTFExtensionParser {
+  /**
+   * @override
+   */
   createAndParse(context: GLTFParserContext, schema: IOasisMaterialRemap): Promise<Material> {
     const { engine } = context.glTFResource;
     // @ts-ignore

From be6b1d476b9e0eb9063beb89dc52fda178a4f789 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Wed, 1 Mar 2023 14:29:13 +0800
Subject: [PATCH 16/25] refactor: draco

---
 packages/loader/src/GLTFLoader.ts             |   4 +-
 .../gltf/extensions/GLTFExtensionParser.ts    |   6 +-
 .../extensions/KHR_draco_mesh_compression.ts  | 169 ++++++++++-
 .../gltf/extensions/KHR_materials_unlit.ts    |   1 -
 .../src/gltf/parser/GLTFMaterialParser.ts     |  67 ++---
 .../loader/src/gltf/parser/GLTFMeshParser.ts  | 284 +++++-------------
 packages/loader/src/gltf/parser/GLTFParser.ts |  20 +-
 7 files changed, 284 insertions(+), 267 deletions(-)

diff --git a/packages/loader/src/GLTFLoader.ts b/packages/loader/src/GLTFLoader.ts
index ad710991eb..990a5c35fd 100644
--- a/packages/loader/src/GLTFLoader.ts
+++ b/packages/loader/src/GLTFLoader.ts
@@ -13,7 +13,7 @@ export class GLTFLoader extends Loader<GLTFResource> {
     const masterPromiseInfo = context.masterPromiseInfo;
 
     context.glTFResource = glTFResource;
-    context.keepMeshData = params.keepMeshData ?? false;
+    context.keepMeshData = params?.keepMeshData ?? false;
 
     masterPromiseInfo.onCancel(() => {
       const { chainPromises } = context;
@@ -22,7 +22,7 @@ export class GLTFLoader extends Loader<GLTFResource> {
       }
     });
 
-    (params.pipeline || GLTFPipeline.defaultPipeline)
+    (params?.pipeline || GLTFPipeline.defaultPipeline)
       ._parse(context)
       .then(masterPromiseInfo.resolve)
       .catch((e) => {
diff --git a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
index 2c559fc4e5..3fb0fad138 100644
--- a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
@@ -31,7 +31,8 @@ export abstract class GLTFExtensionParser {
   createAndParse(
     context: GLTFParserContext,
     extensionSchema: GLTFExtensionSchema,
-    extensionOwnerSchema: GLTFExtensionOwnerSchema
+    extensionOwnerSchema: GLTFExtensionOwnerSchema,
+    ...extra
   ): EngineObject | Promise<EngineObject> {
     throw "Not implemented.";
   }
@@ -48,7 +49,8 @@ export abstract class GLTFExtensionParser {
     context: GLTFParserContext,
     resource: EngineObject,
     extensionSchema: GLTFExtensionSchema,
-    extensionOwnerSchema: GLTFExtensionOwnerSchema
+    extensionOwnerSchema: GLTFExtensionOwnerSchema,
+    ...extra
   ): void | Promise<void> {
     throw "Not implemented.";
   }
diff --git a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
index 65fe1e3ef6..5d079b46f2 100644
--- a/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
+++ b/packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
@@ -1,6 +1,9 @@
+import { ModelMesh, TypedArray } from "@oasis-engine/core";
 import { DRACODecoder } from "@oasis-engine/draco";
-import { IMeshPrimitive } from "../GLTFSchema";
+import { Vector3 } from "@oasis-engine/math";
+import { AccessorType, IGLTF, IMesh, IMeshPrimitive } from "../GLTFSchema";
 import { GLTFUtil } from "../GLTFUtil";
+import { GLTFMeshParser } from "../parser";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
@@ -9,6 +12,7 @@ import { IKHRDracoMeshCompression } from "./GLTFExtensionSchema";
 @registerGLTFExtension("KHR_draco_mesh_compression", GLTFExtensionMode.CreateAndParse)
 class KHR_draco_mesh_compression extends GLTFExtensionParser {
   private static _decoder: DRACODecoder;
+  private static _tempVector3 = new Vector3();
 
   /**
    * @override
@@ -22,8 +26,17 @@ class KHR_draco_mesh_compression extends GLTFExtensionParser {
   /**
    * @override
    */
-  createAndParse(context: GLTFParserContext, schema: IKHRDracoMeshCompression, gltfPrimitive: IMeshPrimitive) {
-    const { gltf, buffers } = context;
+  createAndParse(
+    context: GLTFParserContext,
+    schema: IKHRDracoMeshCompression,
+    gltfPrimitive: IMeshPrimitive,
+    gltfMesh: IMesh
+  ) {
+    const {
+      gltf,
+      buffers,
+      glTFResource: { engine }
+    } = context;
     const { bufferViews, accessors } = gltf;
     const { bufferView: bufferViewIndex, attributes: gltfAttributeMap } = schema;
 
@@ -47,6 +60,154 @@ class KHR_draco_mesh_compression extends GLTFExtensionParser {
       indexType
     };
     const buffer = GLTFUtil.getBufferViewData(bufferViews[bufferViewIndex], buffers);
-    return KHR_draco_mesh_compression._decoder.decode(buffer, taskConfig).then((parsedGeometry) => parsedGeometry);
+    return KHR_draco_mesh_compression._decoder.decode(buffer, taskConfig).then((decodedGeometry) => {
+      const mesh = new ModelMesh(engine, gltfMesh.name);
+      return this._parseMeshFromGLTFPrimitiveDraco(
+        mesh,
+        gltfMesh,
+        gltfPrimitive,
+        gltf,
+        (attributeSemantic) => {
+          for (let j = 0; j < decodedGeometry.attributes.length; j++) {
+            if (decodedGeometry.attributes[j].name === attributeSemantic) {
+              return decodedGeometry.attributes[j].array;
+            }
+          }
+          return null;
+        },
+        (attributeSemantic, shapeIndex) => {
+          throw "BlendShape animation is not supported when using draco.";
+        },
+        () => {
+          return decodedGeometry.index.array;
+        },
+        context.keepMeshData
+      );
+    });
+  }
+
+  private _parseMeshFromGLTFPrimitiveDraco(
+    mesh: ModelMesh,
+    gltfMesh: IMesh,
+    gltfPrimitive: IMeshPrimitive,
+    gltf: IGLTF,
+    getVertexBufferData: (semantic: string) => TypedArray,
+    getBlendShapeData: (semantic: string, shapeIndex: number) => TypedArray,
+    getIndexBufferData: () => TypedArray,
+    keepMeshData: boolean
+  ): Promise<ModelMesh> {
+    const { attributes, targets, indices, mode } = gltfPrimitive;
+    let vertexCount: number;
+
+    const { accessors } = gltf;
+    const accessor = accessors[attributes["POSITION"]];
+    const positionBuffer = <Float32Array>getVertexBufferData("POSITION");
+    const positions = GLTFUtil.floatBufferToVector3Array(positionBuffer);
+    mesh.setPositions(positions);
+
+    const { bounds } = mesh;
+    vertexCount = accessor.count;
+    if (accessor.min && accessor.max) {
+      bounds.min.copyFromArray(accessor.min);
+      bounds.max.copyFromArray(accessor.max);
+    } else {
+      const position = KHR_draco_mesh_compression._tempVector3;
+      const { min, max } = bounds;
+
+      min.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+      max.set(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
+
+      const stride = positionBuffer.length / vertexCount;
+      for (let j = 0; j < vertexCount; j++) {
+        const offset = j * stride;
+        position.copyFromArray(positionBuffer, offset);
+        Vector3.min(min, position, min);
+        Vector3.max(max, position, max);
+      }
+    }
+
+    for (const attributeSemantic in attributes) {
+      if (attributeSemantic === "POSITION") {
+        continue;
+      }
+      const bufferData = getVertexBufferData(attributeSemantic);
+      switch (attributeSemantic) {
+        case "NORMAL":
+          const normals = GLTFUtil.floatBufferToVector3Array(<Float32Array>bufferData);
+          mesh.setNormals(normals);
+          break;
+        case "TEXCOORD_0":
+          const texturecoords = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
+          mesh.setUVs(texturecoords, 0);
+          break;
+        case "TEXCOORD_1":
+          const texturecoords1 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
+          mesh.setUVs(texturecoords1, 1);
+          break;
+        case "TEXCOORD_2":
+          const texturecoords2 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
+          mesh.setUVs(texturecoords2, 2);
+          break;
+        case "TEXCOORD_3":
+          const texturecoords3 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
+          mesh.setUVs(texturecoords3, 3);
+          break;
+        case "TEXCOORD_4":
+          const texturecoords4 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
+          mesh.setUVs(texturecoords4, 4);
+          break;
+        case "TEXCOORD_5":
+          const texturecoords5 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
+          mesh.setUVs(texturecoords5, 5);
+          break;
+        case "TEXCOORD_6":
+          const texturecoords6 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
+          mesh.setUVs(texturecoords6, 6);
+          break;
+        case "TEXCOORD_7":
+          const texturecoords7 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
+          mesh.setUVs(texturecoords7, 7);
+          break;
+        case "COLOR_0":
+          const colors = GLTFUtil.floatBufferToColorArray(
+            <Float32Array>bufferData,
+            accessors[attributes["COLOR_0"]].type === AccessorType.VEC3
+          );
+          mesh.setColors(colors);
+          break;
+        case "TANGENT":
+          const tangents = GLTFUtil.floatBufferToVector4Array(<Float32Array>bufferData);
+          mesh.setTangents(tangents);
+          break;
+
+        case "JOINTS_0":
+          const joints = GLTFUtil.floatBufferToVector4Array(<Float32Array>bufferData);
+          mesh.setBoneIndices(joints);
+          break;
+        case "WEIGHTS_0":
+          const weights = GLTFUtil.floatBufferToVector4Array(<Float32Array>bufferData);
+          mesh.setBoneWeights(weights);
+          break;
+        default:
+          // console.warn(`Unsupport attribute semantic ${attributeSemantic}.`);
+          break;
+      }
+    }
+
+    // Indices
+    if (indices !== undefined) {
+      const indexAccessor = gltf.accessors[indices];
+      const indexData = getIndexBufferData();
+      mesh.setIndices(<Uint8Array | Uint16Array | Uint32Array>indexData);
+      mesh.addSubMesh(0, indexAccessor.count, mode);
+    } else {
+      mesh.addSubMesh(0, vertexCount, mode);
+    }
+
+    // BlendShapes
+    targets && GLTFMeshParser._createBlendShape(mesh, gltfMesh, targets, getBlendShapeData);
+
+    mesh.uploadData(!keepMeshData);
+    return Promise.resolve(mesh);
   }
 }
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
index c7fe542edd..0ab7bd0745 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_unlit.ts
@@ -7,7 +7,6 @@ import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 
 @registerGLTFExtension("KHR_materials_unlit", GLTFExtensionMode.CreateAndParse)
 class KHR_materials_unlit extends GLTFExtensionParser {
-  
   /**
    * @override
    */
diff --git a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
index 17f061e351..86e8b5cc73 100644
--- a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
@@ -26,40 +26,6 @@ export class GLTFMaterialParser extends GLTFParser {
     }
   }
 
-  parse(context: GLTFParserContext): AssetPromise<Material[]> {
-    const { gltf, glTFResource, materialsPromiseInfo } = context;
-    if (!gltf.materials) return;
-
-    const { engine } = glTFResource;
-
-    let materialPromises = [];
-
-    for (let i = 0; i < gltf.materials.length; i++) {
-      const materialInfo = gltf.materials[i];
-      const { extensions, name = "" } = materialInfo;
-
-      let material: any = GLTFParser.createAndParseFromExtensions(extensions, context, materialInfo);
-
-      if (!material) {
-        material = new PBRMaterial(engine);
-        material.name = name;
-        GLTFMaterialParser._parseStandardProperty(context, material, materialInfo);
-      }
-
-      materialPromises.push(material);
-    }
-
-    return AssetPromise.all(materialPromises).then((materials) => {
-      glTFResource.materials = materials;
-      for (let i = 0; i < gltf.materials.length; i++) {
-        const materialInfo = gltf.materials[i];
-        GLTFParser.additiveParseFromExtensions(materialInfo.extensions, context, materials[i], materialInfo);
-      }
-      materialsPromiseInfo.resolve(materials);
-      return materialsPromiseInfo.promise;
-    });
-  }
-
   /**
    * @internal
    */
@@ -161,4 +127,37 @@ export class GLTFMaterialParser extends GLTFParser {
         break;
     }
   }
+
+  parse(context: GLTFParserContext): AssetPromise<Material[]> {
+    const { gltf, glTFResource, materialsPromiseInfo } = context;
+    if (!gltf.materials) return;
+
+    const { engine } = glTFResource;
+
+    let materialPromises = [];
+
+    for (let i = 0; i < gltf.materials.length; i++) {
+      const materialInfo = gltf.materials[i];
+
+      let material: any = GLTFParser.createAndParseFromExtensions(materialInfo.extensions, context, materialInfo);
+
+      if (!material) {
+        material = new PBRMaterial(engine);
+        material.name = materialInfo.name;
+        GLTFMaterialParser._parseStandardProperty(context, material, materialInfo);
+      }
+
+      materialPromises.push(material);
+    }
+
+    return AssetPromise.all(materialPromises).then((materials) => {
+      glTFResource.materials = materials;
+      for (let i = 0; i < gltf.materials.length; i++) {
+        const materialInfo = gltf.materials[i];
+        GLTFParser.additiveParseFromExtensions(materialInfo.extensions, context, materials[i], materialInfo);
+      }
+      materialsPromiseInfo.resolve(materials);
+      return materialsPromiseInfo.promise;
+    });
+  }
 }
diff --git a/packages/loader/src/gltf/parser/GLTFMeshParser.ts b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
index 1295738923..7c5729a360 100644
--- a/packages/loader/src/gltf/parser/GLTFMeshParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
@@ -4,117 +4,23 @@ import {
   Buffer,
   BufferBindFlag,
   BufferUsage,
-  EngineObject,
   ModelMesh,
   TypedArray,
   VertexElement
 } from "@oasis-engine/core";
 import { Vector3 } from "@oasis-engine/math";
+import { IGLTF, IMesh, IMeshPrimitive } from "../GLTFSchema";
 import { GLTFUtil } from "../GLTFUtil";
-import { AccessorType, IGLTF, IMesh, IMeshPrimitive } from "../GLTFSchema";
 import { GLTFParser } from "./GLTFParser";
 import { GLTFParserContext } from "./GLTFParserContext";
 
 export class GLTFMeshParser extends GLTFParser {
   private static _tempVector3 = new Vector3();
 
-  parse(context: GLTFParserContext) {
-    const { gltf, buffers, glTFResource } = context;
-    const { engine } = glTFResource;
-    if (!gltf.meshes) return;
-
-    const meshesPromiseInfo = context.meshesPromiseInfo;
-    const meshPromises: Promise<ModelMesh[]>[] = [];
-
-    for (let i = 0; i < gltf.meshes.length; i++) {
-      const gltfMesh = gltf.meshes[i];
-      const primitivePromises: Promise<ModelMesh>[] = [];
-
-      for (let j = 0; j < gltfMesh.primitives.length; j++) {
-        const gltfPrimitive = gltfMesh.primitives[j];
-        const { extensions = {} } = gltfPrimitive;
-        const { KHR_draco_mesh_compression } = extensions;
-
-        primitivePromises[j] = new Promise((resolve) => {
-          const mesh = new ModelMesh(engine, gltfMesh.name || j + "");
-
-          if (KHR_draco_mesh_compression) {
-            (<Promise<EngineObject>>(
-              GLTFParser.createAndParse(
-                "KHR_draco_mesh_compression",
-                context,
-                KHR_draco_mesh_compression,
-                gltfPrimitive
-              )
-            ))
-              .then((decodedGeometry: any) => {
-                return this._parseMeshFromGLTFPrimitiveDraco(
-                  mesh,
-                  gltfMesh,
-                  gltfPrimitive,
-                  gltf,
-                  (attributeSemantic) => {
-                    for (let j = 0; j < decodedGeometry.attributes.length; j++) {
-                      if (decodedGeometry.attributes[j].name === attributeSemantic) {
-                        return decodedGeometry.attributes[j].array;
-                      }
-                    }
-                    return null;
-                  },
-                  (attributeSemantic, shapeIndex) => {
-                    throw "BlendShape animation is not supported when using draco.";
-                  },
-                  () => {
-                    return decodedGeometry.index.array;
-                  },
-                  context.keepMeshData
-                );
-              })
-              .then(resolve);
-          } else {
-            this._parseMeshFromGLTFPrimitive(
-              context,
-              mesh,
-              gltfMesh,
-              gltfPrimitive,
-              gltf,
-              (attributeSemantic) => {
-                return null;
-              },
-              (attributeName, shapeIndex) => {
-                const shapeAccessorIdx = gltfPrimitive.targets[shapeIndex];
-                const attributeAccessorIdx = shapeAccessorIdx[attributeName];
-                if (attributeAccessorIdx) {
-                  const accessor = gltf.accessors[attributeAccessorIdx];
-                  return GLTFUtil.getAccessorData(gltf, accessor, buffers);
-                } else {
-                  return null;
-                }
-              },
-              () => {
-                const indexAccessor = gltf.accessors[gltfPrimitive.indices];
-                return GLTFUtil.getAccessorData(gltf, indexAccessor, buffers);
-              },
-              context.keepMeshData
-            ).then(resolve);
-          }
-        });
-      }
-
-      meshPromises[i] = Promise.all(primitivePromises);
-    }
-
-    AssetPromise.all(meshPromises)
-      .then((meshes: ModelMesh[][]) => {
-        glTFResource.meshes = meshes;
-        meshesPromiseInfo.resolve(meshes);
-      })
-      .catch(meshesPromiseInfo.reject);
-
-    return meshesPromiseInfo.promise;
-  }
-
-  private _parseMeshFromGLTFPrimitive(
+  /**
+   * @internal
+   */
+  static _parseMeshFromGLTFPrimitive(
     context: GLTFParserContext,
     mesh: ModelMesh,
     gltfMesh: IMesh,
@@ -215,13 +121,16 @@ export class GLTFMeshParser extends GLTFParser {
     }
 
     // BlendShapes
-    targets && this._createBlendShape(mesh, gltfMesh, targets, getBlendShapeData);
+    targets && GLTFMeshParser._createBlendShape(mesh, gltfMesh, targets, getBlendShapeData);
 
     mesh.uploadData(!keepMeshData);
     return Promise.resolve(mesh);
   }
 
-  private _createBlendShape(
+  /**
+   * @internal
+   */
+  static _createBlendShape(
     mesh: ModelMesh,
     glTFMesh: IMesh,
     glTFTargets: {
@@ -246,131 +155,74 @@ export class GLTFMeshParser extends GLTFParser {
     }
   }
 
-  /**
-   * @deprecated
-   */
-  private _parseMeshFromGLTFPrimitiveDraco(
-    mesh: ModelMesh,
-    gltfMesh: IMesh,
-    gltfPrimitive: IMeshPrimitive,
-    gltf: IGLTF,
-    getVertexBufferData: (semantic: string) => TypedArray,
-    getBlendShapeData: (semantic: string, shapeIndex: number) => TypedArray,
-    getIndexBufferData: () => TypedArray,
-    keepMeshData: boolean
-  ): Promise<ModelMesh> {
-    const { attributes, targets, indices, mode } = gltfPrimitive;
-    let vertexCount: number;
-
-    const { accessors } = gltf;
-    const accessor = accessors[attributes["POSITION"]];
-    const positionBuffer = <Float32Array>getVertexBufferData("POSITION");
-    const positions = GLTFUtil.floatBufferToVector3Array(positionBuffer);
-    mesh.setPositions(positions);
+  parse(context: GLTFParserContext) {
+    const { gltf, buffers, glTFResource } = context;
+    const { engine } = glTFResource;
+    if (!gltf.meshes) return;
 
-    const { bounds } = mesh;
-    vertexCount = accessor.count;
-    if (accessor.min && accessor.max) {
-      bounds.min.copyFromArray(accessor.min);
-      bounds.max.copyFromArray(accessor.max);
-    } else {
-      const position = GLTFMeshParser._tempVector3;
-      const { min, max } = bounds;
+    const meshesPromiseInfo = context.meshesPromiseInfo;
+    const meshPromises: Promise<ModelMesh[]>[] = [];
 
-      min.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
-      max.set(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
+    for (let i = 0; i < gltf.meshes.length; i++) {
+      const gltfMesh = gltf.meshes[i];
+      const primitivePromises: Promise<ModelMesh>[] = [];
 
-      const stride = positionBuffer.length / vertexCount;
-      for (let j = 0; j < vertexCount; j++) {
-        const offset = j * stride;
-        position.copyFromArray(positionBuffer, offset);
-        Vector3.min(min, position, min);
-        Vector3.max(max, position, max);
-      }
-    }
+      for (let j = 0; j < gltfMesh.primitives.length; j++) {
+        const gltfPrimitive = gltfMesh.primitives[j];
 
-    for (const attributeSemantic in attributes) {
-      if (attributeSemantic === "POSITION") {
-        continue;
-      }
-      const bufferData = getVertexBufferData(attributeSemantic);
-      switch (attributeSemantic) {
-        case "NORMAL":
-          const normals = GLTFUtil.floatBufferToVector3Array(<Float32Array>bufferData);
-          mesh.setNormals(normals);
-          break;
-        case "TEXCOORD_0":
-          const texturecoords = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
-          mesh.setUVs(texturecoords, 0);
-          break;
-        case "TEXCOORD_1":
-          const texturecoords1 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
-          mesh.setUVs(texturecoords1, 1);
-          break;
-        case "TEXCOORD_2":
-          const texturecoords2 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
-          mesh.setUVs(texturecoords2, 2);
-          break;
-        case "TEXCOORD_3":
-          const texturecoords3 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
-          mesh.setUVs(texturecoords3, 3);
-          break;
-        case "TEXCOORD_4":
-          const texturecoords4 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
-          mesh.setUVs(texturecoords4, 4);
-          break;
-        case "TEXCOORD_5":
-          const texturecoords5 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
-          mesh.setUVs(texturecoords5, 5);
-          break;
-        case "TEXCOORD_6":
-          const texturecoords6 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
-          mesh.setUVs(texturecoords6, 6);
-          break;
-        case "TEXCOORD_7":
-          const texturecoords7 = GLTFUtil.floatBufferToVector2Array(<Float32Array>bufferData);
-          mesh.setUVs(texturecoords7, 7);
-          break;
-        case "COLOR_0":
-          const colors = GLTFUtil.floatBufferToColorArray(
-            <Float32Array>bufferData,
-            accessors[attributes["COLOR_0"]].type === AccessorType.VEC3
+        primitivePromises[j] = new Promise((resolve) => {
+          const mesh: any = GLTFParser.createAndParseFromExtensions(
+            gltfPrimitive.extensions,
+            context,
+            gltfPrimitive,
+            gltfMesh
           );
-          mesh.setColors(colors);
-          break;
-        case "TANGENT":
-          const tangents = GLTFUtil.floatBufferToVector4Array(<Float32Array>bufferData);
-          mesh.setTangents(tangents);
-          break;
 
-        case "JOINTS_0":
-          const joints = GLTFUtil.floatBufferToVector4Array(<Float32Array>bufferData);
-          mesh.setBoneIndices(joints);
-          break;
-        case "WEIGHTS_0":
-          const weights = GLTFUtil.floatBufferToVector4Array(<Float32Array>bufferData);
-          mesh.setBoneWeights(weights);
-          break;
-        default:
-          // console.warn(`Unsupport attribute semantic ${attributeSemantic}.`);
-          break;
+          if (mesh) {
+            AssetPromise.all([mesh]).then((mesh) => {
+              resolve(mesh[0]);
+            });
+          } else {
+            const mesh = new ModelMesh(engine, gltfMesh.name || j + "");
+            GLTFMeshParser._parseMeshFromGLTFPrimitive(
+              context,
+              mesh,
+              gltfMesh,
+              gltfPrimitive,
+              gltf,
+              (attributeSemantic) => {
+                return null;
+              },
+              (attributeName, shapeIndex) => {
+                const shapeAccessorIdx = gltfPrimitive.targets[shapeIndex];
+                const attributeAccessorIdx = shapeAccessorIdx[attributeName];
+                if (attributeAccessorIdx) {
+                  const accessor = gltf.accessors[attributeAccessorIdx];
+                  return GLTFUtil.getAccessorData(gltf, accessor, buffers);
+                } else {
+                  return null;
+                }
+              },
+              () => {
+                const indexAccessor = gltf.accessors[gltfPrimitive.indices];
+                return GLTFUtil.getAccessorData(gltf, indexAccessor, buffers);
+              },
+              context.keepMeshData
+            ).then(resolve);
+          }
+        });
       }
-    }
 
-    // Indices
-    if (indices !== undefined) {
-      const indexAccessor = gltf.accessors[indices];
-      const indexData = getIndexBufferData();
-      mesh.setIndices(<Uint8Array | Uint16Array | Uint32Array>indexData);
-      mesh.addSubMesh(0, indexAccessor.count, mode);
-    } else {
-      mesh.addSubMesh(0, vertexCount, mode);
+      meshPromises[i] = Promise.all(primitivePromises);
     }
 
-    // BlendShapes
-    targets && this._createBlendShape(mesh, gltfMesh, targets, getBlendShapeData);
+    AssetPromise.all(meshPromises)
+      .then((meshes: ModelMesh[][]) => {
+        glTFResource.meshes = meshes;
+        meshesPromiseInfo.resolve(meshes);
+      })
+      .catch(meshesPromiseInfo.reject);
 
-    mesh.uploadData(!keepMeshData);
-    return Promise.resolve(mesh);
+    return meshesPromiseInfo.promise;
   }
 }
diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index f9a9bc81c6..011a6a7184 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -20,12 +20,13 @@ export abstract class GLTFParser {
     extensionName: string,
     context: GLTFParserContext,
     extensionSchema: GLTFExtensionSchema,
-    ownerSchema: GLTFExtensionOwnerSchema
+    ownerSchema: GLTFExtensionOwnerSchema,
+    ...extra
   ): EngineObject | Promise<EngineObject> {
     const parser = GLTFParser.getExtensionParser(extensionName, GLTFExtensionMode.CreateAndParse);
 
     if (parser) {
-      return parser.createAndParse(context, extensionSchema, ownerSchema);
+      return parser.createAndParse(context, extensionSchema, ownerSchema, ...extra);
     }
   }
 
@@ -34,19 +35,21 @@ export abstract class GLTFParser {
     context: GLTFParserContext,
     parseResource: EngineObject,
     extensionSchema: GLTFExtensionSchema,
-    ownerSchema: GLTFExtensionOwnerSchema
+    ownerSchema: GLTFExtensionOwnerSchema,
+    ...extra
   ): void {
     const parser = GLTFParser.getExtensionParser(extensionName, GLTFExtensionMode.AdditiveParse);
 
     if (parser) {
-      parser.additiveParse(context, parseResource, extensionSchema, ownerSchema);
+      parser.additiveParse(context, parseResource, extensionSchema, ownerSchema, ...extra);
     }
   }
 
   static createAndParseFromExtensions(
     extensions: { [key: string]: any } = {},
     context: GLTFParserContext,
-    ownerSchema: GLTFExtensionOwnerSchema
+    ownerSchema: GLTFExtensionOwnerSchema,
+    ...extra
   ): EngineObject | void | Promise<EngineObject | void> {
     let resource: EngineObject | Promise<EngineObject> = null;
 
@@ -56,7 +59,7 @@ export abstract class GLTFParser {
       const extensionSchema = extensions[extensionName];
 
       resource = <EngineObject | Promise<EngineObject>>(
-        GLTFParser.createAndParse(extensionName, context, extensionSchema, ownerSchema)
+        GLTFParser.createAndParse(extensionName, context, extensionSchema, ownerSchema, ...extra)
       );
       if (resource) {
         return resource;
@@ -68,11 +71,12 @@ export abstract class GLTFParser {
     extensions: { [key: string]: any },
     context: GLTFParserContext,
     parseResource: EngineObject,
-    ownerSchema: GLTFExtensionOwnerSchema
+    ownerSchema: GLTFExtensionOwnerSchema,
+    ...extra
   ): void {
     for (let extensionName in extensions) {
       const extensionSchema = extensions[extensionName];
-      GLTFParser.additiveParse(extensionName, context, parseResource, extensionSchema, ownerSchema);
+      GLTFParser.additiveParse(extensionName, context, parseResource, extensionSchema, ownerSchema, ...extra);
     }
   }
 

From 80d30c8614b7ee181fe7d2564924f5681b54c808 Mon Sep 17 00:00:00 2001
From: ChenMo <gl3336563@163.com>
Date: Wed, 1 Mar 2023 14:32:49 +0800
Subject: [PATCH 17/25] refactor: opt code (#7)

---
 .../src/gltf/extensions/KHR_lights_punctual.ts |  9 ++++++---
 .../loader/src/gltf/parser/GLTFSceneParser.ts  | 18 +++---------------
 2 files changed, 9 insertions(+), 18 deletions(-)

diff --git a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
index 9a3efccf21..ad1962a59a 100644
--- a/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
+++ b/packages/loader/src/gltf/extensions/KHR_lights_punctual.ts
@@ -2,15 +2,18 @@ import { DirectLight, Entity, PointLight, SpotLight } from "@oasis-engine/core";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
-import { IKHRLightsPunctual_Light } from "./GLTFExtensionSchema";
+import { IKHRLightsPunctual, IKHRLightsPunctual_LightNode } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_lights_punctual", GLTFExtensionMode.AdditiveParse)
 class KHR_lights_punctual extends GLTFExtensionParser {
   /**
    * @override
    */
-  additiveParse(context: GLTFParserContext, entity: Entity, schema: IKHRLightsPunctual_Light): void {
-    const { color, intensity = 1, type, range, spot } = schema;
+  additiveParse(context: GLTFParserContext, entity: Entity, extensionSchema: IKHRLightsPunctual_LightNode): void {
+    const lightsSchema = (<IKHRLightsPunctual>context.gltf.extensions.KHR_lights_punctual).lights;
+    const lightSchema = lightsSchema[extensionSchema.light];
+
+    const { color, intensity = 1, type, range, spot } = lightSchema;
     const glTFResource = context.glTFResource;
     let light: DirectLight | PointLight | SpotLight;
 
diff --git a/packages/loader/src/gltf/parser/GLTFSceneParser.ts b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
index e6de556298..069e88757c 100644
--- a/packages/loader/src/gltf/parser/GLTFSceneParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
@@ -10,7 +10,6 @@ import {
   MeshRenderer,
   SkinnedMeshRenderer
 } from "@oasis-engine/core";
-import { IKHRLightsPunctual, IKHRLightsPunctual_LightNode } from "../extensions/GLTFExtensionSchema";
 import { GLTFResource } from "../GLTFResource";
 import { CameraType, ICamera, INode } from "../GLTFSchema";
 import { GLTFParser } from "./GLTFParser";
@@ -38,7 +37,7 @@ export class GLTFSceneParser extends GLTFParser {
     for (let i = 0; i < nodes.length; i++) {
       const gltfNode = nodes[i];
       const { camera: cameraID, mesh: meshID, extensions = {} } = gltfNode;
-      const KHR_lights_punctual = <IKHRLightsPunctual_LightNode>extensions.KHR_lights_punctual;
+
       const entity = entities[i];
 
       if (cameraID !== undefined) {
@@ -49,12 +48,7 @@ export class GLTFSceneParser extends GLTFParser {
         this._createRenderer(context, gltfNode, entity);
       }
 
-      if (KHR_lights_punctual) {
-        const lightIndex = KHR_lights_punctual.light;
-        const lights = (gltf.extensions.KHR_lights_punctual as IKHRLightsPunctual).lights;
-
-        GLTFParser.additiveParse("KHR_lights_punctual", context, entity, lights[lightIndex], gltfNode);
-      }
+      GLTFParser.additiveParseFromExtensions(extensions, context, entity, gltfNode);
     }
 
     if (glTFResource.defaultSceneRoot) {
@@ -144,13 +138,7 @@ export class GLTFSceneParser extends GLTFParser {
       const { extensions = {} } = gltfPrimitive;
       const { KHR_materials_variants } = extensions;
       if (KHR_materials_variants) {
-        GLTFParser.additiveParse(
-          "KHR_materials_variants",
-          context,
-          renderer,
-          KHR_materials_variants,
-          gltfPrimitive
-        );
+        GLTFParser.additiveParse("KHR_materials_variants", context, renderer, KHR_materials_variants, gltfPrimitive);
       }
     }
   }

From 55a386556a0d7cfbbf7ca32757e8bb05e99ba5ca Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Wed, 1 Mar 2023 14:42:03 +0800
Subject: [PATCH 18/25] refactor: primitive additive parser

---
 packages/loader/src/gltf/parser/GLTFSceneParser.ts | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/packages/loader/src/gltf/parser/GLTFSceneParser.ts b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
index 069e88757c..1637fc49a6 100644
--- a/packages/loader/src/gltf/parser/GLTFSceneParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
@@ -36,7 +36,7 @@ export class GLTFSceneParser extends GLTFParser {
 
     for (let i = 0; i < nodes.length; i++) {
       const gltfNode = nodes[i];
-      const { camera: cameraID, mesh: meshID, extensions = {} } = gltfNode;
+      const { camera: cameraID, mesh: meshID, extensions } = gltfNode;
 
       const entity = entities[i];
 
@@ -135,11 +135,7 @@ export class GLTFSceneParser extends GLTFParser {
       const material = materials?.[materialIndex] || GLTFSceneParser._getDefaultMaterial(engine);
       renderer.setMaterial(material);
 
-      const { extensions = {} } = gltfPrimitive;
-      const { KHR_materials_variants } = extensions;
-      if (KHR_materials_variants) {
-        GLTFParser.additiveParse("KHR_materials_variants", context, renderer, KHR_materials_variants, gltfPrimitive);
-      }
+      GLTFParser.additiveParseFromExtensions(gltfPrimitive.extensions, context, renderer, gltfPrimitive);
     }
   }
 

From e363823d93aca9ce2b02ea72a2e1323376468437 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Wed, 1 Mar 2023 14:55:48 +0800
Subject: [PATCH 19/25] refactor: add extension data

---
 packages/loader/src/gltf/GLTFResource.ts                   | 6 +++---
 .../loader/src/gltf/extensions/KHR_materials_variants.ts   | 7 ++++---
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/packages/loader/src/gltf/GLTFResource.ts b/packages/loader/src/gltf/GLTFResource.ts
index 682ff9208e..bfa7519d12 100644
--- a/packages/loader/src/gltf/GLTFResource.ts
+++ b/packages/loader/src/gltf/GLTFResource.ts
@@ -38,8 +38,8 @@ export class GLTFResource extends EngineObject {
   sceneRoots: Entity[];
   /** Oasis RootEntity after SceneParser. */
   defaultSceneRoot: Entity;
-  /** Renderer can replace material by `renderer.setMaterial` if gltf use plugin-in KHR_materials_variants. */
-  variants?: { renderer: Renderer; material: Material; variants: string[] }[];
+  /** Extension data. */
+  extensionData: Record<string, any>;
 
   constructor(engine: Engine, url: string) {
     super(engine);
@@ -66,6 +66,6 @@ export class GLTFResource extends EngineObject {
     this.cameras = null;
     this.lights = null;
     this.sceneRoots = null;
-    this.variants = null;
+    this.extensionData = null;
   }
 }
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
index 00a6cfb9b9..fe17278429 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
@@ -6,7 +6,6 @@ import { IKHRMaterialVariants_Mapping } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_variants", GLTFExtensionMode.AdditiveParse)
 class KHR_materials_variants extends GLTFExtensionParser {
-
   /**
    * @override
    */
@@ -21,10 +20,12 @@ class KHR_materials_variants extends GLTFExtensionParser {
     } = context;
     const { mappings } = schema;
 
+    if (!glTFResource.extensionData) glTFResource.extensionData = {};
+    glTFResource.extensionData.variants = [];
+
     for (let i = 0; i < mappings.length; i++) {
       const { material, variants } = mappings[i];
-      if (!glTFResource.variants) glTFResource.variants = [];
-      glTFResource.variants.push({
+      glTFResource.extensionData.variants.push({
         renderer,
         material: glTFResource.materials[material],
         variants: variants.map((index) => variantNames[index].name)

From 43ee74f62e1a0710e2c8ae8ed0fff2a51838ee93 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Wed, 1 Mar 2023 15:06:55 +0800
Subject: [PATCH 20/25] refactor: private

---
 packages/loader/src/gltf/parser/GLTFParser.ts | 62 +++++++++----------
 1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index 011a6a7184..510ae2b313 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -16,35 +16,6 @@ export abstract class GLTFParser {
     }
   }
 
-  static createAndParse(
-    extensionName: string,
-    context: GLTFParserContext,
-    extensionSchema: GLTFExtensionSchema,
-    ownerSchema: GLTFExtensionOwnerSchema,
-    ...extra
-  ): EngineObject | Promise<EngineObject> {
-    const parser = GLTFParser.getExtensionParser(extensionName, GLTFExtensionMode.CreateAndParse);
-
-    if (parser) {
-      return parser.createAndParse(context, extensionSchema, ownerSchema, ...extra);
-    }
-  }
-
-  static additiveParse(
-    extensionName: string,
-    context: GLTFParserContext,
-    parseResource: EngineObject,
-    extensionSchema: GLTFExtensionSchema,
-    ownerSchema: GLTFExtensionOwnerSchema,
-    ...extra
-  ): void {
-    const parser = GLTFParser.getExtensionParser(extensionName, GLTFExtensionMode.AdditiveParse);
-
-    if (parser) {
-      parser.additiveParse(context, parseResource, extensionSchema, ownerSchema, ...extra);
-    }
-  }
-
   static createAndParseFromExtensions(
     extensions: { [key: string]: any } = {},
     context: GLTFParserContext,
@@ -59,7 +30,7 @@ export abstract class GLTFParser {
       const extensionSchema = extensions[extensionName];
 
       resource = <EngineObject | Promise<EngineObject>>(
-        GLTFParser.createAndParse(extensionName, context, extensionSchema, ownerSchema, ...extra)
+        GLTFParser._createAndParse(extensionName, context, extensionSchema, ownerSchema, ...extra)
       );
       if (resource) {
         return resource;
@@ -76,7 +47,7 @@ export abstract class GLTFParser {
   ): void {
     for (let extensionName in extensions) {
       const extensionSchema = extensions[extensionName];
-      GLTFParser.additiveParse(extensionName, context, parseResource, extensionSchema, ownerSchema, ...extra);
+      GLTFParser._additiveParse(extensionName, context, parseResource, extensionSchema, ownerSchema, ...extra);
     }
   }
 
@@ -109,6 +80,35 @@ export abstract class GLTFParser {
     GLTFParser._extensionParsers[extensionName].push(extensionParser);
   }
 
+  private static _createAndParse(
+    extensionName: string,
+    context: GLTFParserContext,
+    extensionSchema: GLTFExtensionSchema,
+    ownerSchema: GLTFExtensionOwnerSchema,
+    ...extra
+  ): EngineObject | Promise<EngineObject> {
+    const parser = GLTFParser.getExtensionParser(extensionName, GLTFExtensionMode.CreateAndParse);
+
+    if (parser) {
+      return parser.createAndParse(context, extensionSchema, ownerSchema, ...extra);
+    }
+  }
+
+  private static _additiveParse(
+    extensionName: string,
+    context: GLTFParserContext,
+    parseResource: EngineObject,
+    extensionSchema: GLTFExtensionSchema,
+    ownerSchema: GLTFExtensionOwnerSchema,
+    ...extra
+  ): void {
+    const parser = GLTFParser.getExtensionParser(extensionName, GLTFExtensionMode.AdditiveParse);
+
+    if (parser) {
+      parser.additiveParse(context, parseResource, extensionSchema, ownerSchema, ...extra);
+    }
+  }
+
   abstract parse(context: GLTFParserContext): AssetPromise<any> | void | Material | AnimationClip | Mesh;
 }
 

From a9d46483d6739ddfe7aba53a3dd9286a7f663f21 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Wed, 1 Mar 2023 16:31:40 +0800
Subject: [PATCH 21/25] refactor: add comments

---
 packages/loader/src/gltf/GLTFResource.ts      |  7 ++--
 packages/loader/src/gltf/GLTFUtil.ts          | 20 ------------
 .../gltf/extensions/GLTFExtensionParser.ts    |  4 +--
 .../gltf/extensions/KHR_materials_variants.ts | 15 ++++++---
 packages/loader/src/gltf/extensions/index.ts  |  2 +-
 .../src/gltf/parser/GLTFMaterialParser.ts     | 15 +++++----
 packages/loader/src/gltf/parser/GLTFParser.ts | 32 +++++++++++++++++++
 7 files changed, 58 insertions(+), 37 deletions(-)

diff --git a/packages/loader/src/gltf/GLTFResource.ts b/packages/loader/src/gltf/GLTFResource.ts
index bfa7519d12..9034a5d710 100644
--- a/packages/loader/src/gltf/GLTFResource.ts
+++ b/packages/loader/src/gltf/GLTFResource.ts
@@ -7,7 +7,6 @@ import {
   Light,
   Material,
   ModelMesh,
-  Renderer,
   Skin,
   Texture2D
 } from "@oasis-engine/core";
@@ -38,8 +37,8 @@ export class GLTFResource extends EngineObject {
   sceneRoots: Entity[];
   /** Oasis RootEntity after SceneParser. */
   defaultSceneRoot: Entity;
-  /** Extension data. */
-  extensionData: Record<string, any>;
+  /** Extensions data. */
+  extensionsData: Record<string, any>;
 
   constructor(engine: Engine, url: string) {
     super(engine);
@@ -66,6 +65,6 @@ export class GLTFResource extends EngineObject {
     this.cameras = null;
     this.lights = null;
     this.sceneRoots = null;
-    this.extensionData = null;
+    this.extensionsData = null;
   }
 }
diff --git a/packages/loader/src/gltf/GLTFUtil.ts b/packages/loader/src/gltf/GLTFUtil.ts
index 9ed0683d66..9b3611e40d 100644
--- a/packages/loader/src/gltf/GLTFUtil.ts
+++ b/packages/loader/src/gltf/GLTFUtil.ts
@@ -3,26 +3,6 @@ import { Color, Vector2, Vector3, Vector4 } from "@oasis-engine/math";
 import { BufferInfo, GLTFParserContext } from "./parser/GLTFParserContext";
 import { AccessorComponentType, AccessorType, IAccessor, IBufferView, IGLTF } from "./GLTFSchema";
 
-const charCodeOfDot = ".".charCodeAt(0);
-const reEscapeChar = /\\(\\)?/g;
-const rePropName = RegExp(
-  // Match anything that isn't a dot or bracket.
-  "[^.[\\]]+" +
-    "|" +
-    // Or match property names within brackets.
-    "\\[(?:" +
-    // Match a non-string expression.
-    "([^\"'][^[]*)" +
-    "|" +
-    // Or match strings (supports escaping characters).
-    "([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2" +
-    ")\\]" +
-    "|" +
-    // Or match "" as the space between consecutive dots or empty brackets.
-    "(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))",
-  "g"
-);
-
 /**
  * @internal
  */
diff --git a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
index 3fb0fad138..63aa3fd1ef 100644
--- a/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
+++ b/packages/loader/src/gltf/extensions/GLTFExtensionParser.ts
@@ -40,14 +40,14 @@ export abstract class GLTFExtensionParser {
   /**
    * Additive parse to the resource.
    * @param context - The parser context
-   * @param resource - The resource
+   * @param parseResource - The parsed resource
    * @param extensionSchema - The extension schema
    * @param extensionOwnerSchema - The extension owner schema
    * @returns The void or promise
    */
   additiveParse(
     context: GLTFParserContext,
-    resource: EngineObject,
+    parseResource: EngineObject,
     extensionSchema: GLTFExtensionSchema,
     extensionOwnerSchema: GLTFExtensionOwnerSchema,
     ...extra
diff --git a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
index fe17278429..234baff165 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_variants.ts
@@ -1,9 +1,15 @@
-import { Renderer } from "@oasis-engine/core";
+import { Material, Renderer } from "@oasis-engine/core";
 import { registerGLTFExtension } from "../parser/GLTFParser";
 import { GLTFParserContext } from "../parser/GLTFParserContext";
 import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
 import { IKHRMaterialVariants_Mapping } from "./GLTFExtensionSchema";
 
+export type IGLTFExtensionVariants = Array<{
+  renderer: Renderer;
+  material: Material;
+  variants: string[];
+}>;
+
 @registerGLTFExtension("KHR_materials_variants", GLTFExtensionMode.AdditiveParse)
 class KHR_materials_variants extends GLTFExtensionParser {
   /**
@@ -20,12 +26,13 @@ class KHR_materials_variants extends GLTFExtensionParser {
     } = context;
     const { mappings } = schema;
 
-    if (!glTFResource.extensionData) glTFResource.extensionData = {};
-    glTFResource.extensionData.variants = [];
+    if (!glTFResource.extensionsData) glTFResource.extensionsData = {};
+    const extensionData: IGLTFExtensionVariants = [];
+    glTFResource.extensionsData.variants = extensionData;
 
     for (let i = 0; i < mappings.length; i++) {
       const { material, variants } = mappings[i];
-      glTFResource.extensionData.variants.push({
+      extensionData.push({
         renderer,
         material: glTFResource.materials[material],
         variants: variants.map((index) => variantNames[index].name)
diff --git a/packages/loader/src/gltf/extensions/index.ts b/packages/loader/src/gltf/extensions/index.ts
index f0ccf5c5eb..e9e71fb5d6 100644
--- a/packages/loader/src/gltf/extensions/index.ts
+++ b/packages/loader/src/gltf/extensions/index.ts
@@ -6,7 +6,7 @@ import "./KHR_materials_pbrSpecularGlossiness";
 import "./KHR_materials_sheen";
 import "./KHR_materials_transmission";
 import "./KHR_materials_unlit";
-import "./KHR_materials_variants";
+export { IGLTFExtensionVariants } from "./KHR_materials_variants";
 import "./KHR_materials_volume";
 import "./KHR_mesh_quantization";
 import "./KHR_texture_basisu";
diff --git a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
index 86e8b5cc73..4acf54a409 100644
--- a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
@@ -1,6 +1,5 @@
 import {
   AssetPromise,
-  BaseMaterial,
   Logger,
   Material,
   PBRMaterial,
@@ -14,8 +13,6 @@ import { IMaterial, ITextureInfo, MaterialAlphaMode } from "../GLTFSchema";
 import { GLTFParser } from "./GLTFParser";
 import { GLTFParserContext } from "./GLTFParserContext";
 
-type StandMaterialType = UnlitMaterial | PBRMaterial | PBRSpecularMaterial;
-
 export class GLTFMaterialParser extends GLTFParser {
   /**
    * @internal
@@ -29,7 +26,11 @@ export class GLTFMaterialParser extends GLTFParser {
   /**
    * @internal
    */
-  static _parseStandardProperty(context: GLTFParserContext, material: StandMaterialType, materialInfo: IMaterial) {
+  static _parseStandardProperty(
+    context: GLTFParserContext,
+    material: UnlitMaterial | PBRMaterial | PBRSpecularMaterial,
+    materialInfo: IMaterial
+  ) {
     const { textures } = context.glTFResource;
     const {
       pbrMetallicRoughness,
@@ -139,12 +140,14 @@ export class GLTFMaterialParser extends GLTFParser {
     for (let i = 0; i < gltf.materials.length; i++) {
       const materialInfo = gltf.materials[i];
 
-      let material: any = GLTFParser.createAndParseFromExtensions(materialInfo.extensions, context, materialInfo);
+      let material = <Material | Promise<Material>>(
+        GLTFParser.createAndParseFromExtensions(materialInfo.extensions, context, materialInfo)
+      );
 
       if (!material) {
         material = new PBRMaterial(engine);
         material.name = materialInfo.name;
-        GLTFMaterialParser._parseStandardProperty(context, material, materialInfo);
+        GLTFMaterialParser._parseStandardProperty(context, material as PBRMaterial, materialInfo);
       }
 
       materialPromises.push(material);
diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index 510ae2b313..80786a2fb9 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -7,6 +7,11 @@ import { GLTFParserContext } from "./GLTFParserContext";
 export abstract class GLTFParser {
   private static readonly _extensionParsers: Record<string, GLTFExtensionParser[]> = {};
 
+  /**
+   * Initialize the parser.
+   * @remarks Some plugins require initialization.
+   * @returns The void or promise
+   */
   static initialize(extensionName: string): void | Promise<void> {
     const parsers = GLTFParser._extensionParsers[extensionName];
     const length = parsers?.length;
@@ -16,6 +21,14 @@ export abstract class GLTFParser {
     }
   }
 
+  /**
+   * Create and parse the resource from extensions.
+   * @param extensions - Related extensions field
+   * @param context - The parser context
+   * @param ownerSchema - The extension owner schema
+   * @param extra - Extra params
+   * @returns
+   */
   static createAndParseFromExtensions(
     extensions: { [key: string]: any } = {},
     context: GLTFParserContext,
@@ -38,6 +51,14 @@ export abstract class GLTFParser {
     }
   }
 
+  /**
+   * Additive parse to the resource from extensions.
+   * @param extensions - Related extensions field
+   * @param context - The parser context
+   * @param parseResource -  The parsed resource
+   * @param ownerSchema - The extension owner schema
+   * @param extra - Extra params
+   */
   static additiveParseFromExtensions(
     extensions: { [key: string]: any },
     context: GLTFParserContext,
@@ -51,10 +72,21 @@ export abstract class GLTFParser {
     }
   }
 
+  /**
+   * Whether the plugin is registered.
+   * @param extensionName - Extension name
+   * @returns Boolean
+   */
   static hasExtensionParser(extensionName: string): boolean {
     return !!GLTFParser._extensionParsers[extensionName]?.length;
   }
 
+  /**
+   * Get the last plugin by glTF extension mode.
+   * @param extensionName - Extension name
+   * @param mode - GLTF extension mode
+   * @returns GLTF extension parser
+   */
   static getExtensionParser(extensionName: string, mode: GLTFExtensionMode): GLTFExtensionParser | void {
     const parsers = GLTFParser._extensionParsers[extensionName];
     const length = parsers?.length;

From 583a4debbfa73ca503f1e5c124276e41809c1034 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Wed, 1 Mar 2023 16:45:15 +0800
Subject: [PATCH 22/25] refactor: perf code

---
 packages/loader/src/gltf/parser/GLTFMeshParser.ts | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/packages/loader/src/gltf/parser/GLTFMeshParser.ts b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
index 7c5729a360..fc3b06e8f7 100644
--- a/packages/loader/src/gltf/parser/GLTFMeshParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
@@ -171,17 +171,16 @@ export class GLTFMeshParser extends GLTFParser {
         const gltfPrimitive = gltfMesh.primitives[j];
 
         primitivePromises[j] = new Promise((resolve) => {
-          const mesh: any = GLTFParser.createAndParseFromExtensions(
-            gltfPrimitive.extensions,
-            context,
-            gltfPrimitive,
-            gltfMesh
+          const mesh = <ModelMesh | Promise<ModelMesh>>(
+            GLTFParser.createAndParseFromExtensions(gltfPrimitive.extensions, context, gltfPrimitive, gltfMesh)
           );
 
           if (mesh) {
-            AssetPromise.all([mesh]).then((mesh) => {
-              resolve(mesh[0]);
-            });
+            if (mesh instanceof ModelMesh) {
+              resolve(mesh);
+            } else {
+              mesh.then((mesh) => resolve(mesh));
+            }
           } else {
             const mesh = new ModelMesh(engine, gltfMesh.name || j + "");
             GLTFMeshParser._parseMeshFromGLTFPrimitive(

From f390b7bdf821d88c450feb96680b5b2c72168b70 Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Wed, 1 Mar 2023 16:46:59 +0800
Subject: [PATCH 23/25] refactor: add comment

---
 packages/loader/src/gltf/parser/GLTFParser.ts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index 80786a2fb9..f029de4364 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -4,6 +4,9 @@ import { GLTFExtensionSchema } from "../extensions/GLTFExtensionSchema";
 import { GLTFExtensionOwnerSchema } from "../GLTFSchema";
 import { GLTFParserContext } from "./GLTFParserContext";
 
+/**
+ * Base class of glTF parser.
+ */
 export abstract class GLTFParser {
   private static readonly _extensionParsers: Record<string, GLTFExtensionParser[]> = {};
 

From 46b6b41a6a7ccb78fb5825d9e6c29b041a55b21c Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Wed, 1 Mar 2023 17:48:12 +0800
Subject: [PATCH 24/25] refactor: rename

---
 .../KHR_materials_pbrSpecularGlossiness.ts         |  3 +--
 .../loader/src/gltf/parser/GLTFMaterialParser.ts   |  6 +++---
 packages/loader/src/gltf/parser/GLTFMeshParser.ts  |  2 +-
 packages/loader/src/gltf/parser/GLTFParser.ts      | 14 +++++++-------
 packages/loader/src/gltf/parser/GLTFSceneParser.ts |  4 ++--
 packages/loader/src/gltf/parser/GLTFValidator.ts   |  2 +-
 6 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
index 43351a8420..6ee4a3588c 100644
--- a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
+++ b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts
@@ -9,7 +9,6 @@ import { IKHRMaterialsPbrSpecularGlossiness } from "./GLTFExtensionSchema";
 
 @registerGLTFExtension("KHR_materials_pbrSpecularGlossiness", GLTFExtensionMode.CreateAndParse)
 class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser {
-  
   /**
    * @override
    */
@@ -33,7 +32,7 @@ class KHR_materials_pbrSpecularGlossiness extends GLTFExtensionParser {
 
     if (diffuseTexture) {
       material.baseTexture = textures[diffuseTexture.index];
-      GLTFParser.additiveParseFromExtensions(diffuseTexture.extensions, context, material, diffuseTexture);
+      GLTFParser.executeExtensionsAdditiveAndParse(diffuseTexture.extensions, context, material, diffuseTexture);
     }
 
     if (specularFactor) {
diff --git a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
index 4acf54a409..991ff3799b 100644
--- a/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMaterialParser.ts
@@ -57,7 +57,7 @@ export class GLTFMaterialParser extends GLTFParser {
       }
       if (baseColorTexture) {
         material.baseTexture = textures[baseColorTexture.index];
-        GLTFParser.additiveParseFromExtensions(baseColorTexture.extensions, context, material, baseColorTexture);
+        GLTFParser.executeExtensionsAdditiveAndParse(baseColorTexture.extensions, context, material, baseColorTexture);
       }
 
       if (material.constructor === PBRMaterial) {
@@ -141,7 +141,7 @@ export class GLTFMaterialParser extends GLTFParser {
       const materialInfo = gltf.materials[i];
 
       let material = <Material | Promise<Material>>(
-        GLTFParser.createAndParseFromExtensions(materialInfo.extensions, context, materialInfo)
+        GLTFParser.executeExtensionsCreateAndParse(materialInfo.extensions, context, materialInfo)
       );
 
       if (!material) {
@@ -157,7 +157,7 @@ export class GLTFMaterialParser extends GLTFParser {
       glTFResource.materials = materials;
       for (let i = 0; i < gltf.materials.length; i++) {
         const materialInfo = gltf.materials[i];
-        GLTFParser.additiveParseFromExtensions(materialInfo.extensions, context, materials[i], materialInfo);
+        GLTFParser.executeExtensionsAdditiveAndParse(materialInfo.extensions, context, materials[i], materialInfo);
       }
       materialsPromiseInfo.resolve(materials);
       return materialsPromiseInfo.promise;
diff --git a/packages/loader/src/gltf/parser/GLTFMeshParser.ts b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
index fc3b06e8f7..ff54988955 100644
--- a/packages/loader/src/gltf/parser/GLTFMeshParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFMeshParser.ts
@@ -172,7 +172,7 @@ export class GLTFMeshParser extends GLTFParser {
 
         primitivePromises[j] = new Promise((resolve) => {
           const mesh = <ModelMesh | Promise<ModelMesh>>(
-            GLTFParser.createAndParseFromExtensions(gltfPrimitive.extensions, context, gltfPrimitive, gltfMesh)
+            GLTFParser.executeExtensionsCreateAndParse(gltfPrimitive.extensions, context, gltfPrimitive, gltfMesh)
           );
 
           if (mesh) {
diff --git a/packages/loader/src/gltf/parser/GLTFParser.ts b/packages/loader/src/gltf/parser/GLTFParser.ts
index f029de4364..f9704785e8 100644
--- a/packages/loader/src/gltf/parser/GLTFParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFParser.ts
@@ -11,11 +11,11 @@ export abstract class GLTFParser {
   private static readonly _extensionParsers: Record<string, GLTFExtensionParser[]> = {};
 
   /**
-   * Initialize the parser.
+   * Execute all parses of extension to initialize plugin.
    * @remarks Some plugins require initialization.
    * @returns The void or promise
    */
-  static initialize(extensionName: string): void | Promise<void> {
+  static executeExtensionsInitialize(extensionName: string): void | Promise<void> {
     const parsers = GLTFParser._extensionParsers[extensionName];
     const length = parsers?.length;
 
@@ -25,14 +25,14 @@ export abstract class GLTFParser {
   }
 
   /**
-   * Create and parse the resource from extensions.
+   * Execute all parses of extension to create resource.
    * @param extensions - Related extensions field
    * @param context - The parser context
    * @param ownerSchema - The extension owner schema
    * @param extra - Extra params
    * @returns
    */
-  static createAndParseFromExtensions(
+  static executeExtensionsCreateAndParse(
     extensions: { [key: string]: any } = {},
     context: GLTFParserContext,
     ownerSchema: GLTFExtensionOwnerSchema,
@@ -55,14 +55,14 @@ export abstract class GLTFParser {
   }
 
   /**
-   * Additive parse to the resource from extensions.
+   * Execute all parses of extension to parse resource.
    * @param extensions - Related extensions field
    * @param context - The parser context
    * @param parseResource -  The parsed resource
    * @param ownerSchema - The extension owner schema
    * @param extra - Extra params
    */
-  static additiveParseFromExtensions(
+  static executeExtensionsAdditiveAndParse(
     extensions: { [key: string]: any },
     context: GLTFParserContext,
     parseResource: EngineObject,
@@ -90,7 +90,7 @@ export abstract class GLTFParser {
    * @param mode - GLTF extension mode
    * @returns GLTF extension parser
    */
-  static getExtensionParser(extensionName: string, mode: GLTFExtensionMode): GLTFExtensionParser | void {
+  static getExtensionParser(extensionName: string, mode: GLTFExtensionMode): GLTFExtensionParser | undefined {
     const parsers = GLTFParser._extensionParsers[extensionName];
     const length = parsers?.length;
 
diff --git a/packages/loader/src/gltf/parser/GLTFSceneParser.ts b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
index 1637fc49a6..c3ea3c9071 100644
--- a/packages/loader/src/gltf/parser/GLTFSceneParser.ts
+++ b/packages/loader/src/gltf/parser/GLTFSceneParser.ts
@@ -48,7 +48,7 @@ export class GLTFSceneParser extends GLTFParser {
         this._createRenderer(context, gltfNode, entity);
       }
 
-      GLTFParser.additiveParseFromExtensions(extensions, context, entity, gltfNode);
+      GLTFParser.executeExtensionsAdditiveAndParse(extensions, context, entity, gltfNode);
     }
 
     if (glTFResource.defaultSceneRoot) {
@@ -135,7 +135,7 @@ export class GLTFSceneParser extends GLTFParser {
       const material = materials?.[materialIndex] || GLTFSceneParser._getDefaultMaterial(engine);
       renderer.setMaterial(material);
 
-      GLTFParser.additiveParseFromExtensions(gltfPrimitive.extensions, context, renderer, gltfPrimitive);
+      GLTFParser.executeExtensionsAdditiveAndParse(gltfPrimitive.extensions, context, renderer, gltfPrimitive);
     }
   }
 
diff --git a/packages/loader/src/gltf/parser/GLTFValidator.ts b/packages/loader/src/gltf/parser/GLTFValidator.ts
index 560ea773f0..d7ec5520d5 100644
--- a/packages/loader/src/gltf/parser/GLTFValidator.ts
+++ b/packages/loader/src/gltf/parser/GLTFValidator.ts
@@ -33,7 +33,7 @@ export class GLTFValidator extends GLTFParser {
         if (!GLTFParser.hasExtensionParser(extensionRequired)) {
           Logger.error(`GLTF parser has not supported required extension ${extensionRequired}.`);
         } else {
-          promises.push(GLTFParser.initialize(extensionRequired));
+          promises.push(GLTFParser.executeExtensionsInitialize(extensionRequired));
         }
       }
     }

From ecab3fe7c4ac9c69f57eded66477effee243e11c Mon Sep 17 00:00:00 2001
From: zhuxudong <callzhuxudong@163.com>
Date: Wed, 1 Mar 2023 18:27:19 +0800
Subject: [PATCH 25/25] refactor: export type

---
 packages/loader/src/gltf/extensions/index.ts | 2 +-
 packages/loader/src/gltf/index.ts            | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/packages/loader/src/gltf/extensions/index.ts b/packages/loader/src/gltf/extensions/index.ts
index e9e71fb5d6..d5791a43f2 100644
--- a/packages/loader/src/gltf/extensions/index.ts
+++ b/packages/loader/src/gltf/extensions/index.ts
@@ -6,7 +6,7 @@ import "./KHR_materials_pbrSpecularGlossiness";
 import "./KHR_materials_sheen";
 import "./KHR_materials_transmission";
 import "./KHR_materials_unlit";
-export { IGLTFExtensionVariants } from "./KHR_materials_variants";
+export type { IGLTFExtensionVariants } from "./KHR_materials_variants";
 import "./KHR_materials_volume";
 import "./KHR_mesh_quantization";
 import "./KHR_texture_basisu";
diff --git a/packages/loader/src/gltf/index.ts b/packages/loader/src/gltf/index.ts
index b6e80c4e0c..e42469dcbf 100644
--- a/packages/loader/src/gltf/index.ts
+++ b/packages/loader/src/gltf/index.ts
@@ -3,4 +3,4 @@ export { GLTFResource } from "./GLTFResource";
 export { GLTFUtil } from "./GLTFUtil";
 export * from "./parser";
 export * from "./extensions/index";
-export { IMaterial, IMeshPrimitive, ITextureInfo, INode, GLTFExtensionOwnerSchema } from "./GLTFSchema";
+export type { IMaterial, IMeshPrimitive, ITextureInfo, INode, GLTFExtensionOwnerSchema } from "./GLTFSchema";