@lingbi/studio 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Application.d.ts CHANGED
@@ -1,11 +1,15 @@
1
1
  import type { ObjImportResult } from './ObjImportResult';
2
2
  import type { ObjImportSource } from './ObjImportSource';
3
+ import type { ObjResourceListSource } from './ObjResourceListSource';
4
+ import type { ObjResourceSceneSource } from './ObjResourceSceneSource';
3
5
  import type { ObjSceneSource } from './ObjSceneSource';
4
6
  export declare class Application {
5
7
  private disposed;
6
8
  private renderer;
7
9
  attach(canvas: HTMLCanvasElement): void;
8
10
  importObj(source: ObjImportSource): Promise<ObjImportResult>;
11
+ importObjResources(source: ObjResourceListSource): Promise<ObjImportResult>;
12
+ importObjResourceScene(source: ObjResourceSceneSource): Promise<ObjImportResult>;
9
13
  importObjScene(source: ObjSceneSource): Promise<ObjImportResult>;
10
14
  resetView(): void;
11
15
  dispose(): void;
@@ -0,0 +1,3 @@
1
+ export interface ObjResourceListSource {
2
+ readonly fileUrls: readonly string[];
3
+ }
@@ -0,0 +1,5 @@
1
+ import type { ObjResourceListSource } from './ObjResourceListSource';
2
+ export interface ObjResourceSceneSource {
3
+ readonly stone?: ObjResourceListSource;
4
+ readonly base?: ObjResourceListSource;
5
+ }
package/index.d.ts CHANGED
@@ -2,4 +2,6 @@ export { Application } from './Application';
2
2
  export type { ObjImportResult } from './ObjImportResult';
3
3
  export { ObjImportFailureCode } from './ObjImportResult';
4
4
  export type { ObjImportSource } from './ObjImportSource';
5
+ export type { ObjResourceListSource } from './ObjResourceListSource';
6
+ export type { ObjResourceSceneSource } from './ObjResourceSceneSource';
5
7
  export type { ObjSceneSource } from './ObjSceneSource';
package/index.js CHANGED
@@ -13983,6 +13983,91 @@ class RawShaderMaterial extends ShaderMaterial {
13983
13983
  this.type = "RawShaderMaterial";
13984
13984
  }
13985
13985
  }
