gltf-parser-plugin 1.1.4 → 1.1.5

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.
@@ -1755,9 +1755,7 @@ class GLTFWorkerLoader extends Loader {
1755
1755
  }
1756
1756
  }
1757
1757
  function ensureColor(color) {
1758
- if (color instanceof Color) {
1759
- return color;
1760
- }
1758
+ if (color instanceof Color) return color;
1761
1759
  return new Color(color);
1762
1760
  }
1763
1761
  function getMaterials(mesh) {
@@ -1765,101 +1763,196 @@ function getMaterials(mesh) {
1765
1763
  if (!mat) return [];
1766
1764
  return Array.isArray(mat) ? mat : [mat];
1767
1765
  }
1768
- function isColorMaterial(material) {
1769
- return "color" in material && typeof material.color !== "undefined";
1766
+ function getMaterialForColor(color) {
1767
+ const key = color.getHex();
1768
+ if (!materialCache.has(key)) {
1769
+ materialCache.set(key, new MeshStandardMaterial({
1770
+ color: color.clone(),
1771
+ roughness: 0.5,
1772
+ metalness: 0.1
1773
+ }));
1774
+ }
1775
+ return materialCache.get(key);
1770
1776
  }
1771
- class ComponentColorModifier {
1777
+ const materialCache = /* @__PURE__ */ new Map();
1778
+ class ComponentColorHelper {
1772
1779
  constructor(context) {
1773
1780
  this.context = context;
1774
1781
  }
1775
- _originalColors = /* @__PURE__ */ new Map();
1776
- _originalOpacities = /* @__PURE__ */ new Map();
1782
+ coloredOids = /* @__PURE__ */ new Set();
1783
+ materialByOid = /* @__PURE__ */ new Map();
1784
+ originalMaterialByMesh = /* @__PURE__ */ new Map();
1785
+ opacityModifiedOids = /* @__PURE__ */ new Set();
1786
+ opacityByOid = /* @__PURE__ */ new Map();
1787
+ originalOpacityByMaterial = /* @__PURE__ */ new Map();
1788
+ meshChangeHandlers = /* @__PURE__ */ new Map();
1789
+ getAllModifiedOids() {
1790
+ return Array.from(/* @__PURE__ */ new Set([...this.coloredOids, ...this.opacityModifiedOids]));
1791
+ }
1792
+ applyToMeshes(oid) {
1793
+ const scene = this.context.getScene();
1794
+ if (!scene) return;
1795
+ const collector = this.context.getMeshCollectorByOid(oid);
1796
+ const colorMaterial = this.materialByOid.get(oid);
1797
+ const opacity = this.opacityByOid.get(oid);
1798
+ collector.meshes.forEach((mesh) => {
1799
+ if (!mesh.parent) scene.add(mesh);
1800
+ if (colorMaterial) {
1801
+ mesh.material = colorMaterial;
1802
+ }
1803
+ if (opacity !== void 0) {
1804
+ for (const mat of getMaterials(mesh)) {
1805
+ if (!this.originalOpacityByMaterial.has(mat)) {
1806
+ this.originalOpacityByMaterial.set(mat, mat.opacity);
1807
+ }
1808
+ mat.opacity = opacity;
1809
+ mat.transparent = opacity < 1;
1810
+ }
1811
+ }
1812
+ });
1813
+ }
1777
1814
  /**
1778
- * 根据 oid 数组修改构件颜色
1779
- * @param oids 构件 OID 数组
1780
- * @param color 颜色值,支持 hex 数字、颜色字符串(如 "#ff0000")、THREE.Color 对象
1815
+ * 根据 oid 数组设置构件颜色
1816
+ * 隐藏原 mesh,将 split mesh 替换材质后加入场景
1781
1817
  */
1782
- setColorByOids(oids, color) {
1818
+ setComponentColorByOids(oids, color) {
1819
+ const scene = this.context.getScene();
1820
+ if (!scene) return;
1783
1821
  const threeColor = ensureColor(color);
1822
+ const material = getMaterialForColor(threeColor);
1784
1823
  for (const oid of oids) {
1785
- const meshes = this.context.getMeshesByOid(oid);
1786
- for (const mesh of meshes) {
1787
- for (const material of getMaterials(mesh)) {
1788
- if (isColorMaterial(material)) {
1789
- if (!this._originalColors.has(material)) {
1790
- this._originalColors.set(material, material.color.clone());
1791
- }
1792
- material.color.copy(threeColor);
1793
- }
1824
+ this.coloredOids.add(oid);
1825
+ this.materialByOid.set(oid, material);
1826
+ const collector = this.context.getMeshCollectorByOid(oid);
1827
+ collector.meshes.forEach((mesh) => {
1828
+ if (!this.originalMaterialByMesh.has(mesh.uuid)) {
1829
+ this.originalMaterialByMesh.set(mesh.uuid, mesh.material);
1794
1830
  }
1831
+ mesh.material = material;
1832
+ scene.add(mesh);
1833
+ });
1834
+ if (!this.meshChangeHandlers.has(oid)) {
1835
+ const handler = () => this.applyToMeshes(oid);
1836
+ this.meshChangeHandlers.set(oid, handler);
1837
+ collector.addEventListener("mesh-change", handler);
1795
1838
  }
1796
1839
  }
1840
+ this.context.hideByOids(this.getAllModifiedOids());
1797
1841
  }
1798
1842
  /**
1799
- * 恢复指定构件的颜色为修改前的状态
1800
- * @param oids 构件 OID 数组
1843
+ * 恢复指定构件的颜色
1844
+ * 若该 oid 已无颜色且无透明度修改,则从场景移除 split mesh 并 unhide 原 mesh
1801
1845
  */
1802
- restoreColorByOids(oids) {
1846
+ restoreComponentColorByOids(oids) {
1847
+ const scene = this.context.getScene();
1848
+ if (!scene) return;
1803
1849
  for (const oid of oids) {
1804
- const meshes = this.context.getMeshesByOid(oid);
1805
- for (const mesh of meshes) {
1806
- for (const material of getMaterials(mesh)) {
1807
- if (isColorMaterial(material)) {
1808
- const original = this._originalColors.get(material);
1809
- if (original) {
1810
- material.color.copy(original);
1811
- this._originalColors.delete(material);
1850
+ this.coloredOids.delete(oid);
1851
+ this.materialByOid.delete(oid);
1852
+ const collector = this.context.getMeshCollectorByOid(oid);
1853
+ const opacity = this.opacityByOid.get(oid);
1854
+ collector.meshes.forEach((mesh) => {
1855
+ const originalMat = this.originalMaterialByMesh.get(mesh.uuid);
1856
+ if (originalMat) {
1857
+ mesh.material = originalMat;
1858
+ this.originalMaterialByMesh.delete(mesh.uuid);
1859
+ if (opacity !== void 0) {
1860
+ for (const mat of getMaterials(mesh)) {
1861
+ if (!this.originalOpacityByMaterial.has(mat)) {
1862
+ this.originalOpacityByMaterial.set(mat, mat.opacity);
1863
+ }
1864
+ mat.opacity = opacity;
1865
+ mat.transparent = opacity < 1;
1812
1866
  }
1813
1867
  }
1814
1868
  }
1869
+ if (!this.coloredOids.has(oid) && !this.opacityModifiedOids.has(oid) && mesh.parent === scene) {
1870
+ scene.remove(mesh);
1871
+ }
1872
+ });
1873
+ if (!this.coloredOids.has(oid) && !this.opacityModifiedOids.has(oid)) {
1874
+ const handler = this.meshChangeHandlers.get(oid);
1875
+ if (handler) {
1876
+ this.meshChangeHandlers.delete(oid);
1877
+ collector.removeEventListener("mesh-change", handler);
1878
+ }
1815
1879
  }
1816
1880
  }
1881
+ this.context.unhideByOids(oids);
1817
1882
  }
1818
1883
  /**
1819
- * 根据 oid 数组修改构件颜色透明度
1884
+ * 根据 oid 数组设置构件透明度
1885
+ * 隐藏原 mesh,将 split mesh 修改材质透明度后加入场景
1820
1886
  * @param oids 构件 OID 数组
1821
1887
  * @param opacity 透明度,0-1,0 完全透明,1 完全不透明
1822
1888
  */
1823
- setOpacityByOids(oids, opacity) {
1889
+ setComponentOpacityByOids(oids, opacity) {
1890
+ const scene = this.context.getScene();
1891
+ if (!scene) return;
1824
1892
  const clampedOpacity = Math.max(0, Math.min(1, opacity));
1825
1893
  for (const oid of oids) {
1826
- const meshes = this.context.getMeshesByOid(oid);
1827
- for (const mesh of meshes) {
1828
- for (const material of getMaterials(mesh)) {
1829
- if (!this._originalOpacities.has(material)) {
1830
- this._originalOpacities.set(material, material.opacity);
1831
- }
1832
- material.opacity = clampedOpacity;
1833
- material.transparent = clampedOpacity < 1;
1894
+ this.opacityModifiedOids.add(oid);
1895
+ this.opacityByOid.set(oid, clampedOpacity);
1896
+ const colorMat = this.materialByOid.get(oid);
1897
+ if (colorMat && colorMat.opacity !== clampedOpacity) {
1898
+ const clone = colorMat.clone();
1899
+ clone.opacity = clampedOpacity;
1900
+ clone.transparent = clampedOpacity < 1;
1901
+ this.materialByOid.set(oid, clone);
1902
+ this.originalOpacityByMaterial.set(clone, 1);
1903
+ }
1904
+ const collector = this.context.getMeshCollectorByOid(oid);
1905
+ collector.meshes.forEach((mesh) => {
1906
+ scene.add(mesh);
1907
+ const mat = colorMat ? this.materialByOid.get(oid) : mesh.material;
1908
+ if (!this.originalOpacityByMaterial.has(mat)) {
1909
+ this.originalOpacityByMaterial.set(mat, mat.opacity);
1834
1910
  }
1911
+ mat.opacity = clampedOpacity;
1912
+ mat.transparent = clampedOpacity < 1;
1913
+ if (colorMat) mesh.material = mat;
1914
+ });
1915
+ if (!this.meshChangeHandlers.has(oid)) {
1916
+ const handler = () => this.applyToMeshes(oid);
1917
+ this.meshChangeHandlers.set(oid, handler);
1918
+ collector.addEventListener("mesh-change", handler);
1835
1919
  }
1836
1920
  }
1921
+ this.context.hideByOids(this.getAllModifiedOids());
1837
1922
  }
1838
1923
  /**
1839
- * 恢复指定构件的透明度为修改前的状态
1840
- * @param oids 构件 OID 数组
1924
+ * 恢复指定构件的透明度
1925
+ * 若该 oid 已无颜色且无透明度修改,则从场景移除 split mesh 并 unhide 原 mesh
1841
1926
  */
1842
- restoreOpacityByOids(oids) {
1927
+ restoreComponentOpacityByOids(oids) {
1928
+ const scene = this.context.getScene();
1929
+ if (!scene) return;
1843
1930
  for (const oid of oids) {
1844
- const meshes = this.context.getMeshesByOid(oid);
1845
- for (const mesh of meshes) {
1846
- for (const material of getMaterials(mesh)) {
1847
- const original = this._originalOpacities.get(material);
1931
+ this.opacityModifiedOids.delete(oid);
1932
+ this.opacityByOid.delete(oid);
1933
+ const collector = this.context.getMeshCollectorByOid(oid);
1934
+ collector.meshes.forEach((mesh) => {
1935
+ for (const mat of getMaterials(mesh)) {
1936
+ const original = this.originalOpacityByMaterial.get(mat);
1848
1937
  if (original !== void 0) {
1849
- material.opacity = original;
1850
- material.transparent = original < 1;
1851
- this._originalOpacities.delete(material);
1938
+ mat.opacity = original;
1939
+ mat.transparent = original < 1;
1940
+ this.originalOpacityByMaterial.delete(mat);
1852
1941
  }
1853
1942
  }
1943
+ if (!this.coloredOids.has(oid) && !this.opacityModifiedOids.has(oid) && mesh.parent === scene) {
1944
+ scene.remove(mesh);
1945
+ }
1946
+ });
1947
+ if (!this.coloredOids.has(oid) && !this.opacityModifiedOids.has(oid)) {
1948
+ const handler = this.meshChangeHandlers.get(oid);
1949
+ if (handler) {
1950
+ this.meshChangeHandlers.delete(oid);
1951
+ collector.removeEventListener("mesh-change", handler);
1952
+ }
1854
1953
  }
1855
1954
  }
1856
- }
1857
- /**
1858
- * 清除缓存的原始值,释放引用
1859
- */
1860
- dispose() {
1861
- this._originalColors.clear();
1862
- this._originalOpacities.clear();
1955
+ this.context.unhideByOids(oids);
1863
1956
  }
1864
1957
  }
1865
1958
  class InteractionFilter {
@@ -2128,7 +2221,7 @@ class GLTFParserPlugin {
2128
2221
  _modelInfo = null;
2129
2222
  _modelInfoPromise = null;
2130
2223
  _interactionFilter;
2131
- _componentColorModifier;
2224
+ _componentColorHelper = null;
2132
2225
  // --- Mesh helper properties ---
2133
2226
  oids = [];
2134
2227
  renderer = null;
@@ -2154,9 +2247,6 @@ class GLTFParserPlugin {
2154
2247
  this._interactionFilter = new InteractionFilter({
2155
2248
  getCollectorCache: () => this.collectorCache
2156
2249
  });
2157
- this._componentColorModifier = new ComponentColorModifier({
2158
- getMeshesByOid: (oid) => this._getMeshesByOidInternal(oid)
2159
- });
2160
2250
  setMaxWorkers(this._options.maxWorkers);
2161
2251
  }
2162
2252
  /**
@@ -2164,6 +2254,12 @@ class GLTFParserPlugin {
2164
2254
  */
2165
2255
  init(tiles) {
2166
2256
  this.tiles = tiles;
2257
+ this._componentColorHelper = new ComponentColorHelper({
2258
+ hideByOids: (oids) => this.hideByOids(oids),
2259
+ unhideByOids: (oids) => this.unhideByOids(oids),
2260
+ getMeshCollectorByOid: (oid) => this.getMeshCollectorByOid(oid),
2261
+ getScene: () => this.tiles?.group ?? null
2262
+ });
2167
2263
  this._loader = new GLTFWorkerLoader(tiles.manager, {
2168
2264
  metadata: this._options.metadata,
2169
2265
  materialBuilder: this._options.materialBuilder
@@ -2567,39 +2663,6 @@ class GLTFParserPlugin {
2567
2663
  getIsolatedOids() {
2568
2664
  return this._interactionFilter.getIsolatedOids();
2569
2665
  }
2570
- // =============================================
2571
- // Component Color Modifier Methods (delegated)
2572
- // =============================================
2573
- /**
2574
- * 根据 oid 数组修改构件颜色
2575
- * @param oids 构件 OID 数组
2576
- * @param color 颜色值,支持 hex 数字(如 0xff0000)、颜色字符串(如 "#ff0000")、THREE.Color 对象
2577
- */
2578
- setColorByOids(oids, color) {
2579
- this._componentColorModifier.setColorByOids(oids, color);
2580
- }
2581
- /**
2582
- * 根据 oid 数组修改构件颜色透明度
2583
- * @param oids 构件 OID 数组
2584
- * @param opacity 透明度,0-1,0 完全透明,1 完全不透明
2585
- */
2586
- setOpacityByOids(oids, opacity) {
2587
- this._componentColorModifier.setOpacityByOids(oids, opacity);
2588
- }
2589
- /**
2590
- * 恢复指定构件的颜色为修改前的状态
2591
- * @param oids 构件 OID 数组
2592
- */
2593
- restoreColorByOids(oids) {
2594
- this._componentColorModifier.restoreColorByOids(oids);
2595
- }
2596
- /**
2597
- * 恢复指定构件的透明度为修改前的状态
2598
- * @param oids 构件 OID 数组
2599
- */
2600
- restoreOpacityByOids(oids) {
2601
- this._componentColorModifier.restoreOpacityByOids(oids);
2602
- }
2603
2666
  /**
2604
2667
  * 内部方法:根据 oid 获取 mesh 数组
2605
2668
  */
@@ -2651,6 +2714,38 @@ class GLTFParserPlugin {
2651
2714
  this.oids = newOids;
2652
2715
  this.featureIdCount = this._calculateFeatureIdCount();
2653
2716
  }
2717
+ /**
2718
+ * 根据 oid 数组设置构件颜色
2719
+ * 隐藏原 mesh,将 split mesh 替换材质后加入场景(使用 tiles.group)
2720
+ * @param oids 构件 OID 数组
2721
+ * @param color 颜色值,支持 hex 数字、颜色字符串(如 "#ff0000")、THREE.Color 对象
2722
+ */
2723
+ setComponentColorByOids(oids, color) {
2724
+ this._componentColorHelper?.setComponentColorByOids(oids, color);
2725
+ }
2726
+ /**
2727
+ * 恢复指定构件的颜色
2728
+ * 从场景移除 split mesh,unhide 原 mesh
2729
+ * @param oids 构件 OID 数组
2730
+ */
2731
+ restoreComponentColorByOids(oids) {
2732
+ this._componentColorHelper?.restoreComponentColorByOids(oids);
2733
+ }
2734
+ /**
2735
+ * 根据 oid 数组设置构件透明度
2736
+ * @param oids 构件 OID 数组
2737
+ * @param opacity 透明度,0-1,0 完全透明,1 完全不透明
2738
+ */
2739
+ setComponentOpacityByOids(oids, opacity) {
2740
+ this._componentColorHelper?.setComponentOpacityByOids(oids, opacity);
2741
+ }
2742
+ /**
2743
+ * 恢复指定构件的透明度
2744
+ * @param oids 构件 OID 数组
2745
+ */
2746
+ restoreComponentOpacityByOids(oids) {
2747
+ this._componentColorHelper?.restoreComponentOpacityByOids(oids);
2748
+ }
2654
2749
  /**
2655
2750
  * Restore the original materials of the mesh
2656
2751
  */
@@ -2688,7 +2783,7 @@ class GLTFParserPlugin {
2688
2783
  this._modelInfo = null;
2689
2784
  this._modelInfoPromise = null;
2690
2785
  this._interactionFilter.dispose();
2691
- this._componentColorModifier.dispose();
2786
+ this._componentColorHelper = null;
2692
2787
  this._loader = null;
2693
2788
  this.tiles = null;
2694
2789
  }