gltf-parser-plugin 1.1.8 → 1.1.10

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.
@@ -393,44 +393,48 @@ var MeshCollector = class extends EventDispatcher {
393
393
  //#endregion
394
394
  //#region src/plugin/style-condition-eval.ts
395
395
  /**
396
- * StyleHelper 中 `show`、`conditions` 条件项的表达式求值一致
397
- * 在 propertyData 的键作为变量名的上下文中执行 `Boolean(expr)`
398
- *
399
- * 实现:对每个表达式字符串只编译一次 `new Function('data', 'with(d){...}')`,
400
- * 避免按「表达式 × 属性键集合」重复编译,也避免每次求值排序/拼接 cacheKey。
396
+ * 编译单个表达式;失败返回 null(无模块级缓存)
401
397
  */
402
- var compiledCache = /* @__PURE__ */ new Map();
403
- var MAX_CACHE_ENTRIES = 512;
404
- function getCompiled(expr) {
405
- let fn = compiledCache.get(expr);
406
- if (fn) return fn;
398
+ function compileStyleCondition(expr) {
399
+ const trimmed = expr.trim();
400
+ if (!trimmed) return null;
407
401
  try {
408
- fn = new Function("data", `var d = data != null && typeof data === "object" ? data : {};
409
- with (d) { return Boolean(${expr}); }`);
402
+ return new Function("data", `var d = data != null && typeof data === "object" ? data : {};
403
+ with (d) { return Boolean(${trimmed}); }`);
410
404
  } catch {
411
405
  return null;
412
406
  }
413
- if (compiledCache.size >= MAX_CACHE_ENTRIES) {
414
- const first = compiledCache.keys().next().value;
415
- if (first !== void 0) compiledCache.delete(first);
416
- }
417
- compiledCache.set(expr, fn);
418
- return fn;
419
407
  }
420
408
  /**
421
- * 清空表达式编译缓存(热更新或单测可调用)
409
+ * 遍历 style 的 show 与 conditions,对每个出现过的字符串表达式只编译一次
422
410
  */
423
- function clearStyleConditionCache() {
424
- compiledCache.clear();
411
+ function buildStyleConditionEvaluatorMap(config) {
412
+ const strings = /* @__PURE__ */ new Set();
413
+ if (config.show?.trim()) strings.add(config.show.trim());
414
+ for (const [cond] of config.conditions ?? []) if (typeof cond === "string" && cond.trim()) strings.add(cond.trim());
415
+ const map = /* @__PURE__ */ new Map();
416
+ for (const s of strings) {
417
+ const fn = compileStyleCondition(s);
418
+ if (fn) map.set(s, fn);
419
+ }
420
+ return map;
425
421
  }
426
- function evaluateStyleCondition(expr, propertyData) {
422
+ function evaluateStyleCondition(expr, propertyData, evaluators) {
427
423
  if (expr === true) return true;
428
424
  if (expr === false) return false;
429
425
  if (typeof expr !== "string" || !expr.trim()) return true;
430
- const fn = getCompiled(expr.trim());
426
+ const trimmed = expr.trim();
427
+ const data = propertyData ?? {};
428
+ const fromMap = evaluators?.get(trimmed);
429
+ if (fromMap) try {
430
+ return fromMap(data);
431
+ } catch {
432
+ return false;
433
+ }
434
+ const fn = compileStyleCondition(trimmed);
431
435
  if (!fn) return false;
432
436
  try {
433
- return fn(propertyData ?? {});
437
+ return fn(data);
434
438
  } catch {
435
439
  return false;
436
440
  }
@@ -2625,6 +2629,36 @@ var PartFrameHelper = class {
2625
2629
  };
2626
2630
  //#endregion
2627
2631
  //#region src/plugin/style-appearance-shared.ts
2632
+ var fnIdentitySeq = /* @__PURE__ */ new WeakMap();
2633
+ var fnIdentityNext = 1;
2634
+ function styleFnIdentity(fn) {
2635
+ let id = fnIdentitySeq.get(fn);
2636
+ if (id === void 0) {
2637
+ id = fnIdentityNext++;
2638
+ fnIdentitySeq.set(fn, id);
2639
+ }
2640
+ return id;
2641
+ }
2642
+ /** 从构件材质提取贴图,供 material 回调使用 */
2643
+ function extractStyleMaterialMaps(material) {
2644
+ const m = material;
2645
+ const tex = (key) => {
2646
+ const v = m[key];
2647
+ return v && typeof v === "object" && "isTexture" in v && v.isTexture ? v : null;
2648
+ };
2649
+ return {
2650
+ map: tex("map"),
2651
+ normalMap: tex("normalMap"),
2652
+ metalnessMap: tex("metalnessMap"),
2653
+ roughnessMap: tex("roughnessMap"),
2654
+ aoMap: tex("aoMap"),
2655
+ emissiveMap: tex("emissiveMap")
2656
+ };
2657
+ }
2658
+ function resolveStyleMaterial(appearance, originalMaterial) {
2659
+ if (typeof appearance.material === "function") return appearance.material(extractStyleMaterialMaps(originalMaterial));
2660
+ return appearance.material;
2661
+ }
2628
2662
  function vec3Key(v) {
2629
2663
  if (v === void 0) return "";
2630
2664
  if (Array.isArray(v)) return `${v[0] ?? 0},${v[1] ?? 0},${v[2] ?? 0}`;
@@ -2647,7 +2681,7 @@ function applyEuler(target, input) {
2647
2681
  else target.copy(input);
2648
2682
  }
2649
2683
  function appearanceGroupKey(a) {
2650
- return `${a.material.uuid}|${vec3Key(a.translation)}|${vec3Key(a.scale)}|${eulerKey(a.rotation)}|${vec3Key(a.origin)}`;
2684
+ return `${typeof a.material === "function" ? `matFn#${styleFnIdentity(a.material)}` : a.material.uuid}${a.mesh ? `|meshFn#${styleFnIdentity(a.mesh)}` : ""}|${vec3Key(a.translation)}|${vec3Key(a.scale)}|${eulerKey(a.rotation)}|${vec3Key(a.origin)}`;
2651
2685
  }
2652
2686
  function buildPivotStyleMatrix(pivot, sx, sy, sz, euler) {
2653
2687
  const m = new Matrix4().makeTranslation(-pivot.x, -pivot.y, -pivot.z);
@@ -2656,28 +2690,25 @@ function buildPivotStyleMatrix(pivot, sx, sy, sz, euler) {
2656
2690
  m.premultiply(new Matrix4().makeTranslation(pivot.x, pivot.y, pivot.z));
2657
2691
  return m;
2658
2692
  }
2659
- function resolveConditionsAppearance(conditions, propertyData) {
2693
+ function resolveConditionsAppearance(conditions, propertyData, evaluators) {
2660
2694
  if (!conditions?.length) return null;
2661
- for (const [cond, value] of conditions) if (evaluateStyleCondition(cond, propertyData)) return value;
2695
+ for (const [cond, value] of conditions) if (evaluateStyleCondition(cond, propertyData, evaluators)) return value;
2662
2696
  return null;
2663
2697
  }
2664
- function resolveStyleAppearance(conditions, propertyData) {
2665
- return resolveConditionsAppearance(conditions, propertyData);
2666
- }
2667
2698
  /** 与 setStyle 相同的 OID 分组逻辑(show + conditions → 外观分组 + 被 show 隐藏的 OID) */
2668
- function buildAppearanceGroupsFromPropertyMap(propertyByOid, config) {
2699
+ function buildAppearanceGroupsFromPropertyMap(propertyByOid, config, evaluators) {
2669
2700
  const hiddenOidsList = [];
2670
2701
  const groups = /* @__PURE__ */ new Map();
2671
2702
  const conditions = config.conditions ?? [];
2672
2703
  for (const [oid, propertyData] of propertyByOid) {
2673
2704
  if (propertyData == null) continue;
2674
2705
  if (config.show) {
2675
- if (!evaluateStyleCondition(config.show, propertyData)) {
2706
+ if (!evaluateStyleCondition(config.show, propertyData, evaluators)) {
2676
2707
  hiddenOidsList.push(oid);
2677
2708
  continue;
2678
2709
  }
2679
2710
  }
2680
- const appearance = resolveStyleAppearance(conditions, propertyData);
2711
+ const appearance = resolveConditionsAppearance(conditions, propertyData, evaluators);
2681
2712
  if (!appearance) continue;
2682
2713
  const gkey = appearanceGroupKey(appearance);
2683
2714
  let g = groups.get(gkey);
@@ -2714,7 +2745,9 @@ function restoreMeshAppearanceMaps(mesh, maps) {
2714
2745
  */
2715
2746
  function applyStyleAppearanceToMesh(mesh, appearance, scene, maps) {
2716
2747
  if (!maps.originalMaterialByMesh.has(mesh.uuid)) maps.originalMaterialByMesh.set(mesh.uuid, mesh.material);
2717
- mesh.material = appearance.material;
2748
+ const resolvedMaterial = resolveStyleMaterial(appearance, maps.originalMaterialByMesh.get(mesh.uuid));
2749
+ if (appearance.mesh) mesh = appearance.mesh(mesh.geometry, resolvedMaterial);
2750
+ else mesh.material = resolvedMaterial;
2718
2751
  if (appearance.translation !== void 0 || appearance.scale !== void 0 || appearance.rotation !== void 0) {
2719
2752
  if (!maps.originalTransformByMesh.has(mesh.uuid)) maps.originalTransformByMesh.set(mesh.uuid, {
2720
2753
  position: mesh.position.clone(),
@@ -2762,7 +2795,7 @@ function applyStyleAppearanceToMesh(mesh, appearance, scene, maps) {
2762
2795
  * 通过 show 表达式控制可见性,通过 conditions 应用条件材质与可选位姿
2763
2796
  */
2764
2797
  var StyleHelper = class {
2765
- /** 当前样式配置,可通过 plugin.style 获取 */
2798
+ /** 当前样式配置;在插件上可通过 `plugin.style` 读写(与 `setStyle` 等价) */
2766
2799
  style = null;
2767
2800
  styledOids = /* @__PURE__ */ new Set();
2768
2801
  hiddenOids = /* @__PURE__ */ new Set();
@@ -2830,10 +2863,14 @@ var StyleHelper = class {
2830
2863
  }
2831
2864
  this.styleCollectors = [];
2832
2865
  this.meshChangeHandlers.clear();
2833
- const { hiddenOidsList, groups } = buildAppearanceGroupsFromPropertyMap(propertyByOid, {
2866
+ const evaluators = buildStyleConditionEvaluatorMap({
2834
2867
  show: style.show,
2835
2868
  conditions: style.conditions ?? []
2836
2869
  });
2870
+ const { hiddenOidsList, groups } = buildAppearanceGroupsFromPropertyMap(propertyByOid, {
2871
+ show: style.show,
2872
+ conditions: style.conditions ?? []
2873
+ }, evaluators);
2837
2874
  for (const { oids } of groups.values()) for (const oid of oids) this.styledOids.add(oid);
2838
2875
  this.hiddenOids = new Set(hiddenOidsList);
2839
2876
  const oidsToHide = [...hiddenOidsList];
@@ -2894,8 +2931,10 @@ function toMaterial(value) {
2894
2931
  return getMaterialForHighlight(value);
2895
2932
  }
2896
2933
  function toStyleAppearance(ha) {
2934
+ const mat = ha.material;
2897
2935
  return {
2898
- material: toMaterial(ha.material),
2936
+ material: typeof mat === "function" ? mat : mat instanceof Material ? mat : toMaterial(mat),
2937
+ mesh: ha.mesh,
2899
2938
  translation: ha.translation,
2900
2939
  scale: ha.scale,
2901
2940
  rotation: ha.rotation,
@@ -2929,12 +2968,16 @@ var PartHighlightHelper = class {
2929
2968
  mergeAppearanceByOid(propertyByOid) {
2930
2969
  const appearanceByOid = /* @__PURE__ */ new Map();
2931
2970
  for (const [, hl] of this.highlightGroups) {
2971
+ const evaluators = buildStyleConditionEvaluatorMap({
2972
+ show: hl.show,
2973
+ conditions: hl.conditions ?? []
2974
+ });
2932
2975
  const conditions = (hl.conditions ?? []).map(([c, h]) => [c, toStyleAppearance(h)]);
2933
2976
  for (const [oid, propertyData] of propertyByOid) {
2934
2977
  if (propertyData == null) continue;
2935
2978
  if (hl.oids && !hl.oids.includes(oid)) continue;
2936
- if (hl.show && !evaluateStyleCondition(hl.show, propertyData)) continue;
2937
- const app = resolveConditionsAppearance(conditions, propertyData);
2979
+ if (hl.show && !evaluateStyleCondition(hl.show, propertyData, evaluators)) continue;
2980
+ const app = resolveConditionsAppearance(conditions, propertyData, evaluators);
2938
2981
  if (!app) continue;
2939
2982
  appearanceByOid.set(oid, app);
2940
2983
  }
@@ -2944,10 +2987,16 @@ var PartHighlightHelper = class {
2944
2987
  /** 各组 show 失败需隐藏的 OID(与 setStyle 一致:show 不满足则隐藏原片) */
2945
2988
  collectUnionShowHide(propertyByOid) {
2946
2989
  const unionHide = /* @__PURE__ */ new Set();
2947
- for (const [, hl] of this.highlightGroups) for (const [oid, propertyData] of propertyByOid) {
2948
- if (propertyData == null) continue;
2949
- if (hl.oids && !hl.oids.includes(oid)) continue;
2950
- if (hl.show && !evaluateStyleCondition(hl.show, propertyData)) unionHide.add(oid);
2990
+ for (const [, hl] of this.highlightGroups) {
2991
+ const evaluators = buildStyleConditionEvaluatorMap({
2992
+ show: hl.show,
2993
+ conditions: hl.conditions ?? []
2994
+ });
2995
+ for (const [oid, propertyData] of propertyByOid) {
2996
+ if (propertyData == null) continue;
2997
+ if (hl.oids && !hl.oids.includes(oid)) continue;
2998
+ if (hl.show && !evaluateStyleCondition(hl.show, propertyData, evaluators)) unionHide.add(oid);
2999
+ }
2951
3000
  }
2952
3001
  return unionHide;
2953
3002
  }
@@ -3368,6 +3417,8 @@ var GLTFParserPlugin = class {
3368
3417
  if (tileWithCache.engineData?.scene) this._onLoadModel(tileWithCache.engineData.scene);
3369
3418
  return true;
3370
3419
  }, null);
3420
+ this._notifyCollectors();
3421
+ if (this._options.style !== void 0) this._styleHelper?.setStyle(this._options.style ?? null);
3371
3422
  }
3372
3423
  _createPartEffectHost() {
3373
3424
  return {
@@ -3488,8 +3539,9 @@ var GLTFParserPlugin = class {
3488
3539
  if (!this.tiles) return null;
3489
3540
  const cond = condition.trim();
3490
3541
  if (!cond) return null;
3542
+ const evaluators = buildStyleConditionEvaluatorMap({ show: cond });
3491
3543
  const targetOids = [];
3492
- for (const oid of getAllOidsFromTiles(this.tiles)) if (evaluateStyleCondition(cond, getPropertyDataByOid(this.tiles, oid))) targetOids.push(oid);
3544
+ for (const oid of getAllOidsFromTiles(this.tiles)) if (evaluateStyleCondition(cond, getPropertyDataByOid(this.tiles, oid), evaluators)) targetOids.push(oid);
3493
3545
  if (targetOids.length === 0) return null;
3494
3546
  return this._getCenterFromOidList(targetOids);
3495
3547
  }
@@ -3551,6 +3603,7 @@ var GLTFParserPlugin = class {
3551
3603
  */
3552
3604
  _onLoadModelCB = ({ scene }) => {
3553
3605
  this._onLoadModel(scene);
3606
+ this._notifyCollectors();
3554
3607
  };
3555
3608
  /**
3556
3609
  * Tiles load end callback
@@ -3569,6 +3622,7 @@ var GLTFParserPlugin = class {
3569
3622
  _notifyCollectors() {
3570
3623
  for (const collector of this.collectors) collector._updateMeshes();
3571
3624
  this._styleHelper?.onTilesLoadEnd();
3625
+ this._partHighlightHelper?.onTilesLoadEnd();
3572
3626
  }
3573
3627
  _registerCollector(collector) {
3574
3628
  this.collectors.add(collector);
@@ -3721,8 +3775,9 @@ var GLTFParserPlugin = class {
3721
3775
  targetOids = [...new Set(params.oids)].sort((a, b) => a - b);
3722
3776
  } else {
3723
3777
  const candidate = params.oids.length === 0 ? getAllOidsFromTiles(this.tiles) : [...new Set(params.oids)];
3778
+ const evaluators = buildStyleConditionEvaluatorMap({ show: cond });
3724
3779
  targetOids = [];
3725
- for (const oid of candidate) if (evaluateStyleCondition(cond, getPropertyDataByOid(this.tiles, oid))) targetOids.push(oid);
3780
+ for (const oid of candidate) if (evaluateStyleCondition(cond, getPropertyDataByOid(this.tiles, oid), evaluators)) targetOids.push(oid);
3726
3781
  targetOids.sort((a, b) => a - b);
3727
3782
  }
3728
3783
  return this._getMeshesByOidsInternal(targetOids);
@@ -3862,11 +3917,14 @@ var GLTFParserPlugin = class {
3862
3917
  this._styleHelper?.setStyle(style);
3863
3918
  }
3864
3919
  /**
3865
- * 当前样式配置,只读
3920
+ * 当前样式配置。赋值与 `setStyle(...)` 等价,例如 `plugin.style = { show, conditions }`。
3866
3921
  */
3867
3922
  get style() {
3868
3923
  return this._styleHelper?.style ?? null;
3869
3924
  }
3925
+ set style(style) {
3926
+ this.setStyle(style);
3927
+ }
3870
3928
  /**
3871
3929
  * 清除构件样式
3872
3930
  */
@@ -3941,6 +3999,6 @@ var GLTFParserPlugin = class {
3941
3999
  }
3942
4000
  };
3943
4001
  //#endregion
3944
- export { GLTFParserPlugin, MeshCollector, clearStyleConditionCache, decodeGzipBase64DataUriSync, evaluateStyleCondition, getStructureDataUriFromTileset, meshCollectorGroupKey, meshCollectorQueryCacheKey, normalizeMeshCollectorOids, parseEmbeddedStructureDataFromTilesSync };
4002
+ export { GLTFParserPlugin, MeshCollector, buildStyleConditionEvaluatorMap, compileStyleCondition, decodeGzipBase64DataUriSync, evaluateStyleCondition, extractStyleMaterialMaps, getStructureDataUriFromTileset, meshCollectorGroupKey, meshCollectorQueryCacheKey, normalizeMeshCollectorOids, parseEmbeddedStructureDataFromTilesSync };
3945
4003
 
3946
4004
  //# sourceMappingURL=gltf-parser-plugin.module.js.map