three-base 2.0.142 → 2.0.166

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.
Files changed (231) hide show
  1. package/DirectionalLight.d.ts +6 -6
  2. package/DirectionalLight.js +68 -68
  3. package/EventMap.d.ts +103 -103
  4. package/EventMap.js +17 -17
  5. package/EventMesh.d.ts +18 -18
  6. package/EventMesh.js +59 -59
  7. package/ExtrudeMesh.d.ts +112 -112
  8. package/ExtrudeMesh.js +342 -342
  9. package/FPScontrol.d.ts +531 -511
  10. package/FPScontrol.js +1866 -1799
  11. package/FPScontrol.ts +1922 -1855
  12. package/Fire/Fire.d.ts +28 -28
  13. package/Fire/Fire.js +80 -80
  14. package/Fire/FireGeometry.d.ts +9 -9
  15. package/Fire/FireGeometry.js +40 -40
  16. package/Fire/FireMaterial.d.ts +28 -28
  17. package/Fire/FireMaterial.js +32 -32
  18. package/Fire/index.d.ts +2 -2
  19. package/Fire/index.js +2 -2
  20. package/GLTFDracoLoader.d.ts +71 -71
  21. package/GLTFDracoLoader.js +266 -266
  22. package/GLTFDracoLoader.ts +1 -1
  23. package/Grass/Grass.d.ts +8 -8
  24. package/Grass/Grass.js +38 -38
  25. package/Grass/index.d.ts +2 -2
  26. package/Grass/index.js +2 -2
  27. package/Ground1/Ground1.d.ts +10 -10
  28. package/Ground1/Ground1.js +71 -71
  29. package/Ground1/index.d.ts +1 -1
  30. package/Ground1/index.js +1 -1
  31. package/MeshBase.d.ts +36 -36
  32. package/MeshBase.js +251 -247
  33. package/MeshBase.ts +6 -2
  34. package/Mirror.d.ts +25 -25
  35. package/Mirror.js +143 -143
  36. package/MktMesh/MktMesh.d.ts +301 -291
  37. package/MktMesh/MktMesh.js +1064 -1045
  38. package/MktMesh/MktMesh.ts +32 -11
  39. package/MktMesh/assetUrl.d.ts +59 -35
  40. package/MktMesh/assetUrl.js +165 -69
  41. package/MktMesh/assetUrl.ts +164 -69
  42. package/MktMesh/mktMappingShader.d.ts +12 -12
  43. package/MktMesh/mktMappingShader.js +138 -138
  44. package/MktMesh/mktMappingShader.ts +139 -139
  45. package/MktMesh/mktShader.d.ts +263 -263
  46. package/MktMesh/mktShader.js +1236 -1236
  47. package/MktMesh/mktShader.ts +1344 -1344
  48. package/MktMesh/panoBitmapTexture.d.ts +25 -25
  49. package/MktMesh/panoBitmapTexture.js +52 -52
  50. package/MktMesh/panoBitmapTexture.ts +54 -54
  51. package/MktMesh/panoSlotBind.d.ts +29 -29
  52. package/MktMesh/panoSlotBind.js +106 -106
  53. package/MktMesh/panoSlotBind.ts +153 -153
  54. package/MktMesh/panoSlotRoster.d.ts +22 -22
  55. package/MktMesh/panoSlotRoster.js +169 -169
  56. package/MktMesh/panoSlotRoster.ts +168 -168
  57. package/MktMesh/panoTileStitcher.d.ts +119 -119
  58. package/MktMesh/panoTileStitcher.js +529 -529
  59. package/MktMesh/panoTileStitcher.ts +616 -616
  60. package/MktMesh/types.d.ts +75 -75
  61. package/MktMesh/types.js +1 -1
  62. package/MktMesh/wallCapTessellate.d.ts +33 -33
  63. package/MktMesh/wallCapTessellate.js +97 -97
  64. package/MktMesh/wallCapTessellate.ts +68 -68
  65. package/PipeMesh/PathGeometry.d.ts +44 -44
  66. package/PipeMesh/PathGeometry.js +307 -307
  67. package/PipeMesh/PathPoint.d.ts +17 -17
  68. package/PipeMesh/PathPoint.js +31 -31
  69. package/PipeMesh/PathPointList.d.ts +31 -31
  70. package/PipeMesh/PathPointList.js +209 -209
  71. package/PipeMesh/PathTubeGeometry.d.ts +25 -25
  72. package/PipeMesh/PathTubeGeometry.js +130 -130
  73. package/PipeMesh/PipeMesh.d.ts +25 -25
  74. package/PipeMesh/PipeMesh.js +63 -63
  75. package/PipeMesh/index.d.ts +1 -1
  76. package/PipeMesh/index.js +1 -1
  77. package/PlaneModal1/PlaneModal1.d.ts +34 -34
  78. package/PlaneModal1/PlaneModal1.js +109 -109
  79. package/PlaneModal1/index.d.ts +1 -1
  80. package/PlaneModal1/index.js +1 -1
  81. package/PlaneText.d.ts +27 -27
  82. package/PlaneText.js +35 -35
  83. package/PlaneWithHtml.d.ts +13 -13
  84. package/PlaneWithHtml.js +66 -64
  85. package/PlaneWithHtml.ts +3 -1
  86. package/PointLight/PointLight.d.ts +13 -13
  87. package/PointLight/PointLight.js +64 -64
  88. package/PointLight/index.d.ts +1 -1
  89. package/PointLight/index.js +1 -1
  90. package/Sky/Sky.d.ts +9 -9
  91. package/Sky/Sky.js +22 -22
  92. package/Sky/index.d.ts +1 -1
  93. package/Sky/index.js +1 -1
  94. package/SpotLight.d.ts +6 -6
  95. package/SpotLight.js +72 -72
  96. package/SpriteModal1/SpriteModal1.d.ts +33 -33
  97. package/SpriteModal1/SpriteModal1.js +116 -116
  98. package/SpriteModal1/index.d.ts +1 -1
  99. package/SpriteModal1/index.js +1 -1
  100. package/SpriteText.d.ts +46 -46
  101. package/SpriteText.js +176 -176
  102. package/SpriteText2.d.ts +48 -48
  103. package/SpriteText2.js +223 -223
  104. package/SpriteText3.d.ts +86 -86
  105. package/SpriteText3.js +517 -517
  106. package/SpriteText3.ts +599 -599
  107. package/SpriteWithHtml.d.ts +9 -9
  108. package/SpriteWithHtml.js +46 -44
  109. package/SpriteWithHtml.ts +3 -1
  110. package/Text3D/Text3D.d.ts +20 -20
  111. package/Text3D/Text3D.js +58 -58
  112. package/Text3D/fontController.d.ts +60 -60
  113. package/Text3D/fontController.js +166 -166
  114. package/Text3D/index.d.ts +1 -1
  115. package/Text3D/index.js +1 -1
  116. package/ThreeBase.d.ts +248 -248
  117. package/ThreeBase.js +1202 -1202
  118. package/ThreeBase.ts +1314 -1314
  119. package/ThreeMouse.d.ts +53 -54
  120. package/ThreeMouse.js +453 -453
  121. package/Transition.d.ts +45 -45
  122. package/Transition.js +209 -209
  123. package/Water/Water.d.ts +5 -5
  124. package/Water/Water.js +44 -44
  125. package/Water/index.d.ts +2 -2
  126. package/Water/index.js +2 -2
  127. package/WaterFlow/FloatingDuck.d.ts +88 -88
  128. package/WaterFlow/FloatingDuck.js +307 -307
  129. package/WaterFlow/FloatingDuck.ts +445 -445
  130. package/WaterFlow/GPUFluidSimulation.d.ts +56 -56
  131. package/WaterFlow/GPUFluidSimulation.js +781 -781
  132. package/WaterFlow/GPUFluidSimulation.ts +827 -827
  133. package/WaterFlow/ReservoirSystem.d.ts +106 -106
  134. package/WaterFlow/ReservoirSystem.js +611 -611
  135. package/WaterFlow/ReservoirSystem.ts +754 -754
  136. package/WaterFlow/SPHField.d.ts +35 -35
  137. package/WaterFlow/SPHField.js +203 -203
  138. package/WaterFlow/SPHField.ts +228 -228
  139. package/WaterFlow/ScreenSpaceFluidPass.d.ts +69 -69
  140. package/WaterFlow/ScreenSpaceFluidPass.js +728 -728
  141. package/WaterFlow/ScreenSpaceFluidPass.ts +789 -789
  142. package/WaterFlow/ShallowWaterSurface.d.ts +45 -45
  143. package/WaterFlow/ShallowWaterSurface.js +438 -438
  144. package/WaterFlow/ShallowWaterSurface.ts +510 -510
  145. package/WaterFlow/WaterFlow.d.ts +87 -87
  146. package/WaterFlow/WaterFlow.js +171 -171
  147. package/WaterFlow/WaterFlow.ts +219 -219
  148. package/WaterFlow/types.d.ts +161 -161
  149. package/WaterFlow/types.js +1 -1
  150. package/WaterFlow/types.ts +189 -189
  151. package/WaterFlow/waterFlowPass.d.ts +3 -3
  152. package/WaterFlow/waterFlowPass.js +20 -20
  153. package/WaterFlow/waterFlowPass.ts +40 -40
  154. package/collisionOBB.d.ts +42 -42
  155. package/collisionOBB.js +112 -112
  156. package/collisionOBB.ts +108 -108
  157. package/declare.d.ts +25 -25
  158. package/index.d.ts +1 -1
  159. package/index.js +1 -1
  160. package/instanced/InstancedBatch.d.ts +57 -57
  161. package/instanced/InstancedBatch.js +348 -348
  162. package/instanced/InstancedBatch.ts +406 -406
  163. package/instanced/InstancedChild.d.ts +174 -174
  164. package/instanced/InstancedChild.js +264 -264
  165. package/instanced/InstancedChild.ts +327 -327
  166. package/instanced/InstancedGroup.d.ts +43 -43
  167. package/instanced/InstancedGroup.js +126 -126
  168. package/instanced/InstancedGroup.ts +137 -137
  169. package/instanced/InstancedMeshBase.d.ts +38 -38
  170. package/instanced/InstancedMeshBase.js +282 -282
  171. package/instanced/InstancedTemplate.d.ts +46 -46
  172. package/instanced/InstancedTemplate.js +125 -125
  173. package/keyControls.d.ts +29 -30
  174. package/keyControls.js +101 -101
  175. package/lensflare/LensFlare.d.ts +39 -39
  176. package/lensflare/LensFlare.js +284 -284
  177. package/package.json +6 -1
  178. package/pass/bloom_pass.d.ts +2 -2
  179. package/pass/bloom_pass.js +174 -174
  180. package/pass/cover_pass.d.ts +2 -2
  181. package/pass/cover_pass.js +108 -108
  182. package/pass/debugDepthState.d.ts +20 -20
  183. package/pass/debugDepthState.js +9 -9
  184. package/pass/debugDepthState.ts +22 -22
  185. package/pass/depthTestBias.d.ts +12 -12
  186. package/pass/depthTestBias.js +12 -12
  187. package/pass/depthTestBias.ts +12 -12
  188. package/pass/effectUserData.d.ts +27 -27
  189. package/pass/effectUserData.js +1 -1
  190. package/pass/effectUserData.ts +46 -46
  191. package/pass/frosted_glass_pass.d.ts +2 -2
  192. package/pass/frosted_glass_pass.js +150 -150
  193. package/pass/fsQuad.d.ts +9 -9
  194. package/pass/fsQuad.js +28 -28
  195. package/pass/glow_pass.d.ts +2 -2
  196. package/pass/glow_pass.js +350 -350
  197. package/pass/screen_bloom_pass.d.ts +11 -11
  198. package/pass/screen_bloom_pass.js +136 -136
  199. package/pass/ssao_pass.d.ts +88 -88
  200. package/pass/ssao_pass.js +799 -799
  201. package/pass/ssao_pass.ts +918 -918
  202. package/pass/stroke_pass.d.ts +2 -2
  203. package/pass/stroke_pass.js +267 -267
  204. package/shaders/FXAAShaderMaterial.d.ts +3 -3
  205. package/shaders/FXAAShaderMaterial.js +20 -20
  206. package/shaders/baseDepthVisShader.d.ts +11 -11
  207. package/shaders/baseDepthVisShader.js +36 -36
  208. package/shaders/baseDepthVisShader.ts +36 -36
  209. package/shaders/baseTextureToRenderShader.d.ts +2 -2
  210. package/shaders/baseTextureToRenderShader.js +19 -19
  211. package/shaders/copyShader.d.ts +3 -3
  212. package/shaders/copyShader.js +13 -13
  213. package/shaders/debugDepthCompareShader.d.ts +14 -14
  214. package/shaders/debugDepthCompareShader.js +49 -49
  215. package/shaders/debugDepthCompareShader.ts +50 -50
  216. package/shaders/debugDepthJudgeShader.d.ts +18 -18
  217. package/shaders/debugDepthJudgeShader.js +52 -52
  218. package/shaders/debugDepthJudgeShader.ts +54 -54
  219. package/shaders/debugExcludedShader.d.ts +13 -13
  220. package/shaders/debugExcludedShader.js +46 -46
  221. package/shaders/debugExcludedShader.ts +48 -48
  222. package/spriteTextBg.d.ts +1 -1
  223. package/spriteTextBg.js +20 -20
  224. package/spriteTextBg.ts +20 -20
  225. package/threeLoader.d.ts +35 -35
  226. package/threeLoader.js +518 -518
  227. package/threeUtils.d.ts +71 -53
  228. package/threeUtils.js +363 -329
  229. package/threeUtils.ts +35 -0
  230. package/types.d.ts +2 -2
  231. package/types.js +6 -6