13986
+ class MeshStandardMaterial extends Material {
13987
+ /**
13988
+ * Constructs a new mesh standard material.
13989
+ *
13990
+ * @param {Object} [parameters] - An object with one or more properties
13991
+ * defining the material's appearance. Any property of the material
13992
+ * (including any property from inherited materials) can be passed
13993
+ * in here. Color values can be passed any type of value accepted
13994
+ * by {@link Color#set}.
13995
+ */
13996
+ constructor(parameters) {
13997
+ super();
13998
+ this.isMeshStandardMaterial = true;
13999
+ this.type = "MeshStandardMaterial";
14000
+ this.defines = { "STANDARD": "" };
14001
+ this.color = new Color(16777215);
14002
+ this.roughness = 1;
14003
+ this.metalness = 0;
14004
+ this.map = null;
14005
+ this.lightMap = null;
14006
+ this.lightMapIntensity = 1;
14007
+ this.aoMap = null;
14008
+ this.aoMapIntensity = 1;
14009
+ this.emissive = new Color(0);
14010
+ this.emissiveIntensity = 1;
14011
+ this.emissiveMap = null;
14012
+ this.bumpMap = null;
14013
+ this.bumpScale = 1;
14014
+ this.normalMap = null;
14015
+ this.normalMapType = TangentSpaceNormalMap;
14016
+ this.normalScale = new Vector2(1, 1);
14017
+ this.displacementMap = null;
14018
+ this.displacementScale = 1;
14019
+ this.displacementBias = 0;
14020
+ this.roughnessMap = null;
14021
+ this.metalnessMap = null;
14022
+ this.alphaMap = null;
14023
+ this.envMap = null;
14024
+ this.envMapRotation = new Euler();
14025
+ this.envMapIntensity = 1;
14026
+ this.wireframe = false;
14027
+ this.wireframeLinewidth = 1;
14028
+ this.wireframeLinecap = "round";
14029
+ this.wireframeLinejoin = "round";
14030
+ this.flatShading = false;
14031
+ this.fog = true;
14032
+ this.setValues(parameters);
14033
+ }
14034
+ copy(source) {
14035
+ super.copy(source);
14036
+ this.defines = { "STANDARD": "" };
14037
+ this.color.copy(source.color);
14038
+ this.roughness = source.roughness;
14039
+ this.metalness = source.metalness;
14040
+ this.map = source.map;
14041
+ this.lightMap = source.lightMap;
14042
+ this.lightMapIntensity = source.lightMapIntensity;
14043
+ this.aoMap = source.aoMap;
14044
+ this.aoMapIntensity = source.aoMapIntensity;
14045
+ this.emissive.copy(source.emissive);
14046
+ this.emissiveMap = source.emissiveMap;
14047
+ this.emissiveIntensity = source.emissiveIntensity;
14048
+ this.bumpMap = source.bumpMap;
14049
+ this.bumpScale = source.bumpScale;
14050
+ this.normalMap = source.normalMap;
14051
+ this.normalMapType = source.normalMapType;
14052
+ this.normalScale.copy(source.normalScale);
14053
+ this.displacementMap = source.displacementMap;
14054
+ this.displacementScale = source.displacementScale;
14055
+ this.displacementBias = source.displacementBias;
14056
+ this.roughnessMap = source.roughnessMap;
14057
+ this.metalnessMap = source.metalnessMap;
14058
+ this.alphaMap = source.alphaMap;
14059
+ this.envMap = source.envMap;
14060
+ this.envMapRotation.copy(source.envMapRotation);
14061
+ this.envMapIntensity = source.envMapIntensity;
14062
+ this.wireframe = source.wireframe;
14063
+ this.wireframeLinewidth = source.wireframeLinewidth;
14064
+ this.wireframeLinecap = source.wireframeLinecap;
14065
+ this.wireframeLinejoin = source.wireframeLinejoin;
14066
+ this.flatShading = source.flatShading;
14067
+ this.fog = source.fog;
14068
+ return this;
14069
+ }
14070
+ }
13986
14071
  class MeshPhongMaterial extends Material {
13987
14072
  /**
13988
14073
  * Constructs a new mesh phong material.
@@ -30474,6 +30559,12 @@ class ObjLoader {
30474
30559
  this.parser = parser;
30475
30560
  }
30476
30561
  async load(source, signal) {
30562
+ return this.loadInternal(source, signal);
30563
+ }
30564
+ async loadResources(resources, signal) {
30565
+ return this.loadInternal(this.createResourceSource(resources), signal, resources);
30566
+ }
30567
+ async loadInternal(source, signal, resources) {
30477
30568
  if (this.hasEmptyRequiredUrl(source)) {
30478
30569
  return {
30479
30570
  code: ObjImportFailureCode$1.EmptySource,
@@ -30485,12 +30576,15 @@ class ObjLoader {
30485
30576
  try {
30486
30577
  const objSource = await this.loadText(source.objUrl, signal);
30487
30578
  this.assertNotCancelled(signal);
30488
- const materialUrl = this.getMaterialUrl(source, objSource);
30579
+ const materialReferences = this.getMaterialLibraryReferences(objSource);
30580
+ resources?.assertMaterialLibraries(materialReferences);
30581
+ const materialUrl = resources === void 0 ? this.getMaterialUrl(source, materialReferences) : resources.mtlUrl;
30489
30582
  if (materialUrl !== void 0) {
30490
30583
  materialContext = await this.loadMaterialContext(
30491
30584
  materialUrl,
30492
30585
  source.textureUrls,
30493
- signal
30586
+ signal,
30587
+ resources
30494
30588
  );
30495
30589
  }
30496
30590
  this.assertNotCancelled(signal);
@@ -30538,6 +30632,11 @@ class ObjLoader {
30538
30632
  throw new Error("The OBJ import was cancelled.");
30539
30633
  }
30540
30634
  }
30635
+ assertMaterialTextures(resources, materialSource, materialBaseUrl, creator) {
30636
+ for (const textureReference of this.getMaterialTextureReferences(materialSource, creator)) {
30637
+ resources.resolveTextureUrl(materialBaseUrl, textureReference);
30638
+ }
30639
+ }
30541
30640
  collectMaterials(material, materials) {
30542
30641
  if (Array.isArray(material)) {
30543
30642
  for (const item of material) {
@@ -30547,6 +30646,17 @@ class ObjLoader {
30547
30646
  }
30548
30647
  materials.add(material);
30549
30648
  }
30649
+ createResourceSource(resources) {
30650
+ if (resources.mtlUrl === void 0) {
30651
+ return {
30652
+ objUrl: resources.objUrl
30653
+ };
30654
+ }
30655
+ return {
30656
+ mtlUrl: resources.mtlUrl,
30657
+ objUrl: resources.objUrl
30658
+ };
30659
+ }
30550
30660
  disposeFailedModel(model) {
30551
30661
  if (model === void 0) {
30552
30662
  return;
@@ -30570,6 +30680,11 @@ class ObjLoader {
30570
30680
  const resourceOwner = new Model(new Group(), [...materials]);
30571
30681
  resourceOwner.dispose();
30572
30682
  }
30683
+ disposeMaterialsWithoutTextures(materials) {
30684
+ for (const material of materials) {
30685
+ material.dispose();
30686
+ }
30687
+ }
30573
30688
  getMaterialArray(context) {
30574
30689
  if (context === void 0) {
30575
30690
  return [];
@@ -30592,20 +30707,33 @@ class ObjLoader {
30592
30707
  getTextureFailureCode(outcome) {
30593
30708
  return outcome === "cancelled" ? ObjImportFailureCode$1.Cancelled : ObjImportFailureCode$1.InvalidSource;
30594
30709
  }
30595
- getMaterialLibraryReference(objSource) {
30710
+ getMaterialLibraryReferences(objSource) {
30711
+ const materialReferences = [];
30596
30712
  for (const line of objSource.split(/\r?\n/u)) {
30597
30713
  const materialReference = /^\s*mtllib\s+(.+?)\s*$/u.exec(line)?.[1];
30598
30714
  if (materialReference !== void 0) {
30599
- return materialReference;
30715
+ materialReferences.push(materialReference);
30600
30716
  }
30601
30717
  }
30602
- return void 0;
30718
+ return materialReferences;
30719
+ }
30720
+ getMaterialTextureReferences(materialSource, creator) {
30721
+ const textureReferences = [];
30722
+ for (const line of materialSource.split(/\r?\n/u)) {
30723
+ const textureValue = /^\s*(?:map_\S+|bump|decal|disp|norm|refl)\s+(.+?)\s*$/iu.exec(
30724
+ line
30725
+ )?.[1];
30726
+ if (textureValue !== void 0) {
30727
+ textureReferences.push(creator.getTextureParams(textureValue, {}).url);
30728
+ }
30729
+ }
30730
+ return textureReferences;
30603
30731
  }
30604
- getMaterialUrl(source, objSource) {
30732
+ getMaterialUrl(source, materialReferences) {
30605
30733
  if (source.mtlUrl !== void 0) {
30606
30734
  return source.mtlUrl;
30607
30735
  }
30608
- const materialReference = this.getMaterialLibraryReference(objSource);
30736
+ const materialReference = materialReferences[0];
30609
30737
  if (materialReference === void 0) {
30610
30738
  return void 0;
30611
30739
  }
@@ -30635,21 +30763,29 @@ class ObjLoader {
30635
30763
  isPoints(object) {
30636
30764
  return object instanceof Points;
30637
30765
  }
30638
- async loadMaterialContext(mtlUrl, textureUrls, signal) {
30766
+ async loadMaterialContext(mtlUrl, textureUrls, signal, resources) {
30639
30767
  const materialSource = await this.loadText(mtlUrl, signal);
30640
30768
  this.assertNotCancelled(signal);
30641
30769
  const materialBaseUrl = this.getResourceDirectoryUrl(mtlUrl);
30642
30770
  const manager = new LoadingManager();
30643
- manager.setURLModifier(this.resolveTextureUrl.bind(this, textureUrls, materialBaseUrl));
30771
+ manager.setURLModifier(
30772
+ resources === void 0 ? this.resolveTextureUrl.bind(this, textureUrls, materialBaseUrl) : resources.resolveTextureUrl.bind(resources, materialBaseUrl)
30773
+ );
30644
30774
  const materialLoader = new MTLLoader(manager);
30645
30775
  materialLoader.setMaterialOptions({
30646
30776
  side: DoubleSide
30647
30777
  });
30648
30778
  const creator = materialLoader.parse(materialSource, materialBaseUrl);
30779
+ const pbrMaterialReferences = this.parsePbrMaterialReferences(materialSource);
30780
+ if (resources !== void 0) {
30781
+ this.assertMaterialTextures(resources, materialSource, materialBaseUrl, creator);
30782
+ }
30649
30783
  this.validateTextureOverrides(textureUrls);
30784
+ this.removeLegacyPbrTextureMappings(creator);
30650
30785
  const monitor = new TextureLoadMonitor(manager, creator);
30651
30786
  try {
30652
30787
  creator.preload();
30788
+ this.replaceMaterialsWithPbr(creator, pbrMaterialReferences, materialBaseUrl);
30653
30789
  monitor.finishScheduling();
30654
30790
  } catch (error2) {
30655
30791
  monitor.finishScheduling();
@@ -30704,6 +30840,77 @@ class ObjLoader {
30704
30840
  }
30705
30841
  this.disposeMaterials(materialsToDispose);
30706
30842
  }
30843
+ createPbrMaterial(source, references, creator, materialBaseUrl) {
30844
+ const material = new MeshStandardMaterial();
30845
+ material.alphaMap = source.alphaMap;
30846
+ material.alphaTest = source.alphaTest;
30847
+ material.color.copy(source.color);
30848
+ material.displacementBias = source.displacementBias;
30849
+ material.displacementMap = source.displacementMap;
30850
+ material.displacementScale = source.displacementScale;
30851
+ material.emissive.copy(source.emissive);
30852
+ material.emissiveIntensity = source.emissiveIntensity;
30853
+ material.emissiveMap = source.emissiveMap;
30854
+ material.map = source.map;
30855
+ material.name = source.name;
30856
+ material.opacity = source.opacity;
30857
+ material.side = source.side;
30858
+ material.transparent = source.transparent;
30859
+ material.vertexColors = source.vertexColors;
30860
+ if (material.map !== null) {
30861
+ material.map.colorSpace = SRGBColorSpace;
30862
+ }
30863
+ if (material.emissiveMap !== null) {
30864
+ material.emissiveMap.colorSpace = SRGBColorSpace;
30865
+ }
30866
+ const roughnessReference = references.roughness ?? references.roughnessFallback;
30867
+ if (roughnessReference !== void 0) {
30868
+ material.roughnessMap = this.loadPbrTexture(
30869
+ creator,
30870
+ materialBaseUrl,
30871
+ roughnessReference
30872
+ ).texture;
30873
+ }
30874
+ if (references.metalness !== void 0) {
30875
+ material.metalnessMap = this.loadPbrTexture(
30876
+ creator,
30877
+ materialBaseUrl,
30878
+ references.metalness
30879
+ ).texture;
30880
+ }
30881
+ const normalReference = references.normal ?? references.legacyNormal;
30882
+ if (normalReference !== void 0) {
30883
+ const normalTexture = this.loadPbrTexture(creator, materialBaseUrl, normalReference);
30884
+ material.normalMap = normalTexture.texture;
30885
+ if (normalTexture.bumpScale !== void 0) {
30886
+ material.normalScale.set(normalTexture.bumpScale, normalTexture.bumpScale);
30887
+ }
30888
+ }
30889
+ if (references.bump !== void 0) {
30890
+ const bumpTexture = this.loadPbrTexture(creator, materialBaseUrl, references.bump);
30891
+ material.bumpMap = bumpTexture.texture;
30892
+ if (bumpTexture.bumpScale !== void 0) {
30893
+ material.bumpScale = bumpTexture.bumpScale;
30894
+ }
30895
+ }
30896
+ return material;
30897
+ }
30898
+ loadPbrTexture(creator, materialBaseUrl, reference) {
30899
+ const materialParameters = {};
30900
+ const textureParameters = creator.getTextureParams(reference, materialParameters);
30901
+ const texture = creator.loadTexture(
30902
+ this.resolveResourceUrl(textureParameters.url, materialBaseUrl)
30903
+ );
30904
+ texture.colorSpace = NoColorSpace;
30905
+ texture.offset.copy(textureParameters.offset);
30906
+ texture.repeat.copy(textureParameters.scale);
30907
+ texture.wrapS = creator.wrap;
30908
+ texture.wrapT = creator.wrap;
30909
+ return {
30910
+ bumpScale: materialParameters.bumpScale,
30911
+ texture
30912
+ };
30913
+ }
30707
30914
  parseObj(source, materials) {
30708
30915
  if (materials === void 0) {
30709
30916
  return this.parser.parse(source);
@@ -30712,6 +30919,78 @@ class ObjLoader {
30712
30919
  parser.setMaterials(materials);
30713
30920
  return parser.parse(source);
30714
30921
  }
30922
+ parsePbrMaterialReferences(materialSource) {
30923
+ const referencesByMaterial = {};
30924
+ let currentReferences;
30925
+ for (const line of materialSource.split(/\r?\n/u)) {
30926
+ const materialName = /^\s*newmtl\s+(.+?)\s*$/iu.exec(line)?.[1];
30927
+ if (materialName !== void 0) {
30928
+ currentReferences = {
30929
+ bump: void 0,
30930
+ legacyNormal: void 0,
30931
+ metalness: void 0,
30932
+ normal: void 0,
30933
+ roughness: void 0,
30934
+ roughnessFallback: void 0
30935
+ };
30936
+ referencesByMaterial[materialName] = currentReferences;
30937
+ continue;
30938
+ }
30939
+ if (currentReferences === void 0) {
30940
+ continue;
30941
+ }
30942
+ const textureReference = /^\s*(map_pr|map_ns|map_pm|map_bump|bump|norm)\s+(.+?)\s*$/iu.exec(line);
30943
+ if (textureReference === null) {
30944
+ continue;
30945
+ }
30946
+ const [, directive = "", value = ""] = textureReference;
30947
+ switch (directive.toLowerCase()) {
30948
+ case "bump":
30949
+ currentReferences.bump = value;
30950
+ break;
30951
+ case "map_bump":
30952
+ currentReferences.legacyNormal = value;
30953
+ break;
30954
+ case "map_pm":
30955
+ currentReferences.metalness = value;
30956
+ break;
30957
+ case "map_ns":
30958
+ currentReferences.roughnessFallback = value;
30959
+ break;
30960
+ case "map_pr":
30961
+ currentReferences.roughness = value;
30962
+ break;
30963
+ case "norm":
30964
+ currentReferences.normal = value;
30965
+ break;
30966
+ }
30967
+ }
30968
+ return referencesByMaterial;
30969
+ }
30970
+ removeLegacyPbrTextureMappings(creator) {
30971
+ for (const materialInfo of Object.values(creator.materialsInfo)) {
30972
+ delete materialInfo.bump;
30973
+ delete materialInfo.map_bump;
30974
+ delete materialInfo.norm;
30975
+ }
30976
+ }
30977
+ replaceMaterialsWithPbr(creator, referencesByMaterial, materialBaseUrl) {
30978
+ const replacedMaterials = /* @__PURE__ */ new Set();
30979
+ for (const [materialName, references] of Object.entries(referencesByMaterial)) {
30980
+ const sourceMaterial = creator.materials[materialName];
30981
+ if (!(sourceMaterial instanceof MeshPhongMaterial)) {
30982
+ throw new Error("The MTL loader did not create a phong material.");
30983
+ }
30984
+ creator.materials[materialName] = this.createPbrMaterial(
30985
+ sourceMaterial,
30986
+ references,
30987
+ creator,
30988
+ materialBaseUrl
30989
+ );
30990
+ replacedMaterials.add(sourceMaterial);
30991
+ }
30992
+ this.disposeMaterialsWithoutTextures(replacedMaterials);
30993
+ }
30715
30994
  resolveResourceUrl(reference, baseUrl) {
30716
30995
  return new URL(reference, this.toAbsoluteUrl(baseUrl)).href;
30717
30996
  }
@@ -30740,6 +31019,101 @@ class ObjLoader {
30740
31019
  }
30741
31020
  }
30742
31021
  }
31022
+ class ObjResourceList {
31023
+ mtlUrl;
31024
+ objUrl;
31025
+ mtlFileName;
31026
+ textureUrls = /* @__PURE__ */ new Set();
31027
+ textureUrlsByFileName = /* @__PURE__ */ new Map();
31028
+ constructor(fileUrls) {
31029
+ let mtlFileName;
31030
+ let mtlUrl;
31031
+ let objUrl;
31032
+ const seenFileNames = /* @__PURE__ */ new Set();
31033
+ const seenUrls = /* @__PURE__ */ new Set();
31034
+ for (const fileUrl of fileUrls) {
31035
+ const resource = this.createResourceEntry(fileUrl);
31036
+ if (seenUrls.has(resource.url) || seenFileNames.has(resource.fileName)) {
31037
+ throw new Error("The OBJ resource list contains a duplicate resource.");
31038
+ }
31039
+ seenUrls.add(resource.url);
31040
+ seenFileNames.add(resource.fileName);
31041
+ if (this.isObjUrl(resource.url)) {
31042
+ if (objUrl !== void 0) {
31043
+ throw new Error("The OBJ resource list must contain exactly one OBJ file.");
31044
+ }
31045
+ objUrl = resource.url;
31046
+ continue;
31047
+ }
31048
+ if (this.isMtlUrl(resource.url)) {
31049
+ if (mtlUrl !== void 0) {
31050
+ throw new Error("The OBJ resource list cannot contain multiple MTL files.");
31051
+ }
31052
+ mtlFileName = resource.fileName;
31053
+ mtlUrl = resource.url;
31054
+ continue;
31055
+ }
31056
+ this.textureUrls.add(resource.url);
31057
+ this.textureUrlsByFileName.set(resource.fileName, resource.url);
31058
+ }
31059
+ if (objUrl === void 0) {
31060
+ throw new Error("The OBJ resource list must contain an OBJ file.");
31061
+ }
31062
+ this.mtlFileName = mtlFileName;
31063
+ this.mtlUrl = mtlUrl;
31064
+ this.objUrl = objUrl;
31065
+ }
31066
+ assertMaterialLibraries(materialReferences) {
31067
+ if (materialReferences.length === 0) {
31068
+ return;
31069
+ }
31070
+ const mtlUrl = this.mtlUrl;
31071
+ const mtlFileName = this.mtlFileName;
31072
+ const [materialReference, ...remainingReferences] = materialReferences;
31073
+ if (materialReference === void 0 || remainingReferences.length > 0 || mtlUrl === void 0 || mtlFileName === void 0) {
31074
+ throw new Error("The OBJ material library is not present in the resource list.");
31075
+ }
31076
+ const referenceUrl = new URL(materialReference, this.objUrl).href;
31077
+ if (referenceUrl === mtlUrl || this.getFileName(new URL(referenceUrl)) === mtlFileName) {
31078
+ return;
31079
+ }
31080
+ throw new Error("The OBJ material library does not match the resource list.");
31081
+ }
31082
+ resolveTextureUrl(materialBaseUrl, textureUrl) {
31083
+ const resolvedUrl = new URL(textureUrl, materialBaseUrl).href;
31084
+ if (this.textureUrls.has(resolvedUrl)) {
31085
+ return resolvedUrl;
31086
+ }
31087
+ const mappedUrl = this.textureUrlsByFileName.get(this.getFileName(new URL(resolvedUrl)));
31088
+ if (mappedUrl === void 0) {
31089
+ throw new Error("The MTL texture is not present in the resource list.");
31090
+ }
31091
+ return mappedUrl;
31092
+ }
31093
+ createResourceEntry(fileUrl) {
31094
+ const url = new URL(fileUrl);
31095
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
31096
+ throw new Error("The OBJ resource list only accepts HTTP URLs.");
31097
+ }
31098
+ return {
31099
+ fileName: this.getFileName(url),
31100
+ url: url.href
31101
+ };
31102
+ }
31103
+ getFileName(url) {
31104
+ const fileName = decodeURIComponent(url.pathname.slice(url.pathname.lastIndexOf("/") + 1));
31105
+ if (fileName.length === 0) {
31106
+ throw new Error("The OBJ resource URL must include a file name.");
31107
+ }
31108
+ return fileName;
31109
+ }
31110
+ isMtlUrl(url) {
31111
+ return new URL(url).pathname.toLowerCase().endsWith(".mtl");
31112
+ }
31113
+ isObjUrl(url) {
31114
+ return new URL(url).pathname.toLowerCase().endsWith(".obj");
31115
+ }
31116
+ }
30743
31117
  const DEFAULT_BACKGROUND_COLOR = 3355443;
30744
31118
  class Renderer {
30745
31119
  activeModels = [];
@@ -30911,6 +31285,47 @@ class Renderer {
30911
31285
  stone: source
30912
31286
  });
30913
31287
  }
31288
+ importObjResources(source) {
31289
+ this.assertNotDisposed();
31290
+ if (this.contextLost) {
31291
+ return Promise.resolve({
31292
+ code: ObjImportFailureCode$1.RenderFailed,
31293
+ success: false
31294
+ });
31295
+ }
31296
+ const session = this.startImportSession();
31297
+ try {
31298
+ return this.completeResourceListImport(session, new ObjResourceList(source.fileUrls));
31299
+ } catch {
31300
+ this.finishImportSession(session);
31301
+ return Promise.resolve({
31302
+ code: ObjImportFailureCode$1.InvalidSource,
31303
+ success: false
31304
+ });
31305
+ }
31306
+ }
31307
+ importObjResourceScene(source) {
31308
+ this.assertNotDisposed();
31309
+ if (this.contextLost) {
31310
+ return Promise.resolve({
31311
+ code: ObjImportFailureCode$1.RenderFailed,
31312
+ success: false
31313
+ });
31314
+ }
31315
+ const session = this.startImportSession();
31316
+ try {
31317
+ return this.completeSceneImport(session, {
31318
+ base: source.base === void 0 ? void 0 : new ObjResourceList(source.base.fileUrls),
31319
+ stone: source.stone === void 0 ? void 0 : new ObjResourceList(source.stone.fileUrls)
31320
+ });
31321
+ } catch {
31322
+ this.finishImportSession(session);
31323
+ return Promise.resolve({
31324
+ code: ObjImportFailureCode$1.InvalidSource,
31325
+ success: false
31326
+ });
31327
+ }
31328
+ }
30914
31329
  importObjScene(source) {
30915
31330
  this.assertNotDisposed();
30916
31331
  if (this.contextLost) {
@@ -30951,7 +31366,7 @@ class Renderer {
30951
31366
  success: false
30952
31367
  };
30953
31368
  }
30954
- const firstCandidate = await this.loadSceneModel(session, firstSource);
31369
+ const firstCandidate = await this.loadModel(session, firstSource);
30955
31370
  if (this.isImportResult(firstCandidate)) {
30956
31371
  return firstCandidate;
30957
31372
  }
@@ -30959,7 +31374,7 @@ class Renderer {
30959
31374
  if (stoneSource === void 0 || baseSource === void 0) {
30960
31375
  return this.replaceActiveModels(session, candidateModels);
30961
31376
  }
30962
- const secondCandidate = await this.loadSceneModel(session, baseSource);
31377
+ const secondCandidate = await this.loadModel(session, baseSource);
30963
31378
  if (this.isImportResult(secondCandidate)) {
30964
31379
  this.releaseModels(candidateModels);
30965
31380
  return secondCandidate;
@@ -30967,10 +31382,17 @@ class Renderer {
30967
31382
  candidateModels.push(secondCandidate);
30968
31383
  return this.replaceActiveModels(session, candidateModels);
30969
31384
  }
30970
- async loadSceneModel(session, source) {
31385
+ async completeResourceListImport(session, resources) {
31386
+ const candidate = await this.loadModel(session, resources);
31387
+ if (this.isImportResult(candidate)) {
31388
+ return candidate;
31389
+ }
31390
+ return this.replaceActiveModels(session, [candidate]);
31391
+ }
31392
+ async loadModel(session, source) {
30971
31393
  let result;
30972
31394
  try {
30973
- result = await this.modelLoader.load(source, session.controller.signal);
31395
+ result = source instanceof ObjResourceList ? await this.modelLoader.loadResources(source, session.controller.signal) : await this.modelLoader.load(source, session.controller.signal);
30974
31396
  } catch {
30975
31397
  return this.completeUnexpectedImportFailure(session);
30976
31398
  }
@@ -31256,6 +31678,14 @@ class Application {
31256
31678
  this.assertNotDisposed();
31257
31679
  return this.mapAsyncObjImportResult(this.getRenderer().importObj(source));
31258
31680
  }
31681
+ importObjResources(source) {
31682
+ this.assertNotDisposed();
31683
+ return this.mapAsyncObjImportResult(this.getRenderer().importObjResources(source));
31684
+ }
31685
+ importObjResourceScene(source) {
31686
+ this.assertNotDisposed();
31687
+ return this.mapAsyncObjImportResult(this.getRenderer().importObjResourceScene(source));
31688
+ }
31259
31689
  importObjScene(source) {
31260
31690
  this.assertNotDisposed();
31261
31691
  return this.mapAsyncObjImportResult(this.getRenderer().importObjScene(source));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingbi/studio",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "module": "./index.js",