@@ -991,8 +991,22 @@ export default class MktMesh extends Mesh<BufferGeometry, ShaderMaterial> {
991
991
 
992
992
  // ───────────────────────── 导入 / 导出 ─────────────────────────
993
993
 
994
- /** 导出数据:墙点位 + 墙高 + 是否闭合 + 纹理数组(url + 矩阵) */
995
- exportData(): MktMeshData {
994
+ /**
995
+ * ⭐ 项目名(皇上旨10-08 19:53「导出时图片地址改成 `{项目名称}/xxx.jpg`」)。
996
+ * 落盘时用它顶替 OSS 上传目录前缀(`three-base_upload/panorama/`),导入时据此还原。
997
+ * 消费方(编辑器)用 `setProjectName()` 注入;没注入时退化为「只剥域名」的纯相对形态。
998
+ */
999
+ projectName: string = "";
1000
+
1001
+ /** 注入项目名(导出 json 前调一次即可;导入时无须调——还原靠落盘地址自身的首段) */
1002
+ setProjectName(name: string): void {
1003
+ this.projectName = typeof name === "string" ? name : "";
1004
+ }
1005
+
1006
+ /** 导出数据:墙点位 + 墙高 + 是否闭合 + 纹理数组(url + 矩阵)
1007
+ * @param projName 项目名(可选,优先于 `setProjectName` 注入的那个)——图片地址落成 `{项目名}/xxx.jpg` */
1008
+ exportData(projName?: string): MktMeshData {
1009
+ const pn = typeof projName === "string" && projName ? projName : this.projectName;
996
1010
  return {
997
1011
  wallPoints: this.wallPoints.map((p) => ({ x: p.x, y: p.y, z: p.z })),
998
1012
  wallHeight: this.wallHeight,
@@ -1001,19 +1015,22 @@ export default class MktMesh extends Mesh<BufferGeometry, ShaderMaterial> {
1001
1015
  // 全景序号映射:每个三角面归属的全景全局序号(与 wallPoints 同几何拓扑绑定,随存档走)
1002
1016
  panoFaceMapping: this.panoFaceMapping.slice(),
1003
1017
  textures: this.textures.map((t) => ({
1004
- // ⭐ 10-08 旨:存档里只落**根相对路径**(域名在读 JavaScript 之外也用不上,还锁死环境)。
1018
+ // ⭐ 10-08 旨:存档里只落**相对路径**(域名在读 JavaScript 之外也用不上,还锁死环境);
1019
+ // 同日 18:46 旨「前面不要有 /」⇒ ⛔ 无前导 /;19:53 旨「改成 {项目名称}/xxx.jpg」
1020
+ // ⇒ OSS 上传目录前缀(`three-base_upload/panorama/`)整段顶掉,落成 `{项目名}/x_0.jpg`。
1005
1021
  // `stripAssetHost` 幂等 ⇒ 内存里已经是相对的不会出问题,旧存档的绝对地址也不会反复剥。
1006
- url: stripAssetHost(t.url),
1022
+ url: stripAssetHost(t.url, pn),
1007
1023
  name: t.name ?? "",
1008
1024
  // 2026-09-20:导出 4 瓦片(顺序 [左上, 右上, 左下, 右下]);旧数据无 tiles 时导空数组
1009
- tiles: (t.tiles && t.tiles.length ? t.tiles.map(stripAssetHost) : []) as string[],
1025
+ tiles: (t.tiles && t.tiles.length ? t.tiles.map((u) => stripAssetHost(u, pn)) : []) as string[],
1010
1026
  matrix: t.matrix.toArray(),
1011
1027
  })),
1012
1028
  };
1013
1029
  }
1014
1030
 
1015
- /** 导入数据:重建墙体几何与纹理列表,并激活第一个纹理 */
1016
- importData(data: MktMeshData): void {
1031
+ /** 导入数据:重建墙体几何与纹理列表,并激活第一个纹理
1032
+ * @param projName 项目名(可选)——用于把落盘的 `{项目名}/x_0.jpg` 还原回真身OSS 地址 */
1033
+ importData(data: MktMeshData, projName?: string): void {
1017
1034
  this.setWallPoints(data.wallPoints ?? [], {
1018
1035
  closed: data.wallClosed,
1019
1036
  height: data.wallHeight,
@@ -1023,16 +1040,20 @@ export default class MktMesh extends Mesh<BufferGeometry, ShaderMaterial> {
1023
1040
  this.setWallSide(data.wallSide ?? "double");
1024
1041
  this.setTextures(
1025
1042
  (data.textures ?? []).map((t) => {
1026
- // ⭐ 10-08 旨的成对另一半:存档落的是根相对路径 ⇒ 进内存前在这里**唯一一处**补回域名,
1043
+ // ⭐ 10-08 旨的成对另一半:存档落的是相对路径 ⇒ 进内存前在这里**唯一一处**补回域名,
1027
1044
  // 下游(拼合器 / 预览 / UI `<img>`)拿到的仍是绝对地址 ⇒ 它们一行都不用改。
1028
- // `absAssetUrl` 幂等 ⇒ 旧存档里已是绝对地址的(= 升级前存的)不会被拼成 `https://host/https://host/...`
1029
- const urlAbs = absAssetUrl(t.url as string);
1045
+ // · `absAssetUrl` 幂等 + **同时认旧存档的根相对形态** ⇒ 上午发布前存的那批
1046
+ // (`/three-base_upload/…`)不必重存也能正常加载,不会被拼成 `https://host/https://host/…`
1047
+ // · 19:53 旨后还要把 `{项目名}/x_0.jpg` **还原**成真身 OSS 地址(顶掉的上传目录要补回来),
1048
+ // 否则 json 里的地址指不回原图(图片裂)。`pn` 取入参、回落 `setProjectName` 注入的那个。
1049
+ const pn = typeof projName === "string" && projName ? projName : this.projectName;
1050
+ const urlAbs = absAssetUrl(t.url as string, pn);
1030
1051
  return {
1031
1052
  url: urlAbs,
1032
1053
  name: t.name ?? "",
1033
1054
  // 2026-09-20:导入瓦片;缺省回退 [url](旧存档整图占 1 格)——10-06 晚旨「只支持 32 张(横 8 × 竖 4)」后
1034
1055
  // 该点走拼合器:整图缩在 1/32 格 + 其余 31 格涂灰,数据不全一眼可见(重传 32 片切片即修复)
1035
- tiles: t.tiles && t.tiles.length ? t.tiles.map(absAssetUrl) : [urlAbs],
1056
+ tiles: t.tiles && t.tiles.length ? t.tiles.map((u) => absAssetUrl(u, pn)) : [urlAbs],
1036
1057
  matrix: new Matrix4().fromArray(t.matrix),
1037
1058
  };
1038
1059
  })
@@ -1,35 +1,59 @@
1
- /**
2
- * 全景图片地址的「相对 ⇄ 绝对」互转 —— **零 import 纯函数**(护栏可用 esbuild 直接转译真跑)。
3
- *
4
- * ⭐ 皇上旨 2026-10-08「json 里面的图片的地址,把域名去掉,只保留相对的根路径」:
5
- * 存档 JSON 里只落**根相对路径**(`/three-base_upload/panorama/xxx_0.jpg`),换来两件事:
6
- * ① 换域名 / 换环境部署时,已有存档与下载的 zip 不用改一字就能用;
7
- * ② 导出的 json 里不再写死机器名,人眼可读、可 diff。
8
- *
9
- * ⛔ 代价必须在同一处偿还:落盘时剥了域名,**加载前就必须补回来**。
10
- * 补的动作由 `MktMesh.importData()` 一处统一做(⛔ 不许在拼合器 / 预览 / UI 各补一份 ——
11
- * 那就是老坑「旁路即失控」的重演)。同理,剥的动作只在 `MktMesh.exportData()` 一处。
12
- *
13
- * 🔒 两个函数必须满足两条硬性质(护栏 BR 组逐条真跑):
14
- * - **幂等**:`strip(strip(x)) === strip(x)`、`abs(abs(x)) === abs(x)`
15
- * ⇒ 旧存档本来存的绝对地址绝不会被反复剥/补成一串 `https://host/https://host/...`
16
- * - **互逆**:`strip(abs(rel)) === rel`(相对 → 绝对 → 相对,回到原样)
17
- *
18
- * ⚠️ 本模块刻意**不 import 任何东西**(连 three 都不):它是地址字符串规则,不是渲染代码,
19
- * 保持零依赖才能被测试单独转译真跑。
20
- */
21
- /** 资源公网域名(⛔ 与 `panoramaUpload.OSS_PUBLIC_HOST` 必须同值,护栏 BR ② 钉着两边一致) */
22
- export declare const MKT_ASSET_HOST = "https://www.3dkeshihua.com";
23
- /**
24
- * 剥掉本站域名 ⇒ 根相对路径。
25
- * - 已是根相对 / blob / data / 别的域名 ⇒ **原样返回**(幂等,也保证旧存档安全)
26
- * - `https://www.3dkeshihua.com/a/b.jpg` ⇒ `/a/b.jpg`
27
- * - host 后面直接跟 `?` `#` 也认(OSS 地址可能带参),或直接到尾 ⇒ `/`
28
- */
29
- export declare function stripAssetHost(url: string): string;
30
- /**
31
- * 补回域名 ⇒ 绝对地址(加载前的唯一落点)。
32
- * - 已是绝对 / blob / data ⇒ **原样返回**(幂等 ⇒ 旧存档进 `importData` 不会被二次拼接)
33
- * - `/a/b.jpg` ⇒ `https://www.3dkeshihua.com/a/b.jpg`
34
- */
35
- export declare function absAssetUrl(url: string): string;
1
+ /**
2
+ * 全景图片地址的「相对 ⇄ 绝对」互转 —— **零 import 纯函数**(护栏可用 esbuild 直接转译真跑)。
3
+ *
4
+ * ⭐ 皇上旨 2026-10-08「json 里面的图片的地址,把域名去掉,只保留相对的根路径」;
5
+ * 同日 18:46 补充「图片路径要相对路径,**前面不要有 `/`**」⇒ 落盘形态最终定为
6
+ * **纯相对路径**(`three-base_upload/panorama/xxx_0.jpg`,⛔ 无前导 `/`),换来两件事:
7
+ * ① 换域名 / 换环境部署时,已有存档与下载的 zip 不用改一字就能用;
8
+ * ② 导出的 json 里不再写死机器名,人眼可读、可 diff。
9
+ * 为什么连前导 `/` 都不留:站点部署在子路径 `/three-base/` 下,相对路径随 `<base href>`
10
+ * 一起解析,换部署位置仍指到同一张图;根相对 `/xxx` 会被钉死在域名根,放到子目录就 404。
11
+ *
12
+ * ⛔ 代价必须在同一处偿还:落盘时剥了域名,**加载前就必须补回来**。
13
+ * 补的动作由 `MktMesh.importData()` 一处统一做(⛔ 不许在拼合器 / 预览 / UI 各补一份 ——
14
+ * 那就是老坑「旁路即失控」的重演)。同理,剥的动作只在 `MktMesh.exportData()` 一处。
15
+ *
16
+ * 🔒 两个函数必须满足两条硬性质(护栏 BR 组逐条真跑):
17
+ * - **幂等**:`strip(strip(x)) === strip(x)`、`abs(abs(x)) === abs(x)`
18
+ * ⇒ 旧存档本来存的绝对地址绝不会被反复剥/补成一串 `https://host/https://host/...`
19
+ * - **互逆**:`strip(abs(rel)) === rel`(相对 → 绝对 → 相对,回到原样)
20
+ * ⚠️ **向后兼容**:`absAssetUrl` 同时认「纯相对」与「旧存档的根相对」两种形态
21
+ * (`/a/b.jpg` 也补成绝对)⇒ 上午发布前存下的那些存档**不必重存**也能正常加载。
22
+ *
23
+ * ⚠️ 本模块刻意**不 import 任何东西**(连 three 都不):它是地址字符串规则,不是渲染代码,
24
+ * 保持零依赖才能被测试单独转译真跑。
25
+ */
26
+ /** 资源公网域名(⛔ 与 `panoramaUpload.OSS_PUBLIC_HOST` 必须同值,护栏 BR ② 钉着两边一致) */
27
+ export declare const MKT_ASSET_HOST = "https://www.3dkeshihua.com";
28
+ /**
29
+ * 剥掉本站域名 ⇒ **纯相对路径**(⭐ 皇上旨10-08 18:46「图片路径要相对路径,前面不要有 "/"」)。
30
+ * @param projName 项目名。给了 ⇒ 落盘成 `{项目名}/文件名.jpg`(19:53 旨);没给 ⇒ 落成 `文件名.jpg`。
31
+ * - 已是相对 / 根相对 / blob / data / 别的域名 ⇒ **原样返回**(幂等,也保证旧存档安全)
32
+ * - `https://www.3dkeshihua.com/a/b.jpg` ⇒ `a/b.jpg`(⛔ 不带前导 `/`)
33
+ * - `https://www.3dkeshihua.com/three-base_upload/panorama/x_0.jpg` ⇒ `x_0.jpg` 或 `{proj}/x_0.jpg`
34
+ * - host 后面直接跟 `?` `#` 也认(OSS 地址可能带参),或直接到尾 ⇒ `""`(空串:无路径可留)
35
+ *
36
+ * ⚠️ 为何要「不带 `/`」:站点部署在子路径 `/three-base/` 下,相对路径能随
37
+ * `<base href>` 一起解析,换部署位置仍指到同一张图;而根相对 `/xxx` 会被钉死在域名根,
38
+ * 放到子目录就404。
39
+ * ⚠️ 为何要顶掉上传目录前缀:落盘地址是给「换环境部署 / 交给别人」用的,
40
+ * `three-base_upload/panorama` 是本项目的 OSS 内部目录,跟内容无关;顶成项目名后
41
+ * 「一个项目一套目录」的语义直接体现在地址里。
42
+ */
43
+ export declare function stripAssetHost(url: string, projName?: string): string;
44
+ /**
45
+ * 补回域名 ⇒ 绝对地址(加载前的唯一落点)。
46
+ * - 已是绝对 / blob / data ⇒ **原样返回**(幂等⇒ 旧存档进 `importData` 不会被二次拼接)
47
+ * - `a/b.jpg` ⇒ `https://www.3dkeshihua.com/a/b.jpg`
48
+ * - `/a/b.jpg`(旧存档的根相对形态)⇒ 同样认,补成绝对(**旧存档不必重存也能用**)
49
+ * - `{项目名}/x_0.jpg`(19:53 旨落盘形态)⇒ 还原成真身
50
+ * `https://host/three-base_upload/panorama/x_0.jpg`
51
+ * ⚠️ 落盘时顶掉了上传目录前缀,这里必须还原,否则 json 里的地址永远指不回原图。
52
+ *
53
+ * ⛔ 认错的后果(所以判据要严):把「项目名段」误当成真目录,地址会指向**不存在的图**(图片裂开);
54
+ * 漏认则地址多一段目录名,同样指不到图。两种都只影响显示、不会崩,所以宁可漏认不可误认 ——
55
+ * 判据 =「首段命中已知站点目录 ⇒ 一律不还原」+「首段等于传入项目名 ⇒ 才还原」。
56
+ *
57
+ * @param projName 项目名。**传了就以它为准**(最可靠);没传则只认「首段是已知站点目录之外的名字」这一条。
58
+ */
59
+ export declare function absAssetUrl(url: string, projName?: string): string;
@@ -1,69 +1,165 @@
1
- /**
2
- * 全景图片地址的「相对 ⇄ 绝对」互转 —— **零 import 纯函数**(护栏可用 esbuild 直接转译真跑)。
3
- *
4
- * ⭐ 皇上旨 2026-10-08「json 里面的图片的地址,把域名去掉,只保留相对的根路径」:
5
- * 存档 JSON 里只落**根相对路径**(`/three-base_upload/panorama/xxx_0.jpg`),换来两件事:
6
- * ① 换域名 / 换环境部署时,已有存档与下载的 zip 不用改一字就能用;
7
- * ② 导出的 json 里不再写死机器名,人眼可读、可 diff。
8
- *
9
- * ⛔ 代价必须在同一处偿还:落盘时剥了域名,**加载前就必须补回来**。
10
- * 补的动作由 `MktMesh.importData()` 一处统一做(⛔ 不许在拼合器 / 预览 / UI 各补一份 ——
11
- * 那就是老坑「旁路即失控」的重演)。同理,剥的动作只在 `MktMesh.exportData()` 一处。
12
- *
13
- * 🔒 两个函数必须满足两条硬性质(护栏 BR 组逐条真跑):
14
- * - **幂等**:`strip(strip(x)) === strip(x)`、`abs(abs(x)) === abs(x)`
15
- * ⇒ 旧存档本来存的绝对地址绝不会被反复剥/补成一串 `https://host/https://host/...`
16
- * - **互逆**:`strip(abs(rel)) === rel`(相对 → 绝对 → 相对,回到原样)
17
- *
18
- * ⚠️ 本模块刻意**不 import 任何东西**(连 three 都不):它是地址字符串规则,不是渲染代码,
19
- * 保持零依赖才能被测试单独转译真跑。
20
- */
21
- /** 资源公网域名(⛔ 与 `panoramaUpload.OSS_PUBLIC_HOST` 必须同值,护栏 BR ② 钉着两边一致) */
22
- export const MKT_ASSET_HOST = "https://www.3dkeshihua.com";
23
- /** http 明文版 host:历史数据里可能存过这个形态,一并认,避免出现「剥不掉」的漏网地址 */
24
- const MKT_ASSET_HOST_HTTP = "http://www.3dkeshihua.com";
25
- /**
26
- * 这些前缀的地址**不参与**剥/补 —— 它们压根不是远端资源:
27
- * `blob:` 是本地内存里的 File/ObjectURL,`data:` 是内联字节,补域名只会把它们弄坏。
28
- */
29
- function isLocalUrl(url) {
30
- return url.startsWith("blob:") || url.startsWith("data:");
31
- }
32
- /** 是不是「根相对路径」(`//host/x` 是协议相对 = 绝对,不算) */
33
- function isRootRelative(url) {
34
- return url.startsWith("/") && !url.startsWith("//");
35
- }
36
- /**
37
- * 剥掉本站域名 ⇒ 根相对路径。
38
- * - 已是根相对 / blob / data / 别的域名 ⇒ **原样返回**(幂等,也保证旧存档安全)
39
- * - `https://www.3dkeshihua.com/a/b.jpg` ⇒ `/a/b.jpg`
40
- * - host 后面直接跟 `?` `#` 也认(OSS 地址可能带参),或直接到尾 ⇒ `/`
41
- */
42
- export function stripAssetHost(url) {
43
- if (typeof url !== "string" || url === "")
44
- return url;
45
- if (isLocalUrl(url) || isRootRelative(url))
46
- return url;
47
- for (const host of [MKT_ASSET_HOST, MKT_ASSET_HOST_HTTP]) {
48
- if (!url.startsWith(host))
49
- continue;
50
- const rest = url.slice(host.length);
51
- // host 是前缀但后面不是 path/query/fragment 的边界 ⇒ 不是本站资源(例如 `...3dkeshihua.com.evil.com`)
52
- if (rest !== "" && !/^[/?#]/.test(rest))
53
- return url;
54
- return rest === "" ? "/" : rest;
55
- }
56
- return url;
57
- }
58
- /**
59
- * 补回域名 ⇒ 绝对地址(加载前的唯一落点)。
60
- * - 已是绝对 / blob / data ⇒ **原样返回**(幂等 ⇒ 旧存档进 `importData` 不会被二次拼接)
61
- * - `/a/b.jpg` ⇒ `https://www.3dkeshihua.com/a/b.jpg`
62
- */
63
- export function absAssetUrl(url) {
64
- if (typeof url !== "string" || url === "")
65
- return url;
66
- if (isLocalUrl(url) || !isRootRelative(url))
67
- return url;
68
- return `${MKT_ASSET_HOST}${url}`;
69
- }
1
+ /**
2
+ * 全景图片地址的「相对 ⇄ 绝对」互转 —— **零 import 纯函数**(护栏可用 esbuild 直接转译真跑)。
3
+ *
4
+ * ⭐ 皇上旨 2026-10-08「json 里面的图片的地址,把域名去掉,只保留相对的根路径」;
5
+ * 同日 18:46 补充「图片路径要相对路径,**前面不要有 `/`**」⇒ 落盘形态最终定为
6
+ * **纯相对路径**(`three-base_upload/panorama/xxx_0.jpg`,⛔ 无前导 `/`),换来两件事:
7
+ * ① 换域名 / 换环境部署时,已有存档与下载的 zip 不用改一字就能用;
8
+ * ② 导出的 json 里不再写死机器名,人眼可读、可 diff。
9
+ * 为什么连前导 `/` 都不留:站点部署在子路径 `/three-base/` 下,相对路径随 `<base href>`
10
+ * 一起解析,换部署位置仍指到同一张图;根相对 `/xxx` 会被钉死在域名根,放到子目录就 404。
11
+ *
12
+ * ⛔ 代价必须在同一处偿还:落盘时剥了域名,**加载前就必须补回来**。
13
+ * 补的动作由 `MktMesh.importData()` 一处统一做(⛔ 不许在拼合器 / 预览 / UI 各补一份 ——
14
+ * 那就是老坑「旁路即失控」的重演)。同理,剥的动作只在 `MktMesh.exportData()` 一处。
15
+ *
16
+ * 🔒 两个函数必须满足两条硬性质(护栏 BR 组逐条真跑):
17
+ * - **幂等**:`strip(strip(x)) === strip(x)`、`abs(abs(x)) === abs(x)`
18
+ * ⇒ 旧存档本来存的绝对地址绝不会被反复剥/补成一串 `https://host/https://host/...`
19
+ * - **互逆**:`strip(abs(rel)) === rel`(相对 → 绝对 → 相对,回到原样)
20
+ * ⚠️ **向后兼容**:`absAssetUrl` 同时认「纯相对」与「旧存档的根相对」两种形态
21
+ * (`/a/b.jpg` 也补成绝对)⇒ 上午发布前存下的那些存档**不必重存**也能正常加载。
22
+ *
23
+ * ⚠️ 本模块刻意**不 import 任何东西**(连 three 都不):它是地址字符串规则,不是渲染代码,
24
+ * 保持零依赖才能被测试单独转译真跑。
25
+ */
26
+ /** 资源公网域名(⛔ 与 `panoramaUpload.OSS_PUBLIC_HOST` 必须同值,护栏 BR ② 钉着两边一致) */
27
+ export const MKT_ASSET_HOST = "https://www.3dkeshihua.com";
28
+ /** http 明文版 host:历史数据里可能存过这个形态,一并认,避免出现「剥不掉」的漏网地址 */
29
+ const MKT_ASSET_HOST_HTTP = "http://www.3dkeshihua.com";
30
+ /**
31
+ * 这些前缀的地址**不参与**剥/补 —— 它们压根不是远端资源:
32
+ * `blob:` 是本地内存里的 File/ObjectURL,`data:` 是内联字节,补域名只会把它们弄坏。
33
+ */
34
+ function isLocalUrl(url) {
35
+ return url.startsWith("blob:") || url.startsWith("data:");
36
+ }
37
+ /** 是不是「路径式地址」(相对 `three-base_upload/xxx` 或根相对 `/three-base_upload/xxx`;`//host/x` 是协议相对 = 绝对,不算) */
38
+ function isPathLike(url) {
39
+ return !url.startsWith("//") && (url.startsWith("/") || !/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url));
40
+ }
41
+ /**
42
+ * OSS 上传目录前缀(`three-base_upload/panorama/…`)⇒ 落盘时整段丢掉,只留**文件名**。
43
+ * ⭐ 皇上旨10-08 19:53「导出时图片地址改成 `{项目名称}/xxx.jpg`」⇒ 这一段要被**项目名**顶替。
44
+ * 取不到项目名时(库内直接调 `exportData()` 而没传)**仍按老口径剥成纯相对**(不退回带`/` 的形态)。
45
+ */
46
+ /** OSS 上传目录(`three-base_upload/panorama/`)——⛔ **不带尾斜杠**(拼接时自己补 `/`,否则会拼出双斜杠) */
47
+ const UPLOAD_DIR_PREFIX = "three-base_upload";
48
+ /** 上传目录的**完整**两级路径(还原时用) */
49
+ const UPLOAD_FULL_PREFIX = `${UPLOAD_DIR_PREFIX}/panorama`;
50
+ /**
51
+ * 本桶上「不是资源目录」的一级目录名—— 命中它们就说明是**站点自身路径**,不是项目名。
52
+ *(`three-base/` = 站点根,`three-base_upload/` = 资源上传根;两者都是固定目录,与项目名无关。)
53
+ */
54
+ const KNOWN_TOP_DIRS = [UPLOAD_DIR_PREFIX, "three-base"];
55
+ /** 首段看起来像「项目名」(= 不是已知站点目录)—— `strip` 与 `abs` 两侧**必须用同一把尺**,否则闭环对不上 */
56
+ function segs0IsProjectDir(seg0) {
57
+ return seg0.length > 0 && !KNOWN_TOP_DIRS.includes(seg0);
58
+ }
59
+ /**
60
+ * 文件名安全化(与 `projectZipLayout.safeFileSegment` **逐字同口径**,两处必须同步 ——
61
+ * 一个存 json 里的地址、一个存zip 里的目录名,规则不一致会让「按 json 里的地址去 zip 找图」扑空)。
62
+ * Windows 与URL 都待见的字符 → 下划线;空名回落。
63
+ */
64
+ function safeSeg(name) {
65
+ const s = (name || "").replace(/[\\/:*?"<>|]+/g, "_").trim();
66
+ return s.length > 0 ? s : "";
67
+ }
68
+ /**
69
+ * 剥掉本站域名 ⇒ **纯相对路径**(⭐ 皇上旨10-08 18:46「图片路径要相对路径,前面不要有 "/"」)。
70
+ * @param projName 项目名。给了 ⇒ 落盘成 `{项目名}/文件名.jpg`(19:53 旨);没给 ⇒ 落成 `文件名.jpg`。
71
+ * - 已是相对 / 根相对 / blob / data / 别的域名 ⇒ **原样返回**(幂等,也保证旧存档安全)
72
+ * - `https://www.3dkeshihua.com/a/b.jpg` ⇒ `a/b.jpg`(⛔ 不带前导 `/`)
73
+ * - `https://www.3dkeshihua.com/three-base_upload/panorama/x_0.jpg` ⇒ `x_0.jpg` 或 `{proj}/x_0.jpg`
74
+ * - host 后面直接跟 `?` `#` 也认(OSS 地址可能带参),或直接到尾 ⇒ `""`(空串:无路径可留)
75
+ *
76
+ * ⚠️ 为何要「不带 `/`」:站点部署在子路径 `/three-base/` 下,相对路径能随
77
+ * `<base href>` 一起解析,换部署位置仍指到同一张图;而根相对 `/xxx` 会被钉死在域名根,
78
+ * 放到子目录就404。
79
+ * ⚠️ 为何要顶掉上传目录前缀:落盘地址是给「换环境部署 / 交给别人」用的,
80
+ * `three-base_upload/panorama` 是本项目的 OSS 内部目录,跟内容无关;顶成项目名后
81
+ * 「一个项目一套目录」的语义直接体现在地址里。
82
+ */
83
+ export function stripAssetHost(url, projName) {
84
+ if (typeof url !== "string" || url === "")
85
+ return url;
86
+ if (isLocalUrl(url) || isPathLike(url))
87
+ return url;
88
+ for (const host of [MKT_ASSET_HOST, MKT_ASSET_HOST_HTTP]) {
89
+ if (!url.startsWith(host))
90
+ continue;
91
+ const rest = url.slice(host.length);
92
+ // host 是前缀但后面不是 path/query/fragment 的边界 ⇒ 不是本站资源(例如`...3dkeshihua.com.evil.com`)
93
+ if (rest !== "" && !/^[/?#]/.test(rest))
94
+ return url;
95
+ // 去掉前导 `/`:得到真正的相对路径(`/a/b.jpg` → `a/b.jpg`;`/` → `""`)
96
+ let path = rest.replace(/^\/+/, "");
97
+ // 上传目录前缀整段丢掉,换成**项目名**(皇上 19:53 旨);项目名缺失时退回「无项目名」的裸文件名。
98
+ // ⭐ 无论哪种形态,产出的地址都必须能被 `absAssetUrl` **原样还原**回真身 OSS 地址
99
+ // (这是「运行期地址不动、只在导出 json 里临时改」的前提 —— 顶替必须是可逆的)。
100
+ if (path === UPLOAD_DIR_PREFIX || path.startsWith(`${UPLOAD_DIR_PREFIX}/`)) {
101
+ const tail = path.slice(UPLOAD_DIR_PREFIX.length + 1); // 越过 `three-base_upload/` ⇒ `panorama/x_0.jpg`
102
+ const cut = tail.search(/[/?#]/); // 截到第一个分隔符(`/` `?` `#`)
103
+ // ⚠️ slice(cut) 会把那个分隔符一起带上(`panorama/x.jpg` → `/x.jpg`)⇒ 要 slice(cut+1)
104
+ const file = cut < 0 ? tail : tail.slice(cut + 1); // 文件名(含后面的 ?/#)
105
+ const dir = safeSeg(projName ?? "");
106
+ return dir ? `${dir}/${file}` : file;
107
+ }
108
+ // ⭐ 幂等对称:`{项目名}/x.jpg` 这种**已顶替过**的形态(还原回绝对后再剥)要认出来,
109
+ // 否则项目名段会被原样留着、形态跟首轮落盘的不一致 ⇒ 导出→导入→导出闭环对不上。
110
+ // 判据 = 首段既不是已知站点目录、也不是上传目录(与 `absAssetUrl` 的还原判据镜像)。
111
+ const seg0 = path.split("/")[0];
112
+ if (segs0IsProjectDir(seg0)) {
113
+ const tail = path.slice(seg0.length + 1); // 越过 `{项目名}/`
114
+ const dir = safeSeg(projName ?? "");
115
+ // 传了项目名且首段与它一致 ⇒ 剥掉首段还原成裸文件名(无项目名时的落盘形态)
116
+ if (dir && seg0 === dir)
117
+ return tail;
118
+ // 没传项目名 ⇒ 首段无从确认是不是项目名,⛔ 原样留着(宁可多一段也不猜错)
119
+ return path;
120
+ }
121
+ return path;
122
+ }
123
+ return url;
124
+ }
125
+ /**
126
+ * 补回域名 ⇒ 绝对地址(加载前的唯一落点)。
127
+ * - 已是绝对 / blob / data ⇒ **原样返回**(幂等⇒ 旧存档进 `importData` 不会被二次拼接)
128
+ * - `a/b.jpg` ⇒ `https://www.3dkeshihua.com/a/b.jpg`
129
+ * - `/a/b.jpg`(旧存档的根相对形态)⇒ 同样认,补成绝对(**旧存档不必重存也能用**)
130
+ * - `{项目名}/x_0.jpg`(19:53 旨落盘形态)⇒ 还原成真身
131
+ * `https://host/three-base_upload/panorama/x_0.jpg`
132
+ * ⚠️ 落盘时顶掉了上传目录前缀,这里必须还原,否则 json 里的地址永远指不回原图。
133
+ *
134
+ * ⛔ 认错的后果(所以判据要严):把「项目名段」误当成真目录,地址会指向**不存在的图**(图片裂开);
135
+ * 漏认则地址多一段目录名,同样指不到图。两种都只影响显示、不会崩,所以宁可漏认不可误认 ——
136
+ * 判据 =「首段命中已知站点目录 ⇒ 一律不还原」+「首段等于传入项目名 ⇒ 才还原」。
137
+ *
138
+ * @param projName 项目名。**传了就以它为准**(最可靠);没传则只认「首段是已知站点目录之外的名字」这一条。
139
+ */
140
+ export function absAssetUrl(url, projName) {
141
+ if (typeof url !== "string" || url === "")
142
+ return url;
143
+ if (isLocalUrl(url) || !isPathLike(url))
144
+ return url;
145
+ const path = url.replace(/^\/+/, "");
146
+ // ⛔ 空路径(`/` 或 `/` 去掉斜杠后)不是文件名,别当裸文件名补上传目录(实测会补出 `host/three-base_upload/panorama/`)
147
+ if (path === "")
148
+ return `${MKT_ASSET_HOST}/`;
149
+ const segs = path.split("/");
150
+ // ⭐ 情形①:**裸文件名**(`x_26.jpg`,无目录)—— 这是 `stripAssetHost` 无项目名时的落盘形态,
151
+ // 它必然来自上传目录 ⇒ 直接还原回 `three-base_upload/panorama/`。
152
+ // ⛔ 漏了这一条就会补成 `https://host/x_26.jpg`(丢了上传目录)⇒ 线上取图 404(皇上 10-09 实测撞到)。
153
+ if (segs.length === 1)
154
+ return `${MKT_ASSET_HOST}/${UPLOAD_FULL_PREFIX}/${segs[0]}`;
155
+ // 情形②:`{项目名}/文件名`(两段、首段不是已知站点目录)⇒ 同样还原回上传目录。
156
+ // 判据与 `strip` 侧镜像,两边用同一把尺(`segs0IsProjectDir`)才能保证「顶替可逆」。
157
+ if (segs.length === 2 && segs0IsProjectDir(segs[0])) {
158
+ const dir = safeSeg(projName ?? "");
159
+ // 传了项目名就严格比它(最可靠);没传才放宽到「非已知目录即可认」
160
+ if (!dir || segs[0] === dir)
161
+ return `${MKT_ASSET_HOST}/${UPLOAD_FULL_PREFIX}/${segs[1]}`;
162
+ }
163
+ // 情形③:其余形态(`three-base/model/a.glb`、已是 `three-base_upload/…` 的)⇒ 原样补域名,不还原。
164
+ return `${MKT_ASSET_HOST}/${path}`;
165
+ }