@realsee/dnalogel 4.0.0-webgpu.3 → 4.0.0-webgpu.4

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 (147) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/floorplan.js +1 -1
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.js +270 -35
  5. package/dist/index.js.map +1 -0
  6. package/dist/internal/{BasePlugin-CT5K8m36.js → BasePlugin-DC5m72La.js} +3 -3
  7. package/dist/internal/{BasePlugin-CT5K8m36.js.map → BasePlugin-DC5m72La.js.map} +1 -1
  8. package/dist/internal/BasePluginWithData-D_0W46_q.js +7 -0
  9. package/dist/internal/{BasePluginWithData-9z4tpAT4.js.map → BasePluginWithData-D_0W46_q.js.map} +1 -1
  10. package/dist/internal/{BetterTween-BX0aTvP1.js → BetterTween-DmptqE8m.js} +2 -2
  11. package/dist/internal/{BetterTween-BX0aTvP1.js.map → BetterTween-DmptqE8m.js.map} +1 -1
  12. package/dist/internal/{CSS3DRenderPlugin-ccSpcvwd.js → CSS3DRenderPlugin-CEatgl0m.js} +3 -3
  13. package/dist/internal/CSS3DRenderPlugin-CEatgl0m.js.map +1 -0
  14. package/dist/internal/{Controller-Csut_kcH.js → Controller-D6o4OGWJ.js} +8 -8
  15. package/dist/internal/{Controller-Csut_kcH.js.map → Controller-D6o4OGWJ.js.map} +1 -1
  16. package/dist/internal/{FiveDomEvents-3H9NvDOz.js → FiveDomEvents-BUBLFzti.js} +2 -2
  17. package/dist/internal/{FiveDomEvents-3H9NvDOz.js.map → FiveDomEvents-BUBLFzti.js.map} +1 -1
  18. package/dist/internal/FivePuppet-C6QmVY70.js +67 -0
  19. package/dist/internal/FivePuppet-C6QmVY70.js.map +1 -0
  20. package/dist/internal/{PointHelper-D565h9b_.js → PointHelper-DIhgdjY2.js} +48 -48
  21. package/dist/internal/{PointHelper-D565h9b_.js.map → PointHelper-DIhgdjY2.js.map} +1 -1
  22. package/dist/internal/{Polygon-CBGvYUfJ.js → Polygon-D3xIL1Pl.js} +30 -30
  23. package/dist/internal/{Polygon-CBGvYUfJ.js.map → Polygon-D3xIL1Pl.js.map} +1 -1
  24. package/dist/internal/{Prism-Dm5ESkgg.js → Prism-CJlyAEAU.js} +13 -13
  25. package/dist/internal/{Prism-Dm5ESkgg.js.map → Prism-CJlyAEAU.js.map} +1 -1
  26. package/dist/internal/{Rectangle-D-zkDycu.js → Rectangle-BpL9lNKU.js} +118 -129
  27. package/dist/internal/Rectangle-BpL9lNKU.js.map +1 -0
  28. package/dist/internal/{Work-DF8j5GnL.js → Work-BE4AgdwH.js} +9 -9
  29. package/dist/internal/{Work-DF8j5GnL.js.map → Work-BE4AgdwH.js.map} +1 -1
  30. package/dist/internal/{animationFrame-XGKHIeQK.js → animationFrame-CacKXN8l.js} +14 -3
  31. package/dist/internal/animationFrame-CacKXN8l.js.map +1 -0
  32. package/dist/internal/{area-maker-Bd9l2pIp.js → area-maker-Bnhx4SkH.js} +4 -4
  33. package/dist/internal/{area-maker-Bd9l2pIp.js.map → area-maker-Bnhx4SkH.js.map} +1 -1
  34. package/dist/internal/{boundingBox-DvCor5Hd.js → boundingBox-CIqXgNXW.js} +2 -2
  35. package/dist/internal/{boundingBox-DvCor5Hd.js.map → boundingBox-CIqXgNXW.js.map} +1 -1
  36. package/dist/internal/{camera-movement-CwI7UqUk.js → camera-movement-C1pwfMk_.js} +2 -2
  37. package/dist/internal/camera-movement-C1pwfMk_.js.map +1 -0
  38. package/dist/internal/{changeMode-BVGYCoqu.js → changeMode-D_I2AOjH.js} +2 -2
  39. package/dist/internal/{changeMode-BVGYCoqu.js.map → changeMode-D_I2AOjH.js.map} +1 -1
  40. package/dist/internal/{controller-BWkZT0l1.js → controller-DIDtFrBE.js} +1991 -2050
  41. package/dist/internal/controller-DIDtFrBE.js.map +1 -0
  42. package/dist/internal/{cruise-C3F0eNQ-.js → cruise-B50Tcq66.js} +2 -2
  43. package/dist/internal/{cruise-C3F0eNQ-.js.map → cruise-B50Tcq66.js.map} +1 -1
  44. package/dist/internal/{current-pano-image-DKUWluR-.js → current-pano-image-BCFr6njt.js} +4 -4
  45. package/dist/internal/{current-pano-image-DKUWluR-.js.map → current-pano-image-BCFr6njt.js.map} +1 -1
  46. package/dist/internal/{defaultUrls-CjKkS9k9.js → defaultUrls-CfMtGzqM.js} +14 -3
  47. package/dist/internal/defaultUrls-CfMtGzqM.js.map +1 -0
  48. package/dist/internal/{fire-scene-CczaBz2_.js → fire-scene-BzZGvyh_.js} +9 -4
  49. package/dist/internal/fire-scene-BzZGvyh_.js.map +1 -0
  50. package/dist/internal/{fiveModelLoad-mg-TnpnM.js → fiveModelLoad-BUIBYxzp.js} +2 -2
  51. package/dist/internal/{fiveModelLoad-mg-TnpnM.js.map → fiveModelLoad-BUIBYxzp.js.map} +1 -1
  52. package/dist/internal/{floorplan-KWlIsTvO.js → floorplan-C8BGw87S.js} +5 -5
  53. package/dist/internal/{floorplan-KWlIsTvO.js.map → floorplan-C8BGw87S.js.map} +1 -1
  54. package/dist/internal/{generatePolygonGeometry-B_5JFq8y.js → generatePolygonGeometry-BOnzdCaG.js} +181 -178
  55. package/dist/internal/generatePolygonGeometry-BOnzdCaG.js.map +1 -0
  56. package/dist/internal/{lookObject-wesf8xt6.js → lookObject-DuRab5wf.js} +2 -2
  57. package/dist/internal/{lookObject-wesf8xt6.js.map → lookObject-DuRab5wf.js.map} +1 -1
  58. package/dist/internal/{measure-BX6boAC7.js → measure-B4jFwdQ6.js} +5 -5
  59. package/dist/internal/{measure-BX6boAC7.js.map → measure-B4jFwdQ6.js.map} +1 -1
  60. package/dist/internal/{model-chassis-compass-InVNmOAQ.js → model-chassis-compass-C6NTVMLo.js} +2 -2
  61. package/dist/internal/{model-chassis-compass-InVNmOAQ.js.map → model-chassis-compass-C6NTVMLo.js.map} +1 -1
  62. package/dist/internal/{model-entry-door-guide-wZbyY77a.js → model-entry-door-guide-DnGTLY2s.js} +2 -2
  63. package/dist/internal/{model-entry-door-guide-wZbyY77a.js.map → model-entry-door-guide-DnGTLY2s.js.map} +1 -1
  64. package/dist/internal/{model-maker-uO8xlTuO.js → model-maker-B1mnDdKY.js} +15 -15
  65. package/dist/internal/{model-maker-uO8xlTuO.js.map → model-maker-B1mnDdKY.js.map} +1 -1
  66. package/dist/internal/{model-tv-video-DzXb2JRf.js → model-tv-video-BP-7HoDC.js} +2 -2
  67. package/dist/internal/{model-tv-video-DzXb2JRf.js.map → model-tv-video-BP-7HoDC.js.map} +1 -1
  68. package/dist/internal/{model-view-CBeeMM98.js → model-view-BWUU0-uq.js} +2 -2
  69. package/dist/internal/{model-view-CBeeMM98.js.map → model-view-BWUU0-uq.js.map} +1 -1
  70. package/dist/internal/object3d-helper-CbRRhnLV.js +7 -0
  71. package/dist/internal/{object3d-helper-DDYsVPN6.js.map → object3d-helper-CbRRhnLV.js.map} +1 -1
  72. package/dist/internal/{pano-compass-jSr629BP.js → pano-compass-BRTM0dCc.js} +7 -7
  73. package/dist/internal/{pano-compass-jSr629BP.js.map → pano-compass-BRTM0dCc.js.map} +1 -1
  74. package/dist/internal/{pano-door-label-DKoYIKLa.js → pano-door-label-BLjYGZrr.js} +3 -3
  75. package/dist/internal/{pano-door-label-DKoYIKLa.js.map → pano-door-label-BLjYGZrr.js.map} +1 -1
  76. package/dist/internal/{pano-measure-DW9mdx1O.js → pano-measure-BIgCWkVJ.js} +14 -14
  77. package/dist/internal/{pano-measure-DW9mdx1O.js.map → pano-measure-BIgCWkVJ.js.map} +1 -1
  78. package/dist/internal/{pano-ruler-pro-D7q0Ob21.js → pano-ruler-pro-D9yTbHJz.js} +2 -2
  79. package/dist/internal/{pano-ruler-pro-D7q0Ob21.js.map → pano-ruler-pro-D9yTbHJz.js.map} +1 -1
  80. package/dist/internal/{pano-spatial-tag-D0qn-__S.js → pano-spatial-tag-B7Gxn3BS.js} +3 -3
  81. package/dist/internal/{pano-spatial-tag-D0qn-__S.js.map → pano-spatial-tag-B7Gxn3BS.js.map} +1 -1
  82. package/dist/internal/{pano-tag-BW5MXXws.js → pano-tag-Bchz-jED.js} +2 -2
  83. package/dist/internal/{pano-tag-BW5MXXws.js.map → pano-tag-Bchz-jED.js.map} +1 -1
  84. package/dist/internal/{pano-video-Bmud_CAn.js → pano-video-BufYQMqo.js} +3 -3
  85. package/dist/internal/{pano-video-Bmud_CAn.js.map → pano-video-BufYQMqo.js.map} +1 -1
  86. package/dist/internal/{pipeline-DDqgb1gw.js → pipeline-t_3IMXKB.js} +4 -4
  87. package/dist/internal/{pipeline-DDqgb1gw.js.map → pipeline-t_3IMXKB.js.map} +1 -1
  88. package/dist/internal/{sculpt-BNkLJR6p.js → sculpt-BCK4PMwL.js} +64 -63
  89. package/dist/internal/{sculpt-BNkLJR6p.js.map → sculpt-BCK4PMwL.js.map} +1 -1
  90. package/dist/internal/tagPosition-DA9YguT8.js +176 -0
  91. package/dist/internal/tagPosition-DA9YguT8.js.map +1 -0
  92. package/dist/internal/withResolvers-DVr4bnnk.js +15 -0
  93. package/dist/internal/withResolvers-DVr4bnnk.js.map +1 -0
  94. package/dist/plugins/area-maker.js +1 -1
  95. package/dist/plugins/camera-movement.js +1 -1
  96. package/dist/plugins/cruise.js +2 -2
  97. package/dist/plugins/css3d-render.js +1 -1
  98. package/dist/plugins/current-pano-image.js +1 -1
  99. package/dist/plugins/digital-performance.d.ts +1 -1
  100. package/dist/plugins/digital-performance.js +1 -1
  101. package/dist/plugins/fire-scene.d.ts +1 -1
  102. package/dist/plugins/fire-scene.js +1 -1
  103. package/dist/plugins/guide-line.js +1 -1
  104. package/dist/plugins/measure.js +1 -1
  105. package/dist/plugins/model-chassis-compass.js +1 -1
  106. package/dist/plugins/model-entry-door-guide.js +1 -1
  107. package/dist/plugins/model-maker.d.ts +1 -1
  108. package/dist/plugins/model-maker.js +1 -1
  109. package/dist/plugins/model-tv-video.js +1 -1
  110. package/dist/plugins/model-view.js +1 -1
  111. package/dist/plugins/object3d-helper.d.ts +1 -1
  112. package/dist/plugins/object3d-helper.js +3 -1
  113. package/dist/plugins/pano-compass.js +1 -1
  114. package/dist/plugins/pano-door-label.js +1 -1
  115. package/dist/plugins/pano-measure.js +1 -1
  116. package/dist/plugins/pano-ruler-pro.js +1 -1
  117. package/dist/plugins/pano-spatial-tag.js +1 -1
  118. package/dist/plugins/pano-tag.d.ts +1 -1
  119. package/dist/plugins/pano-tag.js +4 -1
  120. package/dist/plugins/pano-video.js +1 -1
  121. package/dist/plugins/pipeline.js +1 -1
  122. package/dist/plugins/sculpt.d.ts +1 -1
  123. package/dist/plugins/sculpt.js +7 -1
  124. package/dist/types/public/index.d.ts +2 -0
  125. package/dist/types/public/plugins/digital-performance.d.ts +1 -0
  126. package/dist/types/public/plugins/fire-scene.d.ts +1 -0
  127. package/dist/types/public/plugins/model-maker.d.ts +1 -0
  128. package/dist/types/public/plugins/object3d-helper.d.ts +1 -0
  129. package/dist/types/public/plugins/pano-tag.d.ts +2 -0
  130. package/dist/types/public/plugins/sculpt.d.ts +8 -0
  131. package/dist/types/public/utils.d.ts +5 -0
  132. package/dist/utils.d.ts +1 -1
  133. package/dist/utils.js +16 -50
  134. package/package.json +1 -1
  135. package/dist/internal/BasePluginWithData-9z4tpAT4.js +0 -7
  136. package/dist/internal/CSS3DRenderPlugin-ccSpcvwd.js.map +0 -1
  137. package/dist/internal/Rectangle-D-zkDycu.js.map +0 -1
  138. package/dist/internal/animationFrame-XGKHIeQK.js.map +0 -1
  139. package/dist/internal/blink-DD_0mH-m.js +0 -113
  140. package/dist/internal/blink-DD_0mH-m.js.map +0 -1
  141. package/dist/internal/camera-movement-CwI7UqUk.js.map +0 -1
  142. package/dist/internal/controller-BWkZT0l1.js.map +0 -1
  143. package/dist/internal/defaultUrls-CjKkS9k9.js.map +0 -1
  144. package/dist/internal/fire-scene-CczaBz2_.js.map +0 -1
  145. package/dist/internal/generatePolygonGeometry-B_5JFq8y.js.map +0 -1
  146. package/dist/internal/object3d-helper-DDYsVPN6.js +0 -7
  147. package/dist/utils.js.map +0 -1
@@ -1,7 +1,7 @@
1
- import { i as e, t } from "./Work-DF8j5GnL.js";
1
+ import { i as e, t } from "./Work-BE4AgdwH.js";
2
2
  //#region src/CruisePlugin/index.ts
3
3
  var n = (e, n) => new t(e, n), r = (t, n) => new e(t, n);
4
4
  //#endregion
5
5
  export { r as n, n as t };
6
6
 
7
- //# sourceMappingURL=cruise-C3F0eNQ-.js.map
7
+ //# sourceMappingURL=cruise-B50Tcq66.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cruise-C3F0eNQ-.js","names":["MoveController","CruisePlugin","WalkController","five","parameters","MovePlugin"],"sources":["../../src/CruisePlugin/index.ts"],"sourcesContent":["import type { FivePlugin } from '@realsee/five-webgpu'\nimport * as CruisePluginTypes from './typing'\nimport type { Config } from './typing'\nimport type { MoveConfig as MovePluginConfig } from './Move'\nimport WalkController from './Work'\nimport MoveController from './Move'\n\nexport const CruisePlugin: FivePlugin<Config | undefined, InstanceType<typeof WalkController>> = (five, parameters?) =>\n new WalkController(five, parameters)\nexport const MovePlugin: FivePlugin<MovePluginConfig | undefined, InstanceType<typeof MoveController>> = (five, parameters?) =>\n new MoveController(five, parameters)\n\nexport { WalkController, MoveController, WalkController as CruisePluginController }\nexport type { CruisePluginExportType } from './typing'\nexport { CruisePluginTypes }\n\nexport default CruisePlugin\n"],"mappings":";;AAOA,IAAaC,KAAqF,GAAM,MACtG,IAAIC,EAAeC,GAAMC,CAAU,GACxBC,KAA6F,GAAM,MAC9G,IAAIL,EAAeG,GAAMC,CAAU"}
1
+ {"version":3,"file":"cruise-B50Tcq66.js","names":["MoveController","CruisePlugin","WalkController","five","parameters","MovePlugin"],"sources":["../../src/CruisePlugin/index.ts"],"sourcesContent":["import type { FivePlugin } from '@realsee/five-webgpu'\nimport * as CruisePluginTypes from './typing'\nimport type { Config } from './typing'\nimport type { MoveConfig as MovePluginConfig } from './Move'\nimport WalkController from './Work'\nimport MoveController from './Move'\n\nexport const CruisePlugin: FivePlugin<Config | undefined, InstanceType<typeof WalkController>> = (five, parameters?) =>\n new WalkController(five, parameters)\nexport const MovePlugin: FivePlugin<MovePluginConfig | undefined, InstanceType<typeof MoveController>> = (five, parameters?) =>\n new MoveController(five, parameters)\n\nexport { WalkController, MoveController, WalkController as CruisePluginController }\nexport type { CruisePluginExportType } from './typing'\nexport { CruisePluginTypes }\n\nexport default CruisePlugin\n"],"mappings":";;AAOA,IAAaC,KAAqF,GAAM,MACtG,IAAIC,EAAeC,GAAMC,CAAU,GACxBC,KAA6F,GAAM,MAC9G,IAAIL,EAAeG,GAAMC,CAAU"}
@@ -1,8 +1,8 @@
1
1
  import { n as e } from "./loadTexture-CJ3EbTXw.js";
2
- import { t } from "./defaultUrls-CjKkS9k9.js";
3
- import { n } from "./BetterTween-BX0aTvP1.js";
2
+ import { t } from "./defaultUrls-CfMtGzqM.js";
3
+ import { n } from "./BetterTween-DmptqE8m.js";
4
4
  import { t as r } from "./equal-BiDAilPV.js";
5
- import { t as i } from "./BasePlugin-CT5K8m36.js";
5
+ import { t as i } from "./BasePlugin-DC5m72La.js";
6
6
  import * as a from "three/webgpu";
7
7
  //#region src/CurrentPanoImagePlugin/Controller.ts
8
8
  var o = class extends i {
@@ -216,4 +216,4 @@ var o = class extends i {
216
216
  //#endregion
217
217
  export { s as t };
218
218
 
219
- //# sourceMappingURL=current-pano-image-DKUWluR-.js.map
219
+ //# sourceMappingURL=current-pano-image-BCFr6njt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"current-pano-image-DKUWluR-.js","names":["BasePlugin.Controller","loadTexture","equal","Controller","THREE","CurrentPanoImagePluginController","five","defaultState","params","config","CURRENT_PANO_IMAGE_DEFAULT_IMAGE","userAction","options","mergedOptions","prevState","state","prevConfig","newConfig","msg","result","workCode","standingPosition","panoIndex","position","url","textureLoadingPromise","texture","quaternion","rad","visible","tweenProgress","progress","CurrentPanoImagePlugin"],"sources":["../../src/CurrentPanoImagePlugin/Controller.ts","../../src/CurrentPanoImagePlugin/index.ts"],"sourcesContent":["import * as THREE from 'three/webgpu'\nimport type { Five } from '@realsee/five-webgpu'\nimport * as BasePlugin from '../base/BasePlugin'\nimport type { BetterTween } from '../shared-utils/animationFrame/BetterTween'\nimport { tweenProgress } from '../shared-utils/animationFrame/BetterTween'\nimport type * as PluginType from './typings'\nimport { CURRENT_PANO_IMAGE_DEFAULT_IMAGE, equal } from '../shared-utils'\nimport { loadTexture } from '../shared-utils/three/loadTexture'\n\nexport class CurrentPanoImagePluginController extends BasePlugin.Controller<PluginType.State, PluginType.EventMap> {\n // ==================== public properties ====================\n /** 插件当前状态 */\n public state: PluginType.State\n /** 插件配置项 */\n public get config() {\n return { ...this._config }\n }\n /** 是否已经被销毁 */\n public get disposed() {\n return this._disposed\n }\n /** 查询问题使用的调试对象 */\n public checkMsg = {\n /** mesh 隐藏的原因 */\n meshHidden: '',\n /** 插件 enabled 校验信息 */\n pluginDisabled: '',\n /** 插件 visible 校验信息 */\n pluginHidden: '',\n }\n\n // ==================== private properties ====================\n private group = new THREE.Group()\n private mesh: THREE.Mesh<THREE.PlaneGeometry, THREE.MeshBasicMaterial>\n private textureLoadingPromise?: Promise<THREE.Texture> | null\n private opacityAnimeTween?: BetterTween<{ progress: number }>\n /** 是否正在走点动画中 */\n private isInPanoMoveAnime = false\n /** 上一次走点的全景图索引 */\n private lastArrivedPanoIndex = -1\n /** config 的原始值 */\n private _config: PluginType.Config\n /** disposed 的原始值 */\n private _disposed = false\n\n public constructor(five: Five, params?: PluginType.Params) {\n super(five)\n this.five = five\n\n // 处理 initialState\n const defaultState: PluginType.State = {\n enabled: true,\n visible: true,\n }\n this.state = Object.assign(defaultState, params?.initialState)\n\n // 处理 config\n const config: PluginType.Config = {\n width: 1.4,\n yOffset: 0.01,\n yRotate: 0,\n imageURL: CURRENT_PANO_IMAGE_DEFAULT_IMAGE,\n ...params?.config,\n }\n this._config = config\n\n this.group.name = 'current-pano-image-plugin-group'\n this.mesh = new THREE.Mesh(\n new THREE.PlaneGeometry(this.config.width, this.config.width),\n new THREE.MeshBasicMaterial({ transparent: true, opacity: 0, depthTest: false }),\n )\n this.mesh.visible = false\n this.group.add(this.mesh)\n this.updateMeshQuaternion(this.config.yRotate)\n\n if (!this.state.visible) this.checkMsg.pluginHidden = '初始值设置为隐藏'\n if (!this.state.enabled) this.checkMsg.pluginDisabled = '初始值设置为禁用'\n if (this.state.enabled) this._enable({ userAction: false })\n\n this.five.once('dispose', this.dispose)\n }\n\n /**\n * 启用插件,响应用户操作并展示UI\n * @param options\n */\n public enable(options: BasePlugin.BaseOptions = {}): void {\n if (this.disposed) return\n if (this.state.enabled) return\n const userAction = options.userAction ?? true\n this.updateState({ enabled: true }, userAction)\n this.checkMsg.pluginDisabled = ''\n this._enable({ userAction })\n }\n\n /** 禁用插件\n * @param `options` `<Option> | <undefined>`\n * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。\n */\n public disable(options: BasePlugin.BaseOptions = {}) {\n if (this.disposed) return\n if (this.state.enabled === false) return\n const userAction = options.userAction ?? true\n this.updateState({ enabled: false }, userAction)\n this.checkMsg.pluginDisabled = '调用 disable 禁用'\n this._disable({ userAction })\n }\n\n /** 插件内容整体展示\n * @param `options` `<Partial<BaseOptions>> | <undefined>`\n * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。\n */\n public async show(options?: Partial<PluginType.ShowHideOptions>): Promise<void> {\n if (this.state.visible) return Promise.resolve()\n if (this.disposed) return Promise.reject(new Error('不能在已销毁的插件上调用 show'))\n const mergedOptions = { userAction: true, ...options }\n this.updateState({ visible: true }, mergedOptions.userAction)\n this.checkMsg.pluginHidden = ''\n this._show(mergedOptions)\n }\n\n /** 插件内容整体隐藏\n * @param `options` `<Partial<BaseOptions>> | <undefined>`\n * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。\n */\n public async hide(options?: Partial<PluginType.ShowHideOptions>) {\n if (this.state.visible === false) return\n const mergedOptions = { userAction: true, ...options }\n this.updateState({ visible: false }, mergedOptions.userAction)\n this.checkMsg.pluginDisabled = '调用 hide 隐藏'\n this._hide(mergedOptions)\n }\n\n /** 更改插件 State\n * @param `state` `<Partial<Plugin.State>>` 插件属性 `state` 的子集。\n * @param `options` `<Option> | <undefined>`\n * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。\n */\n public setState(state: Partial<PluginType.State>, options: BasePlugin.BaseOptions = {}) {\n if (this.disposed) return\n const prevState = this.state\n if (equal(state, prevState, { deep: true })) return\n\n const userAction = options.userAction !== undefined ? options.userAction : true\n this.updateState(state, userAction)\n\n if (state.enabled !== undefined && prevState.enabled !== state.enabled) {\n state.enabled ? (this.checkMsg.pluginDisabled = '') : (this.checkMsg.pluginDisabled = '调用 setState 禁用')\n state.enabled ? this._enable({ userAction }) : this._disable({ userAction })\n }\n\n if (state.visible !== undefined && prevState.visible !== state.visible) {\n const options = { userAction, anime: { duration: 500 } }\n state.visible ? (this.checkMsg.pluginHidden = '') : (this.checkMsg.pluginHidden = '调用 setState 隐藏')\n state.visible ? this._show(options) : this._hide(options)\n }\n }\n\n /** 更改插件 Config\n * @param `config` `<Partial<Plugin.Config>>` 插件属性 `config` 的子集。\n * @param `options` `<Option> | <undefined>`\n */\n public updateConfig(config: Partial<PluginType.Config>, options: BasePlugin.BaseOptions = {}) {\n if (this.disposed) return\n const prevConfig = this.config\n const newConfig = { ...prevConfig, ...config }\n this._config = newConfig\n if (prevConfig.imageURL !== newConfig.imageURL) this.reloadTexture(newConfig.imageURL)\n if (prevConfig.yOffset !== newConfig.yOffset) this.updateMeshPosition(this.five.getCurrentState().panoIndex)\n if (prevConfig.yRotate !== newConfig.yRotate) this.updateMeshQuaternion(newConfig.yRotate)\n if (prevConfig.width !== newConfig.width) this.mesh.geometry = new THREE.PlaneGeometry(newConfig.width, newConfig.width)\n this.hooks.emit('configChange', { prevConfig, config: newConfig, userAction: options.userAction ?? true })\n }\n\n /**\n * 销毁插件\n * @todo 销毁贴图时,最好还是直接销毁贴图吧,this.mesh?.material.map 这种都是很深层的引用了。THREE 的建议我看也是自己去管理和销毁公共贴图。\n */\n public dispose = () => {\n if (this.disposed) return\n this._disposed = true\n this.opacityAnimeTween?.dispose()\n this.opacityAnimeTween = undefined\n this.textureLoadingPromise = null\n this.mesh.visible = false\n this.five.scene.remove(this.group)\n this.group.remove(...this.group.children)\n this.five.off('dispose', this.dispose)\n this.five.off('panoArrived', this.onFivePanoArrived)\n this.five.off('panoWillArrive', this.onFivePanoWillArrive)\n this.five.off('willLoad', this.onFiveWillLoad)\n this.five.off('modeChange', this.onFiveModeChange)\n }\n\n /** 问什么看不到模型 */\n public __whyCantSeeMesh() {\n if (this.disposed) return '插件已销毁'\n if (this.checkMsg.pluginDisabled) return this.checkMsg.pluginDisabled\n if (this.checkMsg.pluginHidden) return this.checkMsg.pluginHidden\n if (this.checkMsg.meshHidden) return this.checkMsg.meshHidden\n }\n\n private updateState(state: Partial<PluginType.State>, userAction: boolean) {\n const prevState = this.state\n this.state = { ...this.state, ...state }\n this.hooks.emit('stateChange', { state: this.state, prevState, userAction })\n }\n\n /** 根据各种条件更新 Mesh 的可见性 */\n private updateMeshVisible() {\n const { result, msg } = this.checkMeshVisible()\n this.checkMsg.meshHidden = msg\n if (result !== this.mesh.visible) this.onMeshVisibleChange(result)\n }\n\n private isCurrentOwnerWork(workCode = this.five.getCurrentState().workCode) {\n return !!this.workCode && workCode === this.workCode && this.five.getCurrentState().workCode === this.workCode\n && this.workUtil.work?.workCode === this.workCode\n }\n\n /** 根据点位更新 Mesh 坐标 */\n private updateMeshPosition(panoIndex: number) {\n if (!this.isCurrentOwnerWork()) return\n const standingPosition = this.workUtil.getObserverStandingPosition(panoIndex)\n if (!standingPosition) {\n console.warn('CurrentPanoImagePlugin: 无法获取到当前点位的 standingPosition')\n return\n }\n const position = standingPosition.clone().setY(standingPosition.y + this.config.yOffset)\n if (position) this.mesh.position.copy(position)\n }\n\n /** 重新加载贴图,调用时会先清除已有的贴图 */\n private async reloadTexture(url: string) {\n this.mesh.material.map = null\n if (url !== '') {\n const textureLoadingPromise = loadTexture(url)\n this.textureLoadingPromise = textureLoadingPromise\n const texture = await textureLoadingPromise\n if (this.disposed) { texture.dispose(); return }\n // texture.minFilter 默认是 THREE.LinearMipmapLinearFilter\n texture.minFilter = THREE.LinearFilter\n // texture.magFilter 不需要改,默认就是 THREE.LinearFilter\n // 需要判断一下 Promise 的一致性,防止在加载过程中,又加载了新的贴图\n if (this.textureLoadingPromise === textureLoadingPromise) {\n this.onTextureLoaded(texture)\n this.textureLoadingPromise = null\n }\n }\n this.updateMeshVisible()\n }\n\n /** north_rad 变化时,需要更新模型的旋转角度 */\n private updateMeshQuaternion(rad: number) {\n const quaternion = new THREE.Quaternion()\n quaternion.multiplyQuaternions(\n // 沿着自身 X 轴旋转 -90 度\n new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), -Math.PI / 2),\n // 沿着自身 Z 轴旋转 rad 弧度\n new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 0, 1), rad),\n )\n this.mesh.quaternion.copy(quaternion)\n }\n\n private checkMeshVisible = (): { result: boolean; msg: string } => {\n if (this.disposed) return { result: false, msg: '插件已销毁' }\n if (!this.state.visible) return { result: false, msg: '插件隐藏' }\n if (this.config.imageURL === '') return { result: false, msg: '图片不存在' }\n if (!this.mesh.material.map) return { result: false, msg: '指南针贴图未加载' }\n if (!this.five.work) return { result: false, msg: 'Five 数据未加载' }\n if (!this.isCurrentOwnerWork()) return { result: false, msg: '当前 Work 不是插件所属 Work' }\n if (this.five.getCurrentState().mode !== 'Panorama') return { result: false, msg: '非全景模式' }\n if (this.isInPanoMoveAnime) return { result: false, msg: '处于走点动画中' }\n return { result: true, msg: '' }\n }\n\n private _enable(options: { userAction: boolean }) {\n this.hooks.emit('enable', { userAction: options.userAction })\n\n // 插件启用时,再加载贴图\n if (this.config.imageURL && !this.mesh.material.map && !this.textureLoadingPromise) {\n this.reloadTexture(this.config.imageURL)\n }\n\n // resume model effects\n this.five.scene.add(this.group)\n this.five.needsRender = true\n\n if (this.five.work) this.onFiveWillLoad()\n // enable may precede this owner's first Work; normal panoArrived will position it after loading.\n if (this.isCurrentOwnerWork() && this.five.getCurrentState().mode === 'Panorama') {\n this.onFiveModeChange()\n this.onFivePanoArrived(this.five.getCurrentState().panoIndex)\n }\n\n // resume event effects\n this.five.on('willLoad', this.onFiveWillLoad)\n this.five.on('panoArrived', this.onFivePanoArrived)\n this.five.on('panoWillArrive', this.onFivePanoWillArrive)\n this.five.on('modeChange', this.onFiveModeChange)\n }\n\n private _disable(options: { userAction: boolean }) {\n this.hooks.emit('disable', { userAction: options.userAction })\n\n // dispose model effects\n this.five.scene.remove(this.group)\n this.five.needsRender = true\n\n // dispose event effects\n this.five.off('willLoad', this.onFiveWillLoad)\n this.five.off('panoArrived', this.onFivePanoArrived)\n this.five.off('panoWillArrive', this.onFivePanoWillArrive)\n this.five.off('modeChange', this.onFiveModeChange)\n }\n\n private _show(options: PluginType.ShowHideOptions) {\n this.hooks.emit('show', options)\n this.updateMeshVisible()\n this.five.needsRender = true\n }\n\n private _hide(options: PluginType.ShowHideOptions) {\n this.hooks.emit('hide', options)\n this.updateMeshVisible()\n this.five.needsRender = true\n }\n\n /** 贴图加载完成的回调 */\n private onTextureLoaded = (texture: THREE.Texture) => {\n this.mesh.material.map = texture\n this.mesh.material.needsUpdate = true\n this.updateMeshVisible()\n }\n\n /** Five load Work 后 */\n private onFiveWillLoad = () => {\n // 重启插件时,重置 lastArrivedPanoIndex\n this.lastArrivedPanoIndex = -1\n\n this.updateMeshVisible()\n }\n\n /** 走点前 */\n private onFivePanoWillArrive = (panoIndex: number, state?: Partial<Five['state']>) => {\n if (!this.isCurrentOwnerWork(state?.workCode)) {\n this.lastArrivedPanoIndex = -1\n this.isInPanoMoveAnime = true\n this.opacityAnimeTween?.dispose()\n this.updateMeshVisible()\n return\n }\n if (panoIndex === this.five.getCurrentState().panoIndex) return\n this.isInPanoMoveAnime = true\n this.opacityAnimeTween?.dispose()\n this.updateMeshVisible()\n }\n\n /** 走点后 */\n\n private onFivePanoArrived = (panoIndex: number, state?: Partial<Five['state']>) => {\n if (!this.isCurrentOwnerWork(state?.workCode)) {\n // A global arrival may belong to another Work in the same Five.\n // Do not use its pano index for this owner's position or arrival cache.\n if (!this.isCurrentOwnerWork()) this.lastArrivedPanoIndex = -1\n this.updateMeshVisible()\n return\n }\n // 过滤同一个点位重复 arrived\n if (panoIndex === this.lastArrivedPanoIndex) return\n this.lastArrivedPanoIndex = panoIndex\n this.isInPanoMoveAnime = false\n // 根据点位跟新位置\n this.updateMeshPosition(panoIndex)\n this.updateMeshVisible()\n this.five.needsRender = true\n }\n\n private onMeshVisibleChange = (visible: boolean) => {\n this.opacityAnimeTween?.dispose()\n if (!visible) {\n this.mesh.visible = false\n return\n }\n\n this.mesh.material.setValues({ opacity: 0 })\n this.mesh.visible = true\n this.opacityAnimeTween = tweenProgress(1000)\n .onUpdate(({ progress }) => {\n this.mesh?.material.setValues({ opacity: progress })\n this.five.needsRender = true\n })\n .play()\n }\n\n private onFiveModeChange = () => {\n this.updateMeshVisible()\n }\n}\n","import type { FivePlugin } from '@realsee/five-webgpu'\nimport type * as CurrentPanoImagePluginType from './typings'\nimport { CurrentPanoImagePluginController } from './Controller'\n\nexport const CurrentPanoImagePlugin: FivePlugin<CurrentPanoImagePluginType.Params, CurrentPanoImagePluginController> = (five, params) =>\n new CurrentPanoImagePluginController(five, params)\n\nexport default CurrentPanoImagePlugin\nexport type CurrentPanoImagePluginExportType = CurrentPanoImagePluginController\nexport type { CurrentPanoImagePluginType }\n"],"mappings":"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"}
1
+ {"version":3,"file":"current-pano-image-BCFr6njt.js","names":["BasePlugin.Controller","loadTexture","equal","Controller","THREE","CurrentPanoImagePluginController","five","defaultState","params","config","CURRENT_PANO_IMAGE_DEFAULT_IMAGE","userAction","options","mergedOptions","prevState","state","prevConfig","newConfig","msg","result","workCode","standingPosition","panoIndex","position","url","textureLoadingPromise","texture","quaternion","rad","visible","tweenProgress","progress","CurrentPanoImagePlugin"],"sources":["../../src/CurrentPanoImagePlugin/Controller.ts","../../src/CurrentPanoImagePlugin/index.ts"],"sourcesContent":["import * as THREE from 'three/webgpu'\nimport type { Five } from '@realsee/five-webgpu'\nimport * as BasePlugin from '../base/BasePlugin'\nimport type { BetterTween } from '../shared-utils/animationFrame/BetterTween'\nimport { tweenProgress } from '../shared-utils/animationFrame/BetterTween'\nimport type * as PluginType from './typings'\nimport { CURRENT_PANO_IMAGE_DEFAULT_IMAGE, equal } from '../shared-utils'\nimport { loadTexture } from '../shared-utils/three/loadTexture'\n\nexport class CurrentPanoImagePluginController extends BasePlugin.Controller<PluginType.State, PluginType.EventMap> {\n // ==================== public properties ====================\n /** 插件当前状态 */\n public state: PluginType.State\n /** 插件配置项 */\n public get config() {\n return { ...this._config }\n }\n /** 是否已经被销毁 */\n public get disposed() {\n return this._disposed\n }\n /** 查询问题使用的调试对象 */\n public checkMsg = {\n /** mesh 隐藏的原因 */\n meshHidden: '',\n /** 插件 enabled 校验信息 */\n pluginDisabled: '',\n /** 插件 visible 校验信息 */\n pluginHidden: '',\n }\n\n // ==================== private properties ====================\n private group = new THREE.Group()\n private mesh: THREE.Mesh<THREE.PlaneGeometry, THREE.MeshBasicMaterial>\n private textureLoadingPromise?: Promise<THREE.Texture> | null\n private opacityAnimeTween?: BetterTween<{ progress: number }>\n /** 是否正在走点动画中 */\n private isInPanoMoveAnime = false\n /** 上一次走点的全景图索引 */\n private lastArrivedPanoIndex = -1\n /** config 的原始值 */\n private _config: PluginType.Config\n /** disposed 的原始值 */\n private _disposed = false\n\n public constructor(five: Five, params?: PluginType.Params) {\n super(five)\n this.five = five\n\n // 处理 initialState\n const defaultState: PluginType.State = {\n enabled: true,\n visible: true,\n }\n this.state = Object.assign(defaultState, params?.initialState)\n\n // 处理 config\n const config: PluginType.Config = {\n width: 1.4,\n yOffset: 0.01,\n yRotate: 0,\n imageURL: CURRENT_PANO_IMAGE_DEFAULT_IMAGE,\n ...params?.config,\n }\n this._config = config\n\n this.group.name = 'current-pano-image-plugin-group'\n this.mesh = new THREE.Mesh(\n new THREE.PlaneGeometry(this.config.width, this.config.width),\n new THREE.MeshBasicMaterial({ transparent: true, opacity: 0, depthTest: false }),\n )\n this.mesh.visible = false\n this.group.add(this.mesh)\n this.updateMeshQuaternion(this.config.yRotate)\n\n if (!this.state.visible) this.checkMsg.pluginHidden = '初始值设置为隐藏'\n if (!this.state.enabled) this.checkMsg.pluginDisabled = '初始值设置为禁用'\n if (this.state.enabled) this._enable({ userAction: false })\n\n this.five.once('dispose', this.dispose)\n }\n\n /**\n * 启用插件,响应用户操作并展示UI\n * @param options\n */\n public enable(options: BasePlugin.BaseOptions = {}): void {\n if (this.disposed) return\n if (this.state.enabled) return\n const userAction = options.userAction ?? true\n this.updateState({ enabled: true }, userAction)\n this.checkMsg.pluginDisabled = ''\n this._enable({ userAction })\n }\n\n /** 禁用插件\n * @param `options` `<Option> | <undefined>`\n * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。\n */\n public disable(options: BasePlugin.BaseOptions = {}) {\n if (this.disposed) return\n if (this.state.enabled === false) return\n const userAction = options.userAction ?? true\n this.updateState({ enabled: false }, userAction)\n this.checkMsg.pluginDisabled = '调用 disable 禁用'\n this._disable({ userAction })\n }\n\n /** 插件内容整体展示\n * @param `options` `<Partial<BaseOptions>> | <undefined>`\n * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。\n */\n public async show(options?: Partial<PluginType.ShowHideOptions>): Promise<void> {\n if (this.state.visible) return Promise.resolve()\n if (this.disposed) return Promise.reject(new Error('不能在已销毁的插件上调用 show'))\n const mergedOptions = { userAction: true, ...options }\n this.updateState({ visible: true }, mergedOptions.userAction)\n this.checkMsg.pluginHidden = ''\n this._show(mergedOptions)\n }\n\n /** 插件内容整体隐藏\n * @param `options` `<Partial<BaseOptions>> | <undefined>`\n * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。\n */\n public async hide(options?: Partial<PluginType.ShowHideOptions>) {\n if (this.state.visible === false) return\n const mergedOptions = { userAction: true, ...options }\n this.updateState({ visible: false }, mergedOptions.userAction)\n this.checkMsg.pluginDisabled = '调用 hide 隐藏'\n this._hide(mergedOptions)\n }\n\n /** 更改插件 State\n * @param `state` `<Partial<Plugin.State>>` 插件属性 `state` 的子集。\n * @param `options` `<Option> | <undefined>`\n * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。\n */\n public setState(state: Partial<PluginType.State>, options: BasePlugin.BaseOptions = {}) {\n if (this.disposed) return\n const prevState = this.state\n if (equal(state, prevState, { deep: true })) return\n\n const userAction = options.userAction !== undefined ? options.userAction : true\n this.updateState(state, userAction)\n\n if (state.enabled !== undefined && prevState.enabled !== state.enabled) {\n state.enabled ? (this.checkMsg.pluginDisabled = '') : (this.checkMsg.pluginDisabled = '调用 setState 禁用')\n state.enabled ? this._enable({ userAction }) : this._disable({ userAction })\n }\n\n if (state.visible !== undefined && prevState.visible !== state.visible) {\n const options = { userAction, anime: { duration: 500 } }\n state.visible ? (this.checkMsg.pluginHidden = '') : (this.checkMsg.pluginHidden = '调用 setState 隐藏')\n state.visible ? this._show(options) : this._hide(options)\n }\n }\n\n /** 更改插件 Config\n * @param `config` `<Partial<Plugin.Config>>` 插件属性 `config` 的子集。\n * @param `options` `<Option> | <undefined>`\n */\n public updateConfig(config: Partial<PluginType.Config>, options: BasePlugin.BaseOptions = {}) {\n if (this.disposed) return\n const prevConfig = this.config\n const newConfig = { ...prevConfig, ...config }\n this._config = newConfig\n if (prevConfig.imageURL !== newConfig.imageURL) this.reloadTexture(newConfig.imageURL)\n if (prevConfig.yOffset !== newConfig.yOffset) this.updateMeshPosition(this.five.getCurrentState().panoIndex)\n if (prevConfig.yRotate !== newConfig.yRotate) this.updateMeshQuaternion(newConfig.yRotate)\n if (prevConfig.width !== newConfig.width) this.mesh.geometry = new THREE.PlaneGeometry(newConfig.width, newConfig.width)\n this.hooks.emit('configChange', { prevConfig, config: newConfig, userAction: options.userAction ?? true })\n }\n\n /**\n * 销毁插件\n * @todo 销毁贴图时,最好还是直接销毁贴图吧,this.mesh?.material.map 这种都是很深层的引用了。THREE 的建议我看也是自己去管理和销毁公共贴图。\n */\n public dispose = () => {\n if (this.disposed) return\n this._disposed = true\n this.opacityAnimeTween?.dispose()\n this.opacityAnimeTween = undefined\n this.textureLoadingPromise = null\n this.mesh.visible = false\n this.five.scene.remove(this.group)\n this.group.remove(...this.group.children)\n this.five.off('dispose', this.dispose)\n this.five.off('panoArrived', this.onFivePanoArrived)\n this.five.off('panoWillArrive', this.onFivePanoWillArrive)\n this.five.off('willLoad', this.onFiveWillLoad)\n this.five.off('modeChange', this.onFiveModeChange)\n }\n\n /** 问什么看不到模型 */\n public __whyCantSeeMesh() {\n if (this.disposed) return '插件已销毁'\n if (this.checkMsg.pluginDisabled) return this.checkMsg.pluginDisabled\n if (this.checkMsg.pluginHidden) return this.checkMsg.pluginHidden\n if (this.checkMsg.meshHidden) return this.checkMsg.meshHidden\n }\n\n private updateState(state: Partial<PluginType.State>, userAction: boolean) {\n const prevState = this.state\n this.state = { ...this.state, ...state }\n this.hooks.emit('stateChange', { state: this.state, prevState, userAction })\n }\n\n /** 根据各种条件更新 Mesh 的可见性 */\n private updateMeshVisible() {\n const { result, msg } = this.checkMeshVisible()\n this.checkMsg.meshHidden = msg\n if (result !== this.mesh.visible) this.onMeshVisibleChange(result)\n }\n\n private isCurrentOwnerWork(workCode = this.five.getCurrentState().workCode) {\n return !!this.workCode && workCode === this.workCode && this.five.getCurrentState().workCode === this.workCode\n && this.workUtil.work?.workCode === this.workCode\n }\n\n /** 根据点位更新 Mesh 坐标 */\n private updateMeshPosition(panoIndex: number) {\n if (!this.isCurrentOwnerWork()) return\n const standingPosition = this.workUtil.getObserverStandingPosition(panoIndex)\n if (!standingPosition) {\n console.warn('CurrentPanoImagePlugin: 无法获取到当前点位的 standingPosition')\n return\n }\n const position = standingPosition.clone().setY(standingPosition.y + this.config.yOffset)\n if (position) this.mesh.position.copy(position)\n }\n\n /** 重新加载贴图,调用时会先清除已有的贴图 */\n private async reloadTexture(url: string) {\n this.mesh.material.map = null\n if (url !== '') {\n const textureLoadingPromise = loadTexture(url)\n this.textureLoadingPromise = textureLoadingPromise\n const texture = await textureLoadingPromise\n if (this.disposed) { texture.dispose(); return }\n // texture.minFilter 默认是 THREE.LinearMipmapLinearFilter\n texture.minFilter = THREE.LinearFilter\n // texture.magFilter 不需要改,默认就是 THREE.LinearFilter\n // 需要判断一下 Promise 的一致性,防止在加载过程中,又加载了新的贴图\n if (this.textureLoadingPromise === textureLoadingPromise) {\n this.onTextureLoaded(texture)\n this.textureLoadingPromise = null\n }\n }\n this.updateMeshVisible()\n }\n\n /** north_rad 变化时,需要更新模型的旋转角度 */\n private updateMeshQuaternion(rad: number) {\n const quaternion = new THREE.Quaternion()\n quaternion.multiplyQuaternions(\n // 沿着自身 X 轴旋转 -90 度\n new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), -Math.PI / 2),\n // 沿着自身 Z 轴旋转 rad 弧度\n new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 0, 1), rad),\n )\n this.mesh.quaternion.copy(quaternion)\n }\n\n private checkMeshVisible = (): { result: boolean; msg: string } => {\n if (this.disposed) return { result: false, msg: '插件已销毁' }\n if (!this.state.visible) return { result: false, msg: '插件隐藏' }\n if (this.config.imageURL === '') return { result: false, msg: '图片不存在' }\n if (!this.mesh.material.map) return { result: false, msg: '指南针贴图未加载' }\n if (!this.five.work) return { result: false, msg: 'Five 数据未加载' }\n if (!this.isCurrentOwnerWork()) return { result: false, msg: '当前 Work 不是插件所属 Work' }\n if (this.five.getCurrentState().mode !== 'Panorama') return { result: false, msg: '非全景模式' }\n if (this.isInPanoMoveAnime) return { result: false, msg: '处于走点动画中' }\n return { result: true, msg: '' }\n }\n\n private _enable(options: { userAction: boolean }) {\n this.hooks.emit('enable', { userAction: options.userAction })\n\n // 插件启用时,再加载贴图\n if (this.config.imageURL && !this.mesh.material.map && !this.textureLoadingPromise) {\n this.reloadTexture(this.config.imageURL)\n }\n\n // resume model effects\n this.five.scene.add(this.group)\n this.five.needsRender = true\n\n if (this.five.work) this.onFiveWillLoad()\n // enable may precede this owner's first Work; normal panoArrived will position it after loading.\n if (this.isCurrentOwnerWork() && this.five.getCurrentState().mode === 'Panorama') {\n this.onFiveModeChange()\n this.onFivePanoArrived(this.five.getCurrentState().panoIndex)\n }\n\n // resume event effects\n this.five.on('willLoad', this.onFiveWillLoad)\n this.five.on('panoArrived', this.onFivePanoArrived)\n this.five.on('panoWillArrive', this.onFivePanoWillArrive)\n this.five.on('modeChange', this.onFiveModeChange)\n }\n\n private _disable(options: { userAction: boolean }) {\n this.hooks.emit('disable', { userAction: options.userAction })\n\n // dispose model effects\n this.five.scene.remove(this.group)\n this.five.needsRender = true\n\n // dispose event effects\n this.five.off('willLoad', this.onFiveWillLoad)\n this.five.off('panoArrived', this.onFivePanoArrived)\n this.five.off('panoWillArrive', this.onFivePanoWillArrive)\n this.five.off('modeChange', this.onFiveModeChange)\n }\n\n private _show(options: PluginType.ShowHideOptions) {\n this.hooks.emit('show', options)\n this.updateMeshVisible()\n this.five.needsRender = true\n }\n\n private _hide(options: PluginType.ShowHideOptions) {\n this.hooks.emit('hide', options)\n this.updateMeshVisible()\n this.five.needsRender = true\n }\n\n /** 贴图加载完成的回调 */\n private onTextureLoaded = (texture: THREE.Texture) => {\n this.mesh.material.map = texture\n this.mesh.material.needsUpdate = true\n this.updateMeshVisible()\n }\n\n /** Five load Work 后 */\n private onFiveWillLoad = () => {\n // 重启插件时,重置 lastArrivedPanoIndex\n this.lastArrivedPanoIndex = -1\n\n this.updateMeshVisible()\n }\n\n /** 走点前 */\n private onFivePanoWillArrive = (panoIndex: number, state?: Partial<Five['state']>) => {\n if (!this.isCurrentOwnerWork(state?.workCode)) {\n this.lastArrivedPanoIndex = -1\n this.isInPanoMoveAnime = true\n this.opacityAnimeTween?.dispose()\n this.updateMeshVisible()\n return\n }\n if (panoIndex === this.five.getCurrentState().panoIndex) return\n this.isInPanoMoveAnime = true\n this.opacityAnimeTween?.dispose()\n this.updateMeshVisible()\n }\n\n /** 走点后 */\n\n private onFivePanoArrived = (panoIndex: number, state?: Partial<Five['state']>) => {\n if (!this.isCurrentOwnerWork(state?.workCode)) {\n // A global arrival may belong to another Work in the same Five.\n // Do not use its pano index for this owner's position or arrival cache.\n if (!this.isCurrentOwnerWork()) this.lastArrivedPanoIndex = -1\n this.updateMeshVisible()\n return\n }\n // 过滤同一个点位重复 arrived\n if (panoIndex === this.lastArrivedPanoIndex) return\n this.lastArrivedPanoIndex = panoIndex\n this.isInPanoMoveAnime = false\n // 根据点位跟新位置\n this.updateMeshPosition(panoIndex)\n this.updateMeshVisible()\n this.five.needsRender = true\n }\n\n private onMeshVisibleChange = (visible: boolean) => {\n this.opacityAnimeTween?.dispose()\n if (!visible) {\n this.mesh.visible = false\n return\n }\n\n this.mesh.material.setValues({ opacity: 0 })\n this.mesh.visible = true\n this.opacityAnimeTween = tweenProgress(1000)\n .onUpdate(({ progress }) => {\n this.mesh?.material.setValues({ opacity: progress })\n this.five.needsRender = true\n })\n .play()\n }\n\n private onFiveModeChange = () => {\n this.updateMeshVisible()\n }\n}\n","import type { FivePlugin } from '@realsee/five-webgpu'\nimport type * as CurrentPanoImagePluginType from './typings'\nimport { CurrentPanoImagePluginController } from './Controller'\n\nexport const CurrentPanoImagePlugin: FivePlugin<CurrentPanoImagePluginType.Params, CurrentPanoImagePluginController> = (five, params) =>\n new CurrentPanoImagePluginController(five, params)\n\nexport default CurrentPanoImagePlugin\nexport type CurrentPanoImagePluginExportType = CurrentPanoImagePluginController\nexport type { CurrentPanoImagePluginType }\n"],"mappings":"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"}
@@ -1,6 +1,17 @@
1
1
  //#region src/shared-utils/url/defaultUrls.ts
2
- var e = "//vr-image-4.realsee-cdn.cn", t = "//vr-image-4.realsee-cdn.cn/release/web/arrow1.ebe7d0ff.png", n = "//vr-image-4.realsee-cdn.cn/release/web/arrow-white.5c2c79a5.png", r = "//vr-image-4.realsee-cdn.cn/release/web/PanoSpatialTagPlugin__blur.png", i = "//vr-image-4.realsee-cdn.cn/release/web/test.09dee741.png", a = "//vr-image-4.realsee-cdn.cn/release/web/dipan2.f38a21cc.FBX", o = "//vr-image-4.realsee-cdn.cn/release/web/logo.7febb17f.png", s = "//vr-public.realsee-cdn.cn/release/web/entryDoorMini/Anim_Door1.fbx", c = "//vr-image-4.realsee-cdn.cn/release/web/saas/missing-floorplan.e274c596.png", l = "//vr-image-4.realsee-cdn.cn/release/web/v3/north-point-circle.96498e69.png", u = "//vr-image-4.realsee-cdn.cn/release/web/enterDoor.831b8208.png";
2
+ var e = "//vr-image-4.realsee-cdn.cn", t = "//vr-image-4.realsee-cdn.cn/release/web/arrow1.ebe7d0ff.png", n = "//vr-image-4.realsee-cdn.cn/release/web/arrow-white.5c2c79a5.png", r = "//vr-image-4.realsee-cdn.cn/release/web/PanoSpatialTagPlugin__blur.png", i = "//vr-image-4.realsee-cdn.cn/release/web/test.09dee741.png", a = "//vr-image-4.realsee-cdn.cn/release/web/dipan2.f38a21cc.FBX", o = "//vr-image-4.realsee-cdn.cn/release/web/logo.7febb17f.png", s = "//vr-public.realsee-cdn.cn/release/web/entryDoorMini/Anim_Door1.fbx", c = "//vr-image-4.realsee-cdn.cn/release/web/saas/missing-floorplan.e274c596.png", l = "//vr-image-4.realsee-cdn.cn/release/web/v3/north-point-circle.96498e69.png", u = "//vr-image-4.realsee-cdn.cn/release/web/enterDoor.831b8208.png", d = [
3
+ t,
4
+ n,
5
+ r,
6
+ i,
7
+ a,
8
+ o,
9
+ s,
10
+ c,
11
+ l,
12
+ u
13
+ ];
3
14
  //#endregion
4
- export { t as a, s as c, i as d, c as i, l, e as n, n as o, u as r, a as s, o as t, r as u };
15
+ export { c as a, a as c, r as d, i as f, u as i, s as l, e as n, t as o, d as r, n as s, o as t, l as u };
5
16
 
6
- //# sourceMappingURL=defaultUrls-CjKkS9k9.js.map
17
+ //# sourceMappingURL=defaultUrls-CfMtGzqM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultUrls-CfMtGzqM.js","names":["DEFAULT_STATIC_PREFIX","GUIDELINE_DEFAULT_ARROW_TEXTURE","GUIDELINE_WHITE_ARROW_TEXTURE","PANO_SPATIAL_TAG_BLUR_IMAGE","PANO_TAG_DEFAULT_LINK_ICON","MODEL_CHASSIS_COMPASS_DEFAULT_MODEL","CURRENT_PANO_IMAGE_DEFAULT_IMAGE","MODEL_ENTRY_DOOR_GUIDE_PLUGIN_DEFAULT_MODEL","FLOORPLAN_DEFAULT_IMAGE","PANO_COMPASS_DEFAULT_IMAGE","ENTRY_DOOR_DEFAULT_IMAGE","DNALOGEL_DEFAULT_ASSETS"],"sources":["../../src/shared-utils/url/defaultUrls.ts"],"sourcesContent":["/**\n * 默认资源URL配置\n * 集中管理所有插件使用的默认资源链接\n */\n\n/** 默认的静态资源前缀 */\nexport const DEFAULT_STATIC_PREFIX = '//vr-image-4.realsee-cdn.cn'\n\n/** GuideLinePlugin 默认箭头贴图 */\nexport const GUIDELINE_DEFAULT_ARROW_TEXTURE = `//vr-image-4.realsee-cdn.cn/release/web/arrow1.ebe7d0ff.png`\n\n/** GuideLinePlugin 白色箭头贴图(用于配置) */\nexport const GUIDELINE_WHITE_ARROW_TEXTURE = `//vr-image-4.realsee-cdn.cn/release/web/arrow-white.5c2c79a5.png`\n\n/** PanoSpatialTagPlugin 模糊图片 */\nexport const PANO_SPATIAL_TAG_BLUR_IMAGE = `//vr-image-4.realsee-cdn.cn/release/web/PanoSpatialTagPlugin__blur.png`\n\n/** PanoTagPlugin 默认链接图标 */\nexport const PANO_TAG_DEFAULT_LINK_ICON = `//vr-image-4.realsee-cdn.cn/release/web/test.09dee741.png`\n\n/** ModelChassisCompassPlugin 默认模型 */\nexport const MODEL_CHASSIS_COMPASS_DEFAULT_MODEL = `//vr-image-4.realsee-cdn.cn/release/web/dipan2.f38a21cc.FBX`\n\n/** CurrentPanoImagePlugin 默认图片 */\nexport const CURRENT_PANO_IMAGE_DEFAULT_IMAGE = `//vr-image-4.realsee-cdn.cn/release/web/logo.7febb17f.png`\n\n/** ModelEntryDoorGuidePlugin 默认模型 */\nexport const MODEL_ENTRY_DOOR_GUIDE_PLUGIN_DEFAULT_MODEL = `//vr-public.realsee-cdn.cn/release/web/entryDoorMini/Anim_Door1.fbx`\n\n/** MapviewFloorplanPlugin 默认图片 */\nexport const FLOORPLAN_DEFAULT_IMAGE = `//vr-image-4.realsee-cdn.cn/release/web/saas/missing-floorplan.e274c596.png`\n\n/** PanoCompassPlugin 默认图片 */\nexport const PANO_COMPASS_DEFAULT_IMAGE = `//vr-image-4.realsee-cdn.cn/release/web/v3/north-point-circle.96498e69.png`\n\n/** PanoCompassPlugin 默认图片 */\nexport const ENTRY_DOOR_DEFAULT_IMAGE = `//vr-image-4.realsee-cdn.cn/release/web/enterDoor.831b8208.png`\n\n/**\n * 默认资源URL列表, 用于提供给应用读取默认资源, 并进行转换\n */\nexport const DNALOGEL_DEFAULT_ASSETS = [\n GUIDELINE_DEFAULT_ARROW_TEXTURE,\n GUIDELINE_WHITE_ARROW_TEXTURE,\n PANO_SPATIAL_TAG_BLUR_IMAGE,\n PANO_TAG_DEFAULT_LINK_ICON,\n MODEL_CHASSIS_COMPASS_DEFAULT_MODEL,\n CURRENT_PANO_IMAGE_DEFAULT_IMAGE,\n MODEL_ENTRY_DOOR_GUIDE_PLUGIN_DEFAULT_MODEL,\n FLOORPLAN_DEFAULT_IMAGE,\n PANO_COMPASS_DEFAULT_IMAGE,\n ENTRY_DOOR_DEFAULT_IMAGE,\n]\n"],"mappings":";AAMA,IAAaA,IAAwB,+BAGxBC,IAAkC,+DAGlCC,IAAgC,oEAGhCC,IAA8B,0EAG9BC,IAA6B,6DAG7BC,IAAsC,+DAGtCC,IAAmC,6DAGnCC,IAA8C,uEAG9CC,IAA0B,+EAG1BC,IAA6B,8EAG7BC,IAA2B,kEAK3BC,IAA0B;CACrCV;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;CACAC;AACF"}
@@ -2,7 +2,7 @@ import { n as e } from "./loadTexture-CJ3EbTXw.js";
2
2
  import { t } from "./GLTFLoader-DCsDrP-N.js";
3
3
  import { t as n } from "./transformPosition-Cc92Wf0o.js";
4
4
  import { n as r } from "./FiveUtil-DyTBRHpM.js";
5
- import { t as i } from "./lookObject-wesf8xt6.js";
5
+ import { t as i } from "./lookObject-DuRab5wf.js";
6
6
  import * as a from "three/webgpu";
7
7
  import { attribute as o, texture as s, uv as c, vec4 as l } from "three/tsl";
8
8
  //#region src/FireScenePlugin/constants.ts
@@ -1050,9 +1050,14 @@ function L(e) {
1050
1050
  function R(e) {
1051
1051
  return new a.Box3().setFromPoints(L(e));
1052
1052
  }
1053
+ function z(e) {
1054
+ if (!e) return;
1055
+ let t = e.ignite_sequences?.[0], n = t && e.models?.find((e) => e.id === t.model_id);
1056
+ return n?.area_id && e.areas?.find((e) => e.id === n.area_id) || e.areas?.[0];
1057
+ }
1053
1058
  //#endregion
1054
1059
  //#region src/FireScenePlugin/SequencePlayer.ts
1055
- var z = class {
1060
+ var B = class {
1056
1061
  fireControl;
1057
1062
  config;
1058
1063
  options;
@@ -1157,6 +1162,6 @@ var z = class {
1157
1162
  }
1158
1163
  };
1159
1164
  //#endregion
1160
- export { F as n, z as t };
1165
+ export { z as n, F as r, B as t };
1161
1166
 
1162
- //# sourceMappingURL=fire-scene-CczaBz2_.js.map
1167
+ //# sourceMappingURL=fire-scene-BzZGvyh_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fire-scene-BzZGvyh_.js","names":["loadTexture","transformPosition","WorkUtil","lookObject","THREE","FIRE_ACTION_DURATION_MS","SPREAD_COVERAGE_TARGET","MODEL_SCALE_RANGE","random","base","spread","randomVector","tweenNumber","last","tween","time","index","progress","tweenVector","target","Particle","fallbackTexture","mapNode","texture","options","material","uv","vec4","attribute","geometry","camera","value","timeMilliseconds","emitterAge","particleCount","instance","delay","birthTime","position","z","theta","radius","velocity","positionOffset","age","ageSquared","required","capacity","colorAttribute","opacityAttribute","offset","size","measureSpreadBounds","minX","minY","minZ","maxX","maxY","maxZ","bounds","width","height","depth","speedToGrowth","speedMultiplier","spreadSpeed","DEFAULT_FIRE_GROWTH_CONFIG","buildFireGrowthConfig","maxFires","volume","fireSizeFactor","fireSize","fireSizeMultiplier","interval","diagonal","RadialSpread","stepLength","cx0","cz0","currentRing","maxNew","cells","ix","iz","cx","cz","key","ring","phase","growthLevel","density","rand2","jitterRange","jx","jz","s","hashString","seed","x","h","i","str","disposeParticle","particle","FireManager","scene","particleTexture","finalConfig","config","fireData","positions","id","scale","name","firesReached","coverageReached","radiusReached","newFire","scaleJitter","level","totalTime","extinguishTime","totalSteps","extinguishRate","extinguishStartTime","extinguishTimer","currentRate","particleToRemove","timeElapsed","onComplete","fadeInTime","step","newConfig","oldBase","delta","newBasePosition","opacity","NormalSmokeManager","source","intensity","fadeInMs","steps","durationMs","targetIntensity","smokePosition","spreadFactor","SmokeManager","previous","state","derivedId","coverage","derived","spreadState","SMOKE_SPREAD_FADE_IN_MS","buildSmokeSpreadConfig","maxSources","intensityFactor","getTextureLoader","cache","url","texturePromise","ParticleTexture","listener","SMOKE_RENDER_CONFIG","clampModelScale","FireControl","five","entry","workCode","nextWaterGun","nextParticle","resolver","check","kind","worldPosition","worldBounds","nextSize","spreadBounds","visible","floorIndex","smokeManager","sourceIds","startIntensities","sourceId","startIntensity","token","result","loadGLTF","rotation","spray","firefighter","fire","smoke","entitySize","boxSize","placeholder","pending","corners","y","box","firefighterId","UNIT_BOX_VERTICES","getAreaVertices","matrix4","matrix","vertex","getAreaBox3","getEntryArea","firstStep","firstModel","model","it","FireScenePlayer","fireControl","absoluteMs","endMs","startsAt","timer","executed","item","area","duration","error"],"sources":["../../src/FireScenePlugin/constants.ts","../../src/shared-utils/rendering/Particle.ts","../../src/FireScenePlugin/utils/spread.ts","../../src/FireScenePlugin/fire/config.ts","../../src/FireScenePlugin/utils/radialSpread.ts","../../src/FireScenePlugin/utils/particle.ts","../../src/FireScenePlugin/fire/managers/FireManager.ts","../../src/FireScenePlugin/smoke/managers/NormalSmokeManager.ts","../../src/FireScenePlugin/smoke/managers/SmokeManager.ts","../../src/FireScenePlugin/smoke/config.ts","../../src/shared-utils/three/getTextureLoader.ts","../../src/FireScenePlugin/utils/particleTexture.ts","../../src/FireScenePlugin/FireControl.ts","../../src/FireScenePlugin/utils/areaBounds.ts","../../src/FireScenePlugin/SequencePlayer.ts"],"sourcesContent":["import type { FireModelType, FireSequenceKind } from './typing'\n\n/**\n * 各动作的播放时长(毫秒)。\n */\nexport const FIRE_ACTION_DURATION_MS: Record<FireSequenceKind, Partial<Record<FireModelType, number>>> = {\n /** 起火序列 */\n ignite: {\n /** 火焰淡入时间 */\n fire: 2000,\n /** 烟雾淡入时间 */\n smoke: 2000,\n },\n /** 灭火序列 */\n extinguish: {\n /** 消防员出现,立刻出现,无淡入效果 */\n firefighter: 0,\n /** 火焰淡出时间 */\n fire: 2000,\n /** 烟雾淡出时间 */\n smoke: 2000,\n },\n}\n\n/**\n * 起火点的蔓延速度:值越大,火势铺开越快。\n */\nexport const FIRE_SPREAD_SPEED = 2.0\n\n/**\n * 浓度渐变的分步间隔(毫秒)。\n */\nexport const FADE_STEP_MS = 100\n\n/**\n * 蔓延的目标覆盖率:铺开的面积占比达到它就停止蔓延。\n */\nexport const SPREAD_COVERAGE_TARGET = 0.85\n\n/**\n * 单次蔓延步进最多新增的网格数。\n */\nexport const MAX_SPREAD_CELLS_PER_STEP = 320\n\n/**\n * 模型的尺寸范围(相对原始尺寸的倍率)。\n */\nexport const MODEL_SCALE_RANGE = { min: 0.1, max: 5 } as const\n","import * as THREE from 'three/webgpu'\nimport { attribute, texture, uv, vec4 } from 'three/tsl'\n\nexport type ParticleType = 'CUBE' | 'SPHERE'\n\nexport interface ParticleTween<T> {\n times: number[]\n values: T[]\n}\n\nexport interface ParticleOptions {\n positionBase: THREE.Vector3\n positionStyle: ParticleType\n positionCubeSpread: THREE.Vector3\n positionSphereSpread: number\n velocityStyle: ParticleType\n velocityCubeBase: THREE.Vector3\n velocityCubeSpread: THREE.Vector3\n velocitySphereBase: number\n velocitySphereSpread: number\n accelerationBase: THREE.Vector3\n accelerationSpread: THREE.Vector3\n angleBase: number\n angleSpread: number\n angleVelocityBase: number\n angleVelocitySpread: number\n angleAccelerationBase: number\n angleAccelerationSpread: number\n sizeBase: number\n sizeSpread: number\n sizeTween: ParticleTween<number> | null\n colorBase: THREE.Vector3\n colorSpread: THREE.Vector3\n colorTween: ParticleTween<THREE.Vector3> | null\n opacityBase: number\n opacitySpread: number\n opacityTween: ParticleTween<number> | null\n texture: THREE.Texture\n blending: THREE.Blending\n particlesPerSecond: number\n particleDeathAge: number\n}\n\ninterface ParticleInstance {\n birthTime: number\n position: THREE.Vector3\n velocity: THREE.Vector3\n acceleration: THREE.Vector3\n angle: number\n angleVelocity: number\n angleAcceleration: number\n color: THREE.Vector3\n size: number\n opacity: number\n}\n\nfunction random(base: number, spread: number): number {\n return base + spread * (Math.random() - 0.5)\n}\n\nfunction randomVector(base: THREE.Vector3, spread: THREE.Vector3): THREE.Vector3 {\n return new THREE.Vector3(random(base.x, spread.x), random(base.y, spread.y), random(base.z, spread.z))\n}\n\nfunction tweenNumber(tween: ParticleTween<number>, time: number): number {\n const last = tween.times.length - 1\n if (last < 0) return 0\n if (time <= tween.times[0]) return tween.values[0]\n if (time >= tween.times[last]) return tween.values[last]\n\n let index = 1\n while (time > tween.times[index]) index += 1\n const progress = (time - tween.times[index - 1]) / (tween.times[index] - tween.times[index - 1])\n return THREE.MathUtils.lerp(tween.values[index - 1], tween.values[index], progress)\n}\n\nfunction tweenVector(tween: ParticleTween<THREE.Vector3>, time: number, target: THREE.Vector3): THREE.Vector3 {\n const last = tween.times.length - 1\n if (last < 0) return target.set(0, 0, 0)\n if (time <= tween.times[0]) return target.copy(tween.values[0])\n if (time >= tween.times[last]) return target.copy(tween.values[last])\n\n let index = 1\n while (time > tween.times[index]) index += 1\n const progress = (time - tween.times[index - 1]) / (tween.times[index] - tween.times[index - 1])\n return target.copy(tween.values[index - 1]).lerp(tween.values[index], progress)\n}\n\nexport class Particle extends THREE.InstancedMesh<THREE.PlaneGeometry, THREE.MeshBasicNodeMaterial> {\n public needsRender = true\n public paused = false\n\n public positionBase: THREE.Vector3\n public positionStyle: ParticleType\n public positionCubeSpread: THREE.Vector3\n public positionSphereSpread: number\n public velocityStyle: ParticleType\n public velocityCubeBase: THREE.Vector3\n public velocityCubeSpread: THREE.Vector3\n public velocitySphereBase: number\n public velocitySphereSpread: number\n public accelerationBase: THREE.Vector3\n public accelerationSpread: THREE.Vector3\n public angleBase: number\n public angleSpread: number\n public angleVelocityBase: number\n public angleVelocitySpread: number\n public angleAccelerationBase: number\n public angleAccelerationSpread: number\n public sizeBase: number\n public sizeSpread: number\n public sizeTween: ParticleTween<number> | null\n public colorBase: THREE.Vector3\n public colorSpread: THREE.Vector3\n public colorTween: ParticleTween<THREE.Vector3> | null\n public opacityBase: number\n public opacitySpread: number\n public opacityTween: ParticleTween<number> | null\n public particlesPerSecond: number\n public particleDeathAge: number\n\n private disposed = false\n private emissionStartTime: number | null = null\n private capacity = 1\n private instances: Array<ParticleInstance | undefined> = []\n private colors = new Float32Array(3)\n private opacities = new Float32Array(1)\n private sizes = new Float32Array(1)\n private angles = new Float32Array(1)\n private positions = new Float32Array(3)\n private readonly mapNode\n private readonly fallbackTexture: THREE.DataTexture\n private readonly localCameraQuaternion = new THREE.Quaternion()\n private readonly worldQuaternion = new THREE.Quaternion()\n private readonly angleQuaternion = new THREE.Quaternion()\n private readonly instanceTransform = new THREE.Matrix4()\n private readonly scaleVector = new THREE.Vector3()\n private readonly color = new THREE.Color()\n private readonly hsl = new THREE.Vector3()\n private readonly zAxis = new THREE.Vector3(0, 0, 1)\n\n public constructor(options: Partial<ParticleOptions>) {\n const fallbackTexture = new THREE.DataTexture(new Uint8Array([255, 255, 255, 255]), 1, 1)\n fallbackTexture.needsUpdate = true\n const mapNode = texture(options.texture ?? fallbackTexture)\n const material = new THREE.MeshBasicNodeMaterial({\n transparent: true,\n depthWrite: false,\n blending: options.blending ?? THREE.NormalBlending,\n side: THREE.DoubleSide,\n })\n material.colorNode = mapNode\n .sample(uv())\n .mul(vec4(attribute<'vec3'>('particleColor', 'vec3'), attribute<'float'>('particleOpacity', 'float')))\n material.alphaTest = 0.001\n\n const geometry = new THREE.PlaneGeometry(1, 1)\n geometry.setAttribute('particleColor', new THREE.InstancedBufferAttribute(new Float32Array(3), 3))\n geometry.setAttribute('particleOpacity', new THREE.InstancedBufferAttribute(new Float32Array(1), 1))\n super(geometry, material, 1)\n this.colors = geometry.getAttribute('particleColor').array as Float32Array<ArrayBuffer>\n this.opacities = geometry.getAttribute('particleOpacity').array as Float32Array<ArrayBuffer>\n\n this.fallbackTexture = fallbackTexture\n this.mapNode = mapNode\n this.count = 0\n this.frustumCulled = false\n\n this.positionBase = options.positionBase?.clone() ?? new THREE.Vector3()\n this.positionStyle = options.positionStyle ?? 'CUBE'\n this.positionCubeSpread = options.positionCubeSpread?.clone() ?? new THREE.Vector3()\n this.positionSphereSpread = options.positionSphereSpread ?? 0\n this.velocityStyle = options.velocityStyle ?? 'CUBE'\n this.velocityCubeBase = options.velocityCubeBase?.clone() ?? new THREE.Vector3()\n this.velocityCubeSpread = options.velocityCubeSpread?.clone() ?? new THREE.Vector3()\n this.velocitySphereBase = options.velocitySphereBase ?? 0\n this.velocitySphereSpread = options.velocitySphereSpread ?? 0\n this.accelerationBase = options.accelerationBase?.clone() ?? new THREE.Vector3()\n this.accelerationSpread = options.accelerationSpread?.clone() ?? new THREE.Vector3()\n this.angleBase = options.angleBase ?? 0\n this.angleSpread = options.angleSpread ?? 0\n this.angleVelocityBase = options.angleVelocityBase ?? 0\n this.angleVelocitySpread = options.angleVelocitySpread ?? 0\n this.angleAccelerationBase = options.angleAccelerationBase ?? 0\n this.angleAccelerationSpread = options.angleAccelerationSpread ?? 0\n this.sizeBase = options.sizeBase ?? 0.1\n this.sizeSpread = options.sizeSpread ?? 0\n this.sizeTween = options.sizeTween ?? null\n this.colorBase = options.colorBase?.clone() ?? new THREE.Vector3()\n this.colorSpread = options.colorSpread?.clone() ?? new THREE.Vector3()\n this.colorTween = options.colorTween ?? null\n this.opacityBase = options.opacityBase ?? (options.opacityTween ? 0 : 1)\n this.opacitySpread = options.opacitySpread ?? 0\n this.opacityTween = options.opacityTween ?? null\n this.particlesPerSecond = options.particlesPerSecond ?? 60\n this.particleDeathAge = options.particleDeathAge ?? 1\n\n this.onBeforeRender = (_renderer, _scene, camera) => {\n this.worldQuaternion.setFromRotationMatrix(this.matrixWorld).invert()\n this.localCameraQuaternion.copy(this.worldQuaternion).multiply(camera.quaternion)\n this.updateMatrices()\n }\n }\n\n public get texture(): THREE.Texture | null {\n return this.mapNode.value === this.fallbackTexture ? null : this.mapNode.value\n }\n\n public set texture(value: THREE.Texture | null) {\n this.mapNode.value = value ?? this.fallbackTexture\n this.material.needsUpdate = true\n }\n\n public get blending(): THREE.Blending {\n return this.material.blending\n }\n\n public set blending(value: THREE.Blending) {\n this.material.blending = value\n this.material.needsUpdate = true\n }\n\n public pause(): void {\n if (this.paused) return\n this.paused = true\n this.emissionStartTime = null\n }\n\n public play(): void {\n if (!this.paused) return\n this.paused = false\n this.emissionStartTime = null\n }\n\n public setTime(timeMilliseconds: number): void {\n if (this.disposed) return\n const time = timeMilliseconds / 1000\n this.emissionStartTime ??= time\n const emitterAge = time - this.emissionStartTime\n const particleCount = Math.max(0, Math.ceil(this.particlesPerSecond * this.particleDeathAge))\n this.ensureCapacity(particleCount)\n this.count = particleCount\n this.instances.length = particleCount\n\n for (let index = 0; index < particleCount; index += 1) {\n let instance = this.instances[index]\n if (!this.paused && (!instance || time - instance.birthTime >= this.particleDeathAge)) {\n const delay = particleCount > 0 ? (this.particleDeathAge / particleCount) * index : 0\n if (emitterAge > delay) {\n const birthTime = time - ((emitterAge - delay) % this.particleDeathAge)\n instance = this.createInstance(birthTime)\n this.instances[index] = instance\n }\n }\n this.updateInstance(index, instance, time)\n }\n\n this.updateAttributes()\n this.updateMatrices()\n this.needsRender = true\n }\n\n public dispose(): this {\n if (this.disposed) return this\n this.disposed = true\n this.geometry.dispose()\n this.material.dispose()\n this.fallbackTexture.dispose()\n this.instances = []\n return this\n }\n\n private createInstance(birthTime: number): ParticleInstance {\n let position: THREE.Vector3\n if (this.positionStyle === 'SPHERE') {\n const z = 2 * Math.random() - 1\n const theta = Math.PI * 2 * Math.random()\n const radius = Math.sqrt(1 - z * z)\n position = new THREE.Vector3(radius * Math.cos(theta), radius * Math.sin(theta), z)\n .multiplyScalar(this.positionSphereSpread)\n .add(this.positionBase)\n } else {\n position = randomVector(this.positionBase, this.positionCubeSpread)\n }\n\n let velocity: THREE.Vector3\n if (this.velocityStyle === 'SPHERE') {\n velocity = position\n .clone()\n .sub(this.positionBase)\n .normalize()\n .multiplyScalar(random(this.velocitySphereBase, this.velocitySphereSpread))\n } else {\n velocity = randomVector(this.velocityCubeBase, this.velocityCubeSpread)\n }\n\n return {\n birthTime,\n position,\n velocity,\n acceleration: randomVector(this.accelerationBase, this.accelerationSpread),\n angle: random(this.angleBase, this.angleSpread),\n angleVelocity: random(this.angleVelocityBase, this.angleVelocitySpread),\n angleAcceleration: random(this.angleAccelerationBase, this.angleAccelerationSpread),\n color: randomVector(this.colorBase, this.colorSpread),\n size: random(this.sizeBase, this.sizeSpread),\n opacity: random(this.opacityBase, this.opacitySpread),\n }\n }\n\n private updateInstance(index: number, instance: ParticleInstance | undefined, time: number): void {\n const positionOffset = index * 3\n if (!instance) {\n this.positions.fill(0, positionOffset, positionOffset + 3)\n this.colors.fill(0, positionOffset, positionOffset + 3)\n this.opacities[index] = 0\n this.sizes[index] = 0\n this.angles[index] = 0\n return\n }\n\n const age = Math.min(this.particleDeathAge, Math.max(0, time - instance.birthTime))\n const ageSquared = age * age * 0.5\n this.positions[positionOffset] =\n instance.position.x + instance.velocity.x * age + instance.acceleration.x * ageSquared\n this.positions[positionOffset + 1] =\n instance.position.y + instance.velocity.y * age + instance.acceleration.y * ageSquared\n this.positions[positionOffset + 2] =\n instance.position.z + instance.velocity.z * age + instance.acceleration.z * ageSquared\n this.angles[index] = instance.angle + instance.angleVelocity * age + instance.angleAcceleration * ageSquared\n this.sizes[index] = instance.size + (this.sizeTween ? tweenNumber(this.sizeTween, age) : 0)\n this.opacities[index] = instance.opacity + (this.opacityTween ? tweenNumber(this.opacityTween, age) : 0)\n\n this.hsl.copy(instance.color)\n if (this.colorTween) this.hsl.add(tweenVector(this.colorTween, age, new THREE.Vector3()))\n this.color.setHSL(this.hsl.x, this.hsl.y, this.hsl.z)\n this.colors[positionOffset] = this.color.r\n this.colors[positionOffset + 1] = this.color.g\n this.colors[positionOffset + 2] = this.color.b\n }\n\n private ensureCapacity(required: number): void {\n if (required <= this.capacity) return\n let capacity = this.capacity\n while (capacity < required) capacity *= 2\n this.capacity = capacity\n\n this.positions = new Float32Array(capacity * 3)\n this.colors = new Float32Array(capacity * 3)\n this.opacities = new Float32Array(capacity)\n this.sizes = new Float32Array(capacity)\n this.angles = new Float32Array(capacity)\n this.instanceMatrix = new THREE.InstancedBufferAttribute(new Float32Array(capacity * 16), 16)\n this.geometry.setAttribute('particleColor', new THREE.InstancedBufferAttribute(this.colors, 3))\n this.geometry.setAttribute('particleOpacity', new THREE.InstancedBufferAttribute(this.opacities, 1))\n }\n\n private updateAttributes(): void {\n const colorAttribute = this.geometry.getAttribute('particleColor')\n const opacityAttribute = this.geometry.getAttribute('particleOpacity')\n colorAttribute.needsUpdate = true\n opacityAttribute.needsUpdate = true\n }\n\n private updateMatrices(): void {\n for (let index = 0; index < this.count; index += 1) {\n const offset = index * 3\n const size = Math.max(0, this.sizes[index])\n this.angleQuaternion.setFromAxisAngle(this.zAxis, this.angles[index])\n this.worldQuaternion.copy(this.localCameraQuaternion).multiply(this.angleQuaternion)\n this.scaleVector.set(size, size, size)\n this.instanceTransform.compose(\n new THREE.Vector3(this.positions[offset], this.positions[offset + 1], this.positions[offset + 2]),\n this.worldQuaternion,\n this.scaleVector,\n )\n this.setMatrixAt(index, this.instanceTransform)\n }\n this.instanceMatrix.needsUpdate = true\n }\n}\n","import type { FireSpreadBounds } from '../typing'\n\n/** 蔓延边界的尺寸信息 */\nexport interface SpreadSize {\n volume: number\n /** 水平面对角线长度 */\n diagonal: number\n}\n\n/** 由蔓延边界算尺寸:火与烟共用 */\nexport const measureSpreadBounds = (bounds: FireSpreadBounds): SpreadSize => {\n const [minX, minY, minZ, maxX, maxY, maxZ] = bounds\n const width = Math.abs(maxX - minX)\n const height = Math.abs(maxY - minY)\n const depth = Math.abs(maxZ - minZ)\n\n return {\n volume: width * height * depth,\n diagonal: Math.sqrt(width * width + depth * depth),\n }\n}\n\n/**\n * 蔓延速度 → 步进间隔与增长率。\n * 速度越快,间隔越短、每次增长越多;火与烟用同一套手感。\n */\nexport const speedToGrowth = (spreadSpeed: number) => {\n const speedMultiplier = Math.max(0.1, Math.min(2.0, spreadSpeed))\n\n return {\n interval: Math.max(200, 1000 / speedMultiplier),\n growthRate: Math.max(0.1, Math.min(0.8, speedMultiplier * 0.3)),\n }\n}\n","import type { FireSpreadBounds } from '../typing'\nimport { SPREAD_COVERAGE_TARGET } from '../constants'\nimport { measureSpreadBounds, speedToGrowth } from '../utils/spread'\nimport type { FireGrowthConfig } from './type'\n\n/**\n * 默认火焰增长配置\n */\nexport const DEFAULT_FIRE_GROWTH_CONFIG: FireGrowthConfig = {\n growthInterval: 2000,\n growthRate: 0.3,\n maxAdditionalFires: 3,\n spreadRange: 2,\n}\n\n/**\n * 由起火区域算火焰蔓延参数。\n */\nexport const buildFireGrowthConfig = (\n bounds: FireSpreadBounds,\n fireSize: number,\n spreadSpeed: number,\n): FireGrowthConfig => {\n const { volume, diagonal } = measureSpreadBounds(bounds)\n const { interval, growthRate } = speedToGrowth(spreadSpeed)\n\n const maxFires = Math.max(12, Math.min(100, Math.round(volume * 1.2)))\n const fireSizeFactor = Math.max(0.3, Math.min(2.0, fireSize))\n const fireSizeMultiplier = Math.max(0.8, Math.min(1.5, fireSize))\n\n return {\n growthInterval: interval,\n growthRate,\n maxAdditionalFires: Math.round(maxFires / fireSizeFactor),\n spreadRange: diagonal * 0.7 * fireSizeMultiplier,\n bounds,\n coverageTarget: SPREAD_COVERAGE_TARGET,\n }\n}\n\n","import * as THREE from 'three/webgpu'\nimport type { FireSpreadBounds } from '../typing'\nimport { MAX_SPREAD_CELLS_PER_STEP } from '../constants'\n\nexport interface RadialSpreadOptions {\n /** 区域包围盒(世界坐标):[minX, minY, minZ, maxX, maxY, maxZ] */\n bounds: FireSpreadBounds\n /** 扩散中心(世界坐标) */\n origin: THREE.Vector3\n /** 噪声种子。同一个 seed 得到同一套布局,火焰用火焰 id,烟雾用烟雾源 id */\n seed: string\n /** 扩散半径上限 */\n spreadRange: number\n /** 增长率,影响每一步的半径推进距离 */\n growthRate: number\n /** 网格边长(米),不传按 1 米 */\n cell?: number\n}\n\nexport interface RadialSpreadCell {\n /** 新铺开的位置,已做抖动,不会排成规则阵列 */\n position: THREE.Vector3\n /** 尺寸抖动系数(0.9~1.1),调用方按需用在实体大小上 */\n scaleJitter: number\n}\n\nexport interface RadialSpreadStepResult {\n /** 这一步新铺开的位置 */\n cells: RadialSpreadCell[]\n /** 当前扩散半径 */\n radius: number\n /** 当前覆盖率(0~1) */\n coverage: number\n}\n\n/**\n * 径向扩散:以某个点为中心、按网格扫描包围盒,每一步只取当前半径环带内的格子。\n */\nexport class RadialSpread {\n private readonly bounds: FireSpreadBounds\n private readonly origin: THREE.Vector3\n private readonly seed: string\n private readonly cell: number\n private readonly spreadRange: number\n private readonly growthRate: number\n\n private readonly coveredCells = new Set<string>()\n private readonly totalCells: number\n private readonly nx: number\n private readonly nz: number\n private currentRadius = 0\n private maxRing = 0\n\n constructor(options: RadialSpreadOptions) {\n this.bounds = options.bounds\n this.origin = options.origin\n this.seed = options.seed\n this.spreadRange = options.spreadRange\n this.growthRate = options.growthRate\n this.cell = Math.max(0.08, options.cell ?? 1)\n\n const [minX, , minZ, maxX, , maxZ] = this.bounds\n this.nx = Math.max(1, Math.ceil((maxX - minX) / this.cell))\n this.nz = Math.max(1, Math.ceil((maxZ - minZ) / this.cell))\n this.totalCells = this.nx * this.nz\n }\n\n /** 当前扩散半径 */\n get radius(): number {\n return this.currentRadius\n }\n\n /** 当前覆盖率(0~1) */\n get coverage(): number {\n return Math.min(1, this.coveredCells.size / Math.max(1, this.totalCells))\n }\n\n step(growthLevel: number, maxNew: number): RadialSpreadStepResult {\n const [minX, , minZ, maxX, , maxZ] = this.bounds\n const base = this.origin\n\n // 半径递增(与增长率相关)\n const stepLength = Math.max(this.cell * 0.35, (this.spreadRange / 28) * Math.max(0.2, this.growthRate))\n this.currentRadius = Math.min(this.spreadRange, this.currentRadius + stepLength)\n\n const cx0 = (base.x - minX) / this.cell - 0.5\n const cz0 = (base.z - minZ) / this.cell - 0.5\n const currentRing = Math.max(0, Math.floor(this.currentRadius / this.cell))\n\n const capacity = Math.max(1, Math.min(MAX_SPREAD_CELLS_PER_STEP, maxNew))\n const cells: RadialSpreadCell[] = []\n\n for (let ix = 0; ix < this.nx; ix++) {\n for (let iz = 0; iz < this.nz; iz++) {\n if (cells.length >= capacity) break\n\n const cx = minX + ix * this.cell + this.cell / 2\n const cz = minZ + iz * this.cell + this.cell / 2\n const key = `${ix}_${iz}`\n\n if (this.coveredCells.has(key)) continue\n\n const ring = Math.max(Math.abs(ix - Math.round(cx0)), Math.abs(iz - Math.round(cz0)))\n if (ring > currentRing || ring < this.maxRing) continue\n\n // 基于噪声的密度控制,避免排布过于规则\n const theta = Math.atan2(cz - base.z, cx - base.x)\n const phase = growthLevel * 0.3\n const density = 0.75 + 0.2 * Math.sin(theta * 3 + phase)\n const noise = rand2(ix, iz, this.seed)\n\n // 邻居已铺开时放宽阈值,保证连续\n const neighborsCovered =\n this.isCovered(ix - 1, iz) ||\n this.isCovered(ix + 1, iz) ||\n this.isCovered(ix, iz - 1) ||\n this.isCovered(ix, iz + 1)\n const threshold = neighborsCovered ? density : Math.max(0.55, density - 0.15)\n if (noise > threshold) continue\n\n // 抖动位置,打破网格对齐\n const jitterRange = this.cell * 0.35\n const jx = (rand2(ix + 13, iz + 7, this.seed) - 0.5) * 2 * jitterRange\n const jz = (rand2(ix + 29, iz + 3, this.seed) - 0.5) * 2 * jitterRange\n\n cells.push({\n position: new THREE.Vector3(cx + jx, base.y, cz + jz),\n scaleJitter: 0.9 + 0.2 * rand2(ix + 5, iz + 11, this.seed),\n })\n this.coveredCells.add(key)\n }\n\n if (cells.length >= capacity) break\n }\n\n if (cells.length < capacity * 0.25) {\n this.maxRing = Math.min(currentRing, this.maxRing + 1)\n }\n\n return { cells, radius: this.currentRadius, coverage: this.coverage }\n }\n\n private isCovered(ix: number, iz: number): boolean {\n return this.coveredCells.has(`${ix}_${iz}`)\n }\n}\n\nfunction rand2(ix: number, iz: number, seed: string): number {\n const s = hashString(seed)\n const x = Math.sin(ix * 12.9898 + iz * 78.233 + s * 0.0001) * 43758.5453\n return x - Math.floor(x)\n}\n\nfunction hashString(str: string): number {\n let h = 2166136261 >>> 0\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i)\n h = Math.imul(h, 16777619)\n }\n return h >>> 0\n}\n","import type { Particle } from '../../shared-utils/rendering/Particle'\n\n/**\n * 释放粒子占用的显存。\n */\nexport const disposeParticle = (particle: Particle): void => {\n particle.parent?.remove(particle)\n particle.dispose()\n}\n","import * as THREE from 'three/webgpu'\nimport { Particle } from '../../../shared-utils/rendering/Particle'\nimport type { FireGrowthConfig, FireData } from '../type'\nimport { DEFAULT_FIRE_GROWTH_CONFIG } from '../config'\nimport { RadialSpread } from '../../utils/radialSpread'\nimport { FADE_STEP_MS, MAX_SPREAD_CELLS_PER_STEP, SPREAD_COVERAGE_TARGET } from '../../constants'\nimport type { ParticleTexture } from '../../utils/particleTexture'\nimport { disposeParticle } from '../../utils/particle'\n\n/**\n * 扩展的火焰配置接口,包含火苗大小\n */\ninterface ExtendedFireConfig extends Partial<FireGrowthConfig> {\n fireSize?: number\n}\n\n/**\n * 火焰管理器\n */\nexport class FireManager {\n private fires: Map<string, FireData> = new Map()\n private scene: THREE.Scene\n private particleTexture: ParticleTexture\n private unsubscribeTexture: () => void\n\n constructor(scene: THREE.Scene, particleTexture: ParticleTexture) {\n this.scene = scene\n this.particleTexture = particleTexture\n this.unsubscribeTexture = particleTexture.onChange((texture) => {\n this.fires.forEach((fireData) => {\n fireData.particles.forEach((particle) => {\n particle.texture = texture\n })\n })\n })\n }\n\n /**\n * 添加火焰\n */\n addFire(id: string, positions: THREE.Vector3[], config?: ExtendedFireConfig) {\n const finalConfig = { ...DEFAULT_FIRE_GROWTH_CONFIG, ...config }\n const fireSize = config?.fireSize || 1\n\n const fireData: FireData = {\n id,\n positions,\n config: finalConfig,\n particles: [],\n growthLevel: 1,\n fireSize,\n }\n\n // 创建初始火焰粒子\n positions.forEach((position, index) => {\n const particle = this.createFireParticle(position, `${id}-${index}`, fireSize)\n fireData.particles.push(particle)\n })\n\n this.fires.set(id, fireData)\n }\n\n /**\n * 创建火焰粒子\n */\n private createFireParticle(position: THREE.Vector3, name: string, scale: number): Particle {\n const particle = new Particle({\n positionBase: new THREE.Vector3(0, 0.01, 0),\n positionStyle: 'SPHERE',\n positionSphereSpread: 0.25 * scale,\n velocityStyle: 'CUBE',\n velocityCubeBase: new THREE.Vector3(0, 0.5 * scale, 0), // 降低向上速度\n velocityCubeSpread: new THREE.Vector3(0.2 * scale, 0.3 * scale, 0.2 * scale), // 减少Y轴随机范围\n texture: this.particleTexture.current,\n sizeTween: {\n times: [0, 0.3, 1.2],\n values: [0.2 * scale, 1.5 * scale, 1 * scale],\n },\n opacityTween: {\n times: [0.9, 1.5],\n values: [1, 0],\n },\n colorTween: {\n times: [0.5, 1.0],\n values: [new THREE.Vector3(0.02, 1, 0.2), new THREE.Vector3(0.05, 1, 0)],\n },\n blending: THREE.AdditiveBlending,\n particlesPerSecond: 30 * scale,\n particleDeathAge: 1.0,\n })\n particle.name = name\n particle.position.copy(position)\n this.scene.add(particle)\n return particle\n }\n\n /**\n * 开始增长\n */\n private startGrowth(fireData: FireData) {\n const { config } = fireData\n\n fireData.growthTimer = setInterval(() => {\n fireData.growthLevel += config.growthRate\n\n // 更新现有火焰参数\n this.refreshFireParams(fireData)\n\n // 火势蔓延\n this.radialExpand(fireData)\n\n // 停止条件:火点数达上限、覆盖率达标、或半径铺到顶\n const firesReached = fireData.particles.length >= config.maxAdditionalFires + fireData.positions.length\n const coverageReached = (fireData.spread?.coverage ?? 0) >= (config.coverageTarget ?? SPREAD_COVERAGE_TARGET)\n const radiusReached = (fireData.spread?.radius ?? 0) >= config.spreadRange\n\n if (firesReached || coverageReached || radiusReached) {\n clearInterval(fireData.growthTimer)\n fireData.growthTimer = null\n }\n }, config.growthInterval)\n }\n\n /**\n * 以起火点为中心,按半径批量扩散\n */\n private radialExpand(fireData: FireData) {\n const { config } = fireData\n if (!config.bounds) return\n\n if (!fireData.spread) {\n fireData.spread = new RadialSpread({\n bounds: config.bounds,\n origin: fireData.positions[0],\n seed: fireData.id,\n spreadRange: config.spreadRange,\n growthRate: config.growthRate,\n cell: Math.max(0.08, fireData.fireSize * 0.7),\n })\n }\n\n const maxNew = Math.max(16, Math.min(MAX_SPREAD_CELLS_PER_STEP, config.maxAdditionalFires))\n const { cells } = fireData.spread.step(fireData.growthLevel, maxNew)\n\n for (const { position, scaleJitter } of cells) {\n const newFire = this.createFireParticle(\n position,\n `${fireData.id}-extra-${fireData.particles.length}`,\n Math.min(1.5, fireData.growthLevel * (fireData.fadeIn ?? 1) * 0.5) * scaleJitter,\n )\n fireData.particles.push(newFire)\n\n // 达到上限则退出\n if (fireData.particles.length >= config.maxAdditionalFires + fireData.positions.length) break\n }\n }\n\n /**\n * 更新火焰参数\n */\n private updateFireParams(particle: Particle, level: number, fireSize: number) {\n const scale = Math.min(3, level) * fireSize\n\n // 调整火焰大小\n if (particle.sizeTween) {\n particle.sizeTween.values[1] = 1.5 * scale\n particle.sizeTween.values[2] = 1 * scale\n }\n\n // 调整粒子产生速率\n particle.particlesPerSecond = Math.min(100, 30 * scale)\n\n // 调整速度 (降低火焰高度)\n particle.velocityCubeBase.y = Math.min(1.5, 0.5 * scale) // 降低最大Y轴速度\n particle.velocityCubeSpread.x = Math.min(0.5, 0.2 * scale)\n particle.velocityCubeSpread.y = Math.min(0.3, 0.3 * scale) // 限制Y轴速度随机范围\n particle.velocityCubeSpread.z = Math.min(0.5, 0.2 * scale)\n }\n\n /** 按当前火势与淡入进度刷新该起火点的所有粒子 */\n private refreshFireParams(fireData: FireData) {\n const level = fireData.growthLevel * (fireData.fadeIn ?? 1)\n fireData.particles.forEach((particle) => this.updateFireParams(particle, level, fireData.fireSize))\n }\n\n /**\n * 移除火焰\n */\n removeFire(id: string) {\n const fireData = this.fires.get(id)\n if (!fireData) return\n\n // 停止增长\n if (fireData.growthTimer) {\n clearInterval(fireData.growthTimer)\n }\n\n // 停止灭火\n if (fireData.extinguishTimer) {\n clearInterval(fireData.extinguishTimer)\n }\n\n // 停止点燃淡入\n if (fireData.fadeInTimer) {\n clearInterval(fireData.fadeInTimer)\n }\n\n // 移除粒子\n fireData.particles.forEach((particle) => {\n disposeParticle(particle)\n })\n\n this.fires.delete(id)\n }\n\n /**\n * 销毁管理器\n */\n destroy() {\n const fireIds = Array.from(this.fires.keys())\n fireIds.forEach((id) => this.removeFire(id))\n\n this.unsubscribeTexture()\n }\n\n /**\n * 开始灭火过程\n */\n startExtinguish(id: string, onComplete?: () => void, extinguishTime = 5000): void {\n const fireData = this.fires.get(id)\n if (!fireData) return\n\n if (fireData.extinguishTimer) {\n clearInterval(fireData.extinguishTimer)\n fireData.extinguishTimer = null\n }\n\n // 停止火焰增长\n if (fireData.growthTimer) {\n clearInterval(fireData.growthTimer)\n fireData.growthTimer = null\n }\n\n // 熄灭优先于淡入\n if (fireData.fadeInTimer) {\n clearInterval(fireData.fadeInTimer)\n fireData.fadeInTimer = null\n }\n fireData.fadeIn = undefined\n\n // 设置灭火参数\n const totalTime = Math.max(1000, Math.min(30000, extinguishTime)) // 限制在1-30秒之间\n const totalSteps = totalTime / FADE_STEP_MS // 总步数\n const extinguishRate = fireData.growthLevel / totalSteps // 每步减少的量\n const extinguishStartTime = Date.now() // 记录开始时间\n\n // 开始灭火定时器\n const extinguishTimer = setInterval(() => {\n // 减少增长级别\n fireData.growthLevel = Math.max(0, fireData.growthLevel - extinguishRate)\n\n // 更新现有火焰参数\n this.refreshFireParams(fireData)\n\n // 逐渐减少粒子产生速率\n fireData.particles.forEach((particle) => {\n const currentRate = particle.particlesPerSecond\n particle.particlesPerSecond = Math.max(0, currentRate - extinguishRate * 10)\n })\n\n // 当增长级别很低时,开始移除火焰粒子\n if (fireData.growthLevel < 0.5 && fireData.particles.length > 0) {\n // 每次移除一个火焰粒子\n const particleToRemove = fireData.particles.pop()\n if (particleToRemove) {\n disposeParticle(particleToRemove)\n }\n }\n\n // 检查是否完全灭火 - 只在真正必要时提前结束,否则按设定时间执行\n const timeElapsed = Date.now() - extinguishStartTime\n const shouldComplete =\n (fireData.growthLevel <= 0.01 && fireData.particles.length === 0) || // 只有完全熄灭才提前结束\n timeElapsed >= totalTime // 或者到达设定时间\n\n if (shouldComplete) {\n clearInterval(extinguishTimer)\n\n // 调用完成回调\n if (onComplete) {\n onComplete()\n }\n }\n }, FADE_STEP_MS)\n\n // 保存灭火定时器引用,以便后续清理\n fireData.extinguishTimer = extinguishTimer\n }\n\n /**\n * 点燃淡入\n */\n startFadeIn(id: string, fadeInTime = 0): void {\n const fireData = this.fires.get(id)\n if (!fireData) return\n\n if (fireData.fadeInTimer) {\n clearInterval(fireData.fadeInTimer)\n fireData.fadeInTimer = null\n }\n\n const totalTime = Math.max(0, fadeInTime)\n if (totalTime === 0) return\n\n const totalSteps = Math.max(1, Math.round(totalTime / FADE_STEP_MS))\n let step = 0\n\n fireData.fadeIn = 0\n this.refreshFireParams(fireData)\n\n fireData.fadeInTimer = setInterval(() => {\n step += 1\n\n if (step >= totalSteps) {\n clearInterval(fireData.fadeInTimer)\n fireData.fadeInTimer = null\n fireData.fadeIn = undefined\n this.refreshFireParams(fireData)\n return\n }\n\n fireData.fadeIn = step / totalSteps\n this.refreshFireParams(fireData)\n }, FADE_STEP_MS)\n }\n\n /**\n * 停止灭火过程\n */\n stopExtinguish(id: string): void {\n const fireData = this.fires.get(id)\n if (!fireData || !fireData.extinguishTimer) return\n\n // 停止灭火定时器\n clearInterval(fireData.extinguishTimer)\n fireData.extinguishTimer = null\n }\n\n /**\n * 合并配置并重启增长定时器\n */\n updateFireConfig(id: string, newConfig: ExtendedFireConfig) {\n const fireData = this.fires.get(id)\n if (!fireData) return\n\n // 更新配置\n fireData.config = { ...fireData.config, ...newConfig }\n\n // 重新开始增长:重复调用时先收掉上一次的定时器\n if (fireData.growthTimer) {\n clearInterval(fireData.growthTimer)\n fireData.growthTimer = null\n }\n this.startGrowth(fireData)\n }\n\n /**\n * 移动单个火焰的基础位置\n */\n moveFire(id: string, newBasePosition: THREE.Vector3) {\n const fireData = this.fires.get(id)\n if (!fireData) return\n\n const oldBase = fireData.positions[0]\n if (!oldBase) return\n\n const delta = new THREE.Vector3().subVectors(newBasePosition, oldBase)\n\n // 更新基础位置\n fireData.positions[0].copy(newBasePosition)\n\n // 平移所有粒子\n fireData.particles.forEach((particle) => {\n particle.position.add(delta)\n })\n }\n\n /**\n * 设置指定火焰的透明度\n * @param id 火焰ID\n * @param opacity 透明度 (0-1)\n */\n setFireOpacity(id: string, opacity: number): void {\n const fireData = this.fires.get(id)\n if (!fireData) return\n\n // 遍历该火焰的所有粒子,通过修改 opacityTween 来控制透明度\n fireData.particles.forEach((particle) => {\n if (particle.opacityTween) {\n // 修改 opacityTween 的 values,将最大透明度设为目标值\n // 原始值通常是 [1, 0],修改后变为 [opacity, 0]\n particle.opacityTween.values = [opacity, 0]\n }\n })\n }\n}\n","import * as THREE from 'three/webgpu'\nimport { Particle } from '../../../shared-utils/rendering/Particle'\nimport type { SmokeConfig } from './SmokeManager'\nimport type { ParticleTexture } from '../../utils/particleTexture'\nimport { disposeParticle } from '../../utils/particle'\nimport { FADE_STEP_MS } from '../../constants'\n\n/**\n * 烟雾源信息\n */\ninterface SmokeSource {\n id: string\n particle: Particle\n /** 渐显定时器 */\n fadeInTimer?: ReturnType<typeof setInterval>\n}\n\n/**\n * 普通烟雾管理器\n * 管理传统的向上飘散烟雾效果\n */\nexport class NormalSmokeManager {\n private scene: THREE.Scene\n private config: SmokeConfig\n private sources: Map<string, SmokeSource> = new Map()\n private particleTexture: ParticleTexture\n private unsubscribeTexture: () => void\n\n constructor(scene: THREE.Scene, config: SmokeConfig, particleTexture: ParticleTexture) {\n this.scene = scene\n this.config = config\n this.particleTexture = particleTexture\n this.unsubscribeTexture = particleTexture.onChange((texture) => {\n this.sources.forEach((source) => {\n source.particle.texture = texture\n })\n })\n }\n\n /**\n * 添加烟雾源\n */\n addSource(id: string, position: THREE.Vector3, intensity: number, fadeInMs = 0) {\n const particle = this.createNormalSmoke(position, id, intensity)\n const source: SmokeSource = { id, particle }\n this.sources.set(id, source)\n\n if (fadeInMs > 0) this.fadeInSource(source, intensity, fadeInMs)\n }\n\n /** 渐显:在 durationMs 内把浓度从 0 涨到目标值 */\n private fadeInSource(source: SmokeSource, targetIntensity: number, durationMs: number) {\n const steps = Math.max(1, Math.round(durationMs / FADE_STEP_MS))\n let step = 0\n\n this.updateSourceIntensity(source.id, 0)\n source.fadeInTimer = setInterval(() => {\n step += 1\n\n if (step >= steps) {\n clearInterval(source.fadeInTimer)\n source.fadeInTimer = undefined\n this.updateSourceIntensity(source.id, targetIntensity)\n return\n }\n\n this.updateSourceIntensity(source.id, targetIntensity * (step / steps))\n }, FADE_STEP_MS)\n }\n\n /**\n * 平移某个烟雾源的粒子\n */\n moveSource(id: string, delta: THREE.Vector3) {\n this.sources.get(id)?.particle.position.add(delta)\n }\n\n /**\n * 更新烟雾源强度\n */\n updateSourceIntensity(id: string, intensity: number) {\n const source = this.sources.get(id)\n if (!source) return\n\n this.updateNormalSmokeParams(source.particle, intensity)\n }\n\n /**\n * 移除烟雾源\n */\n removeSource(id: string) {\n const source = this.sources.get(id)\n if (!source) return\n\n // 清理渐显定时器和粒子\n if (source.fadeInTimer) clearInterval(source.fadeInTimer)\n disposeParticle(source.particle)\n this.sources.delete(id)\n }\n\n /**\n * 创建普通烟雾粒子\n */\n private createNormalSmoke(position: THREE.Vector3, id: string, intensity: number): Particle {\n const scale = intensity * this.config.densityMultiplier\n const smokePosition = position.clone()\n // 确保烟雾在火焰上方,增加基础偏移让烟雾在更高位置产生\n smokePosition.y += 0.3 + this.config.heightOffset * intensity\n\n const particle = new Particle({\n positionBase: new THREE.Vector3(0, 0.05, 0), // 减少基础高度偏移,让烟雾更贴近火焰\n positionCubeSpread: new THREE.Vector3(\n 0.5 * scale * this.config.spreadMultiplier,\n 0.05 * scale,\n 0.5 * scale * this.config.spreadMultiplier,\n ),\n\n velocityStyle: 'CUBE',\n velocityCubeBase: new THREE.Vector3(0, 0.4 * scale * Math.max(Math.random(), 0.6), 0.05),\n velocityCubeSpread: new THREE.Vector3(\n 0.8 * scale * this.config.spreadMultiplier,\n 0.2 * scale * this.config.spreadMultiplier * Math.max(Math.random(), 0.4),\n 0.8 * scale * this.config.spreadMultiplier,\n ),\n accelerationBase: new THREE.Vector3(0, 0.1, 0.02), // 恢复向上加速度,让烟雾向上升腾\n\n texture: this.particleTexture.current,\n blending: THREE.NormalBlending, // 使用正常混合模式,避免颜色异常\n\n angleBase: 0,\n angleSpread: (720 / 180) * Math.PI,\n angleVelocityBase: 0,\n angleVelocitySpread: (360 / 180) * Math.PI,\n\n sizeTween: {\n times: [0, 1, 2, 3, 4, 6],\n // 尺寸随浓度等比缩放\n values: [0.4, 1.0, 1.6, 2.0, 1.6, 0.8].map((value) => value * intensity),\n },\n opacityTween: {\n times: [0, 1, 2, 3, 4, 6],\n // 峰值透明度 0.45\n values: [0.15, 0.3, 0.45, 0.3, 0.15, 0],\n },\n colorTween: {\n // 黑色浓烟\n times: [0.3, 1.5],\n values: [new THREE.Vector3(0.2, 0.2, 0.2), new THREE.Vector3(0.05, 0.05, 0.05)],\n },\n // 速率与浓度等比,基准 30/秒(创建与更新同一基准)\n particlesPerSecond: 30 * intensity,\n particleDeathAge: 6,\n })\n\n particle.name = id\n particle.position.copy(smokePosition)\n this.scene.add(particle)\n return particle\n }\n\n /**\n * 更新普通烟雾参数\n */\n private updateNormalSmokeParams(particle: Particle, intensity: number) {\n const scale = intensity * this.config.densityMultiplier\n\n // 按浓度等比缩放密度\n particle.particlesPerSecond = Math.floor(30 * intensity)\n\n // 动态调整烟雾上升速度\n particle.velocityCubeBase.y = Math.min(2.0, 0.6 * scale)\n\n // 动态调整烟雾扩散范围\n const spreadFactor = Math.min(3, scale * this.config.spreadMultiplier)\n particle.velocityCubeSpread.x = 0.8 * spreadFactor\n particle.velocityCubeSpread.z = 0.8 * spreadFactor\n\n // 动态调整烟雾初始扩散位置\n particle.positionCubeSpread.x = 0.3 * spreadFactor\n particle.positionCubeSpread.z = 0.3 * spreadFactor\n }\n\n /**\n * 清理所有烟雾\n */\n clearAll() {\n const sourceIds = Array.from(this.sources.keys())\n sourceIds.forEach((id) => this.removeSource(id))\n }\n\n /**\n * 销毁管理器\n */\n destroy() {\n this.clearAll()\n this.unsubscribeTexture()\n }\n}\n","import * as THREE from 'three/webgpu'\nimport type { FireSpreadBounds } from '../../typing'\nimport { RadialSpread } from '../../utils/radialSpread'\nimport type { ParticleTexture } from '../../utils/particleTexture'\nimport { SPREAD_COVERAGE_TARGET } from '../../constants'\nimport { NormalSmokeManager } from './NormalSmokeManager'\n\n/**\n * 烟雾配置接口\n */\nexport interface SmokeConfig {\n /** 密度倍数 */\n densityMultiplier: number\n /** 高度偏移 */\n heightOffset: number\n /** 扩散倍数 */\n spreadMultiplier: number\n}\n\n/**\n * 烟雾源信息\n */\ninterface SmokeSource {\n id: string\n position: THREE.Vector3\n intensity: number\n}\n\n/**\n * 烟雾扩散参数\n */\nexport interface SmokeSpreadOptions {\n /** 扩散边界(世界坐标):`[minX, minY, minZ, maxX, maxY, maxZ]` */\n bounds: FireSpreadBounds\n /** 扩散半径上限 */\n spreadRange: number\n /** 每次步进的强度增长,决定半径推进的快慢 */\n growthRate: number\n /** 步进间隔(毫秒) */\n interval: number\n /** 扩散源数量上限(不含主源) */\n maxAdditional: number\n /** 扩散源的浓度 */\n intensity: number\n /** 扩散源的渐显时长(毫秒) */\n fadeInMs?: number\n /** 网格边长(米),不传按 1 米 */\n cell?: number\n}\n\n/** 扩散过程中的运行时状态 */\ninterface SmokeSpreadState {\n spread: RadialSpread\n timer: ReturnType<typeof setInterval>\n /** 已生成的扩散源 id,按生成顺序 */\n derivedIds: string[]\n options: SmokeSpreadOptions\n growthLevel: number\n}\n\n/**\n * 烟雾管理器\n *\n * 维护「有哪些烟源」的记录,具体粒子交给 {@link NormalSmokeManager}。\n */\nexport class SmokeManager {\n private sources: Map<string, SmokeSource> = new Map()\n /** 正在扩散的烟雾源,key = 主源 id */\n private spreads: Map<string, SmokeSpreadState> = new Map()\n private normalSmoke: NormalSmokeManager\n\n constructor(scene: THREE.Scene, config: SmokeConfig, particleTexture: ParticleTexture) {\n this.normalSmoke = new NormalSmokeManager(scene, config, particleTexture)\n }\n\n /**\n * 添加烟雾源\n */\n addSource(id: string, position: THREE.Vector3, intensity: number = 1, fadeInMs = 0) {\n const source: SmokeSource = { id, position, intensity }\n this.sources.set(id, source)\n this.normalSmoke.addSource(id, position, intensity, fadeInMs)\n }\n\n /**\n * 让某个烟雾源在给定区域内扩散。\n */\n spreadSmoke(id: string, options: SmokeSpreadOptions) {\n const previous = this.spreads.get(id)\n this.stopSmokeSpread(id)\n\n const source = this.sources.get(id)\n if (!source) return\n\n const spread = new RadialSpread({\n bounds: options.bounds,\n origin: source.position,\n seed: id,\n spreadRange: options.spreadRange,\n growthRate: options.growthRate,\n cell: options.cell,\n })\n\n this.spreads.set(id, {\n spread,\n timer: setInterval(() => this.stepSpread(id), options.interval),\n // 重复扩散时接着上次的编号,避免和已存在的扩散源撞 id\n derivedIds: previous?.derivedIds ?? [],\n options,\n growthLevel: 1,\n })\n }\n\n /** 停止扩散(已经生成的扩散源保留) */\n stopSmokeSpread(id: string) {\n const state = this.spreads.get(id)\n if (!state) return\n\n clearInterval(state.timer)\n }\n\n /** 扩散产生的烟雾源 id */\n getSpreadSourceIds(id: string): string[] {\n return this.spreads.get(id)?.derivedIds ?? []\n }\n\n /** 走一步扩散:在区域内新铺开若干个烟雾源 */\n private stepSpread(id: string) {\n const state = this.spreads.get(id)\n if (!state) return\n\n const { options } = state\n state.growthLevel += options.growthRate\n\n const { cells, coverage } = state.spread.step(state.growthLevel, options.maxAdditional)\n\n for (const { position, scaleJitter } of cells) {\n if (state.derivedIds.length >= options.maxAdditional) break\n\n const derivedId = `${id}-spread-${state.derivedIds.length}`\n this.addSource(derivedId, position, options.intensity * scaleJitter, options.fadeInMs ?? 0)\n state.derivedIds.push(derivedId)\n }\n\n if (state.derivedIds.length >= options.maxAdditional || coverage >= SPREAD_COVERAGE_TARGET) {\n this.stopSmokeSpread(id)\n }\n }\n\n /**\n * 平移某个烟雾源。\n */\n moveSource(id: string, position: THREE.Vector3) {\n const source = this.sources.get(id)\n if (!source) return\n\n const delta = new THREE.Vector3().subVectors(position, source.position)\n source.position.copy(position)\n this.normalSmoke.moveSource(id, delta)\n\n this.spreads.get(id)?.derivedIds.forEach((derivedId) => {\n const derived = this.sources.get(derivedId)\n if (!derived) return\n derived.position.add(delta)\n this.normalSmoke.moveSource(derivedId, delta)\n })\n }\n\n /**\n * 更新烟雾源强度\n */\n updateSourceIntensity(id: string, intensity: number) {\n const source = this.sources.get(id)\n if (!source) return\n\n source.intensity = intensity\n this.normalSmoke.updateSourceIntensity(id, intensity)\n }\n\n /**\n * 移除烟雾源\n */\n removeSource(id: string) {\n const source = this.sources.get(id)\n if (!source) return\n\n // 移除的是主源时,连带清掉它扩散出来的源和定时器\n const spreadState = this.spreads.get(id)\n if (spreadState) {\n this.stopSmokeSpread(id)\n this.spreads.delete(id)\n spreadState.derivedIds.forEach((derivedId) => this.removeSource(derivedId))\n }\n\n this.normalSmoke.removeSource(id)\n this.sources.delete(id)\n }\n\n /**\n * 清理所有烟雾\n */\n clearAll() {\n // 扩散定时器先停掉,否则清空之后还会继续往场景里加源\n this.spreads.forEach((state) => clearInterval(state.timer))\n this.spreads.clear()\n\n this.normalSmoke.clearAll()\n this.sources.clear()\n }\n\n /**\n * 销毁管理器\n */\n destroy() {\n this.clearAll()\n this.normalSmoke.destroy()\n }\n\n /**\n * 获取某个烟雾源的当前浓度\n */\n getSourceIntensity(id: string): number {\n return this.sources.get(id)?.intensity ?? 0\n }\n\n /**\n * 获取烟雾源数量\n */\n getSourceCount(): number {\n return this.sources.size\n }\n}\n","import type { FireSpreadBounds } from '../typing'\nimport type { SmokeSpreadOptions } from './managers/SmokeManager'\nimport { measureSpreadBounds, speedToGrowth } from '../utils/spread'\n\n/** 扩散出来的烟雾源的渐显时长(毫秒) */\nexport const SMOKE_SPREAD_FADE_IN_MS = 1000\n\n/**\n * 由起火区域算烟雾蔓延参数。\n */\nexport const buildSmokeSpreadConfig = (\n bounds: FireSpreadBounds,\n intensity: number,\n spreadSpeed: number,\n): SmokeSpreadOptions => {\n const { volume, diagonal } = measureSpreadBounds(bounds)\n const { interval, growthRate } = speedToGrowth(spreadSpeed)\n\n const maxSources = Math.max(4, Math.min(24, Math.round(volume * 0.35)))\n const intensityFactor = Math.max(0.5, Math.min(2.0, intensity))\n\n return {\n bounds,\n interval,\n growthRate,\n spreadRange: diagonal * 0.7,\n maxAdditional: Math.round(maxSources / intensityFactor),\n intensity,\n fadeInMs: SMOKE_SPREAD_FADE_IN_MS,\n cell: Math.max(0.5, diagonal / 8),\n }\n}\n","import type * as THREE from 'three/webgpu'\nimport { loadTexture } from './loadTexture'\n\n/** 贴图加载器,用于满足资源共用 */\nexport function getTextureLoader() {\n const cache = new Map<string, Promise<THREE.Texture>>()\n\n const load = function (url: string): Promise<THREE.Texture> {\n if (cache.has(url)) return cache.get(url)!\n const texturePromise = loadTexture(url)\n cache.set(url, texturePromise)\n return texturePromise\n }\n\n const dispose = function () {\n cache.forEach((texturePromise) => texturePromise.then((texture) => texture.dispose()))\n cache.clear()\n }\n\n return { load, dispose }\n}\n","import type * as THREE from 'three/webgpu'\nimport { getTextureLoader } from '../../shared-utils/three/getTextureLoader'\n\ntype TextureListener = (texture: THREE.Texture | null) => void\n\n/**\n * 火焰、烟雾、喷水共用的粒子贴图。\n */\nexport class ParticleTexture {\n private loader = getTextureLoader()\n private url = ''\n private texture: THREE.Texture | null = null\n private listeners = new Set<TextureListener>()\n\n /** 当前贴图。加载完成前为 null */\n public get current(): THREE.Texture | null {\n return this.texture\n }\n\n public setUrl(url: string): void {\n if (url === this.url) return\n\n this.url = url\n this.texture = null\n this.emit()\n\n if (!url) return\n void this.loader.load(url).then((texture) => {\n // 加载期间 URL 又变了,这次结果作废\n if (url !== this.url) return\n this.texture = texture\n this.emit()\n })\n }\n\n /**\n * 订阅贴图变化(含清空),返回取消订阅的函数。\n */\n public onChange(listener: TextureListener): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n public dispose(): void {\n this.listeners.clear()\n this.texture = null\n this.url = ''\n this.loader.dispose()\n }\n\n private emit(): void {\n this.listeners.forEach((listener) => listener(this.texture))\n }\n}\n","import type { Five } from '@realsee/five-webgpu'\nimport * as THREE from 'three/webgpu'\nimport { FireManager } from './fire'\nimport { buildFireGrowthConfig } from './fire/config'\nimport type { SmokeConfig } from './smoke'\nimport { SmokeManager } from './smoke'\nimport { buildSmokeSpreadConfig } from './smoke/config'\nimport type { FireSpreadBounds } from './typing'\nimport { FADE_STEP_MS, MODEL_SCALE_RANGE } from './constants'\nimport { Particle } from '../shared-utils/rendering/Particle'\nimport { disposeParticle } from './utils/particle'\nimport { ParticleTexture } from './utils/particleTexture'\nimport loadGLTF from '../shared-utils/three/GLTFLoader'\nimport { transformPosition } from '../shared-utils/five/transformPosition'\nimport { lookObject } from '../shared-utils/five/lookObject'\nimport { WorkUtil } from '../shared-utils/Utils/WorkUtil'\n\n/**\n * 烟雾的渲染参数。\n */\nconst SMOKE_RENDER_CONFIG: SmokeConfig = {\n densityMultiplier: 0.2,\n heightOffset: 0.2,\n spreadMultiplier: 4.5,\n}\n\n/** 把模型尺寸限制在允许范围 */\nconst clampModelScale = (value: number) => THREE.MathUtils.clamp(value, MODEL_SCALE_RANGE.min, MODEL_SCALE_RANGE.max)\n\ninterface FireEntry {\n /** 世界坐标 */\n position: THREE.Vector3\n /** 火苗大小 */\n size: number\n /** 所属楼层,用于按楼层控制可见性 */\n floorIndex?: number\n /** 蔓延边界。已点燃(开始蔓延)时才有值 */\n spreadBounds?: FireSpreadBounds\n /** 蔓延速度 */\n spreadSpeed?: number\n}\n\ninterface SmokeEntry {\n /** 世界坐标 */\n position: THREE.Vector3\n /** 渐隐定时器 */\n dissipateTimer?: ReturnType<typeof setInterval>\n}\n\ninterface FirefighterEntry {\n scene: THREE.Object3D\n particle?: Particle | null\n dispose: () => void\n}\n\n/**\n * 消防演绎的三维实体控制器\n * 管理三类实体:火、烟、消防员\n */\nexport class FireControl {\n readonly five: Five\n\n private fireManager: FireManager | null = null\n private smokeManager: SmokeManager | null = null\n\n /** 已添加的起火点 */\n private fires: Map<string, FireEntry> = new Map()\n /** 已添加的烟雾*/\n private smokes: Map<string, SmokeEntry> = new Map()\n /** 已添加的消防员 */\n private firefighters: Map<string, FirefighterEntry> = new Map()\n /** 消防员加载代次,用于丢弃加载期间已经失效的结果 */\n private firefighterTokens: Map<string, number> = new Map()\n\n /** 粒子贴图 */\n private particleTexture = new ParticleTexture()\n private unsubscribeTexture: () => void\n\n private resourceConfig = {\n waterGunModelUrl: '',\n /** 粒子贴图。火焰、烟雾、喷水三种粒子共用同一张 */\n particleTextureUrl: '',\n }\n private resourceConfigResolvers: { check: () => boolean; resolve: () => void }[] = []\n\n private disposed = false\n private workUtil: WorkUtil\n\n constructor(five: Five) {\n this.five = five\n five.on('dispose', this.dispose)\n this.workUtil = new WorkUtil(five)\n this.unsubscribeTexture = this.particleTexture.onChange((texture) => {\n this.firefighters.forEach((entry) => {\n if (entry.particle) entry.particle.texture = texture\n })\n })\n }\n\n public set workCode(workCode: string) {\n this.workUtil.workCode = workCode\n }\n\n public get workCode() {\n return this.workUtil.workCode\n }\n\n /** 粒子贴图是否已配置 */\n public get hasParticleTexture(): boolean {\n return Boolean(this.resourceConfig.particleTextureUrl)\n }\n\n /** 消防员模型 URL 是否已配置 */\n public get hasWaterGunModel(): boolean {\n return Boolean(this.resourceConfig.waterGunModelUrl)\n }\n\n /** 更新资源配置 */\n public updateResourceConfig(config: { waterGunObj?: string; particleTexture?: string }): void {\n const nextWaterGun = config.waterGunObj?.trim()\n const nextParticle = config.particleTexture?.trim()\n\n if (nextWaterGun) {\n this.resourceConfig.waterGunModelUrl = nextWaterGun\n }\n\n if (nextParticle && nextParticle !== this.resourceConfig.particleTextureUrl) {\n this.resourceConfig.particleTextureUrl = nextParticle\n this.particleTexture.setUrl(nextParticle)\n }\n\n this.resourceConfigResolvers = this.resourceConfigResolvers.filter((resolver) => {\n if (!resolver.check()) return true\n resolver.resolve()\n return false\n })\n }\n\n /**\n * 等待某项资源配置就位\n */\n public waitForResourceConfig(kind: 'particle' | 'firefighter'): Promise<void> {\n const check = kind === 'particle' ? () => this.hasParticleTexture : () => this.hasWaterGunModel\n if (check()) return Promise.resolve()\n return new Promise((resolve) => this.resourceConfigResolvers.push({ check, resolve }))\n }\n\n /**\n * 添加一个起火点\n */\n public addFire(\n id: string,\n position: [number, number, number],\n options?: { size?: number; floorIndex?: number; fadeInMs?: number },\n ): void {\n const size = clampModelScale(options?.size ?? 1)\n const worldPosition = this.toWorld(new THREE.Vector3(position[0], position[1], position[2]))\n\n if (this.fires.has(id)) this.removeFire(id)\n\n this.ensureFireManager().addFire(id, [worldPosition], { fireSize: size })\n if (options?.fadeInMs) this.fireManager?.startFadeIn(id, options.fadeInMs)\n this.fires.set(id, { position: worldPosition, size, floorIndex: options?.floorIndex })\n this.five.needsRender = true\n }\n\n /**\n * 让指定起火点开始在给定区域内蔓延。\n */\n public igniteFire(id: string, bounds: FireSpreadBounds, options?: { spreadSpeed?: number }): void {\n const entry = this.fires.get(id)\n if (!entry || !this.fireManager) return\n\n const spreadSpeed = options?.spreadSpeed ?? 1.0\n const worldBounds = this.toWorldBounds(bounds)\n entry.spreadBounds = bounds\n entry.spreadSpeed = spreadSpeed\n\n this.fireManager.updateFireConfig(id, {\n ...buildFireGrowthConfig(worldBounds, entry.size, spreadSpeed),\n fireSize: entry.size,\n })\n this.five.needsRender = true\n }\n\n /** 熄灭:渐进减少火点直到完全消失 */\n public extinguishFire(id: string, options?: { duration?: number; onComplete?: () => void }): void {\n if (!this.fires.has(id) || !this.fireManager) return\n\n this.fireManager.startExtinguish(id, options?.onComplete, options?.duration ?? 5000)\n }\n\n /** 停止熄灭过程 */\n public stopExtinguishFire(id: string): void {\n if (!this.fires.has(id) || !this.fireManager) return\n\n this.fireManager.stopExtinguish(id)\n }\n\n /**\n * 移动起火点\n */\n public moveFire(id: string, position: [number, number, number]): void {\n const entry = this.fires.get(id)\n if (!entry || !this.fireManager) return\n\n const worldPosition = this.toWorld(new THREE.Vector3(position[0], position[1], position[2]))\n entry.position = worldPosition\n this.fireManager.moveFire(id, worldPosition)\n this.five.needsRender = true\n }\n\n /**\n * 缩放起火点\n */\n public scaleFire(id: string, size: number): void {\n const entry = this.fires.get(id)\n if (!entry) return\n\n const { position, floorIndex, spreadBounds, spreadSpeed } = entry\n const nextSize = clampModelScale(size)\n\n this.fireManager?.removeFire(id)\n this.ensureFireManager().addFire(id, [position], { fireSize: nextSize })\n this.fires.set(id, { position, size: nextSize, floorIndex, spreadBounds, spreadSpeed })\n\n if (spreadBounds) this.igniteFire(id, spreadBounds, { spreadSpeed })\n this.five.needsRender = true\n }\n\n /** 移除起火点 */\n public removeFire(id: string): void {\n if (!this.fires.has(id)) return\n\n this.fireManager?.removeFire(id)\n this.fires.delete(id)\n this.five.needsRender = true\n }\n\n /**\n * 按楼层控制起火点的可见性\n */\n public changeFireVisibleByFloorIndex(floorIndex: number | null): void {\n if (!this.fireManager) return\n\n this.fires.forEach((entry, id) => {\n const visible = floorIndex === null || entry.floorIndex === undefined || entry.floorIndex === floorIndex\n this.fireManager!.setFireOpacity(id, visible ? 1.0 : 0.1)\n })\n this.five.needsRender = true\n }\n\n\n /**\n * 添加烟雾。\n */\n public addSmoke(\n id: string,\n position: [number, number, number],\n options?: { intensity?: number; fadeInMs?: number },\n ): void {\n const smokeManager = this.ensureSmokeManager()\n\n const intensity = clampModelScale(options?.intensity ?? 1)\n const worldPosition = this.toWorld(new THREE.Vector3(position[0], position[1], position[2]))\n\n if (this.smokes.has(id)) this.removeSmoke(id)\n\n smokeManager.addSource(id, worldPosition, intensity, options?.fadeInMs ?? 0)\n this.smokes.set(id, { position: worldPosition })\n this.five.needsRender = true\n }\n\n /**\n * 让烟雾在所属区域内扩散\n */\n public spreadSmoke(id: string, bounds: FireSpreadBounds, options?: { spreadSpeed?: number }): void {\n const entry = this.smokes.get(id)\n const smokeManager = this.smokeManager\n if (!entry || !smokeManager) return\n\n const worldBounds = this.toWorldBounds(bounds)\n const intensity = smokeManager.getSourceIntensity(id)\n smokeManager.spreadSmoke(id, buildSmokeSpreadConfig(worldBounds, intensity, options?.spreadSpeed ?? 1.0))\n }\n\n /**\n * 移动烟雾。\n */\n public moveSmoke(id: string, position: [number, number, number]): void {\n const entry = this.smokes.get(id)\n const smokeManager = this.smokeManager\n if (!entry || !smokeManager) return\n\n const worldPosition = this.toWorld(new THREE.Vector3(position[0], position[1], position[2]))\n entry.position = worldPosition\n smokeManager.moveSource(id, worldPosition)\n this.five.needsRender = true\n }\n\n /**\n * 缩放烟雾\n */\n public scaleSmoke(id: string, size: number): void {\n const entry = this.smokes.get(id)\n const smokeManager = this.smokeManager\n if (!entry || !smokeManager) return\n\n smokeManager.updateSourceIntensity(id, clampModelScale(size))\n this.five.needsRender = true\n }\n\n /**\n * 烟雾渐隐并移除。\n */\n public dissipateSmoke(id: string, options?: { duration?: number; onComplete?: () => void }): void {\n const entry = this.smokes.get(id)\n const smokeManager = this.smokeManager\n if (!entry || !smokeManager) return\n\n if (entry.dissipateTimer) clearInterval(entry.dissipateTimer)\n\n // 停止扩散:已经进入消失阶段,再往外铺新源会让烟雾越灭越多\n smokeManager.stopSmokeSpread(id)\n\n const sourceIds = [id, ...smokeManager.getSpreadSourceIds(id)]\n const startIntensities = new Map(sourceIds.map((sourceId) => [sourceId, smokeManager.getSourceIntensity(sourceId)]))\n const steps = Math.max(1, Math.round((options?.duration ?? 3000) / FADE_STEP_MS))\n let step = 0\n\n entry.dissipateTimer = setInterval(() => {\n step += 1\n if (step >= steps) {\n this.removeSmoke(id)\n options?.onComplete?.()\n return\n }\n startIntensities.forEach((startIntensity, sourceId) => {\n smokeManager.updateSourceIntensity(sourceId, startIntensity * (1 - step / steps))\n })\n this.five.needsRender = true\n }, FADE_STEP_MS)\n }\n\n /**\n * 停止消散\n */\n public stopDissipateSmoke(id: string): void {\n const entry = this.smokes.get(id)\n if (!entry) return\n\n if (entry.dissipateTimer) {\n clearInterval(entry.dissipateTimer)\n entry.dissipateTimer = undefined\n this.five.needsRender = true\n }\n }\n\n /** 移除烟雾 */\n public removeSmoke(id: string): void {\n const entry = this.smokes.get(id)\n if (!entry) return\n\n if (entry.dissipateTimer) clearInterval(entry.dissipateTimer)\n this.smokeManager?.removeSource(id)\n this.smokes.delete(id)\n this.five.needsRender = true\n }\n\n\n /**\n * 添加消防员。\n */\n public async addFirefighter(options: {\n id: string\n position: [number, number, number]\n rotation: THREE.Euler\n /** 是否喷水 */\n spray?: boolean\n /** 等比缩放 */\n scale?: number\n }): Promise<void> {\n const { id, position, rotation, spray = false, scale = 1 } = options\n if (!this.resourceConfig.waterGunModelUrl) {\n throw new Error('消防员模型未配置,请先调用 updateResourceConfig 设置 waterGunObj')\n }\n\n if (this.firefighters.has(id)) this.removeFirefighter(id)\n this.invalidateFirefighter(id)\n const token = this.firefighterTokens.get(id)\n\n const worldPosition = this.toWorld(new THREE.Vector3(position[0], position[1], position[2]))\n const result = await loadGLTF(this.resourceConfig.waterGunModelUrl)\n if (this.firefighterTokens.get(id) !== token) {\n result.dispose()\n return\n }\n\n const scene = result.scene\n scene.scale.setScalar(clampModelScale(scale))\n scene.rotation.copy(rotation)\n scene.position.copy(worldPosition)\n scene.name = id\n this.five.scene.add(scene)\n\n let particle: Particle | null = null\n if (spray) {\n particle = this.createSprayParticle(id)\n scene.add(particle)\n }\n\n this.firefighters.set(id, { scene, particle, dispose: result.dispose })\n this.five.needsRender = true\n }\n\n private invalidateFirefighter(id: string): void {\n this.firefighterTokens.set(id, (this.firefighterTokens.get(id) ?? 0) + 1)\n }\n\n /**\n * 把相机移到某个实体上(以最佳视角观察它)。\n */\n public async focusEntity(id: string, options?: { scale?: number }): Promise<void> {\n const firefighter = this.firefighters.get(id)\n if (firefighter) {\n await lookObject(this.five, firefighter.scene, options)\n return\n }\n\n const fire = this.fires.get(id)\n const smoke = this.smokes.get(id)\n const position = fire?.position ?? smoke?.position\n if (!position) return\n\n const entitySize = fire?.size ?? (smoke ? this.smokeManager?.getSourceIntensity(id) ?? 1 : 1)\n const boxSize = Math.max(entitySize, 3)\n const placeholder = new THREE.Mesh(new THREE.BoxGeometry(boxSize, boxSize, boxSize))\n placeholder.visible = false\n placeholder.position.copy(position)\n this.five.scene.add(placeholder)\n try {\n await lookObject(this.five, placeholder, options)\n } finally {\n this.five.scene.remove(placeholder)\n placeholder.geometry.dispose()\n }\n }\n\n /** 移除消防员 */\n public removeFirefighter(id?: string): void {\n if (id === undefined) {\n Array.from(this.firefighterTokens.keys()).forEach((key) => this.invalidateFirefighter(key))\n Array.from(this.firefighters.keys()).forEach((key) => this.removeFirefighter(key))\n return\n }\n\n this.invalidateFirefighter(id)\n const entry = this.firefighters.get(id)\n if (!entry) return\n\n // 喷水粒子由引擎创建,先单独释放\n if (entry.particle) disposeParticle(entry.particle)\n this.five.scene.remove(entry.scene)\n entry.dispose()\n this.firefighters.delete(id)\n this.five.needsRender = true\n }\n\n /** 清空所有实体,保留管理器与资源配置 */\n public clearAll(): void {\n this.fires.forEach((_, id) => this.fireManager?.removeFire(id))\n this.fires.clear()\n\n this.smokes.forEach((entry) => entry.dissipateTimer && clearInterval(entry.dissipateTimer))\n this.smokes.clear()\n this.smokeManager?.clearAll()\n\n this.removeFirefighter()\n this.five.needsRender = true\n }\n\n /** 销毁控制器 */\n public dispose = (): void => {\n if (this.disposed) return\n this.disposed = true\n this.five.off('dispose', this.dispose)\n this.clearAll()\n\n this.fireManager?.destroy()\n this.fireManager = null\n\n this.smokeManager?.destroy()\n this.smokeManager = null\n\n this.unsubscribeTexture()\n this.particleTexture.dispose()\n this.firefighterTokens.clear()\n\n const pending = this.resourceConfigResolvers\n this.resourceConfigResolvers = []\n pending.forEach((resolver) => resolver.resolve())\n }\n\n /**\n * 创建火焰管理器。\n */\n private ensureFireManager(): FireManager {\n if (this.fireManager) return this.fireManager\n\n this.ensureParticleTexture()\n this.fireManager = new FireManager(this.five.scene, this.particleTexture)\n return this.fireManager\n }\n\n /**\n * 创建烟雾管理器。\n */\n private ensureSmokeManager(): SmokeManager {\n if (this.smokeManager) return this.smokeManager\n\n this.ensureParticleTexture()\n this.smokeManager = new SmokeManager(this.five.scene, SMOKE_RENDER_CONFIG, this.particleTexture)\n return this.smokeManager\n }\n\n private ensureParticleTexture(): void {\n if (!this.resourceConfig.particleTextureUrl) {\n throw new Error('粒子贴图未配置,请先调用 updateResourceConfig 设置 particleTexture')\n }\n }\n\n /** 把数据里的 work 局部坐标变换为场景世界坐标 */\n private toWorld(position: THREE.Vector3): THREE.Vector3 {\n return transformPosition(position, this.workUtil.transform)\n }\n\n /**\n * 把局部坐标的包围盒变换为世界坐标包围盒。\n */\n private toWorldBounds(bounds: FireSpreadBounds): FireSpreadBounds {\n const [minX, minY, minZ, maxX, maxY, maxZ] = bounds\n const corners = [\n [minX, minY, minZ],\n [maxX, minY, minZ],\n [minX, maxY, minZ],\n [maxX, maxY, minZ],\n [minX, minY, maxZ],\n [maxX, minY, maxZ],\n [minX, maxY, maxZ],\n [maxX, maxY, maxZ],\n ].map(([x, y, z]) => this.toWorld(new THREE.Vector3(x, y, z)))\n\n const box = new THREE.Box3().setFromPoints(corners)\n return [box.min.x, box.min.y, box.min.z, box.max.x, box.max.y, box.max.z]\n }\n\n /** 创建消防员的喷水粒子 */\n private createSprayParticle(firefighterId: string): Particle {\n const particle = new Particle({\n positionStyle: 'CUBE',\n positionBase: new THREE.Vector3(0, 0, 0),\n positionCubeSpread: new THREE.Vector3(0.05, 0.0, 0.05),\n velocityStyle: 'CUBE',\n velocityCubeBase: new THREE.Vector3(0, 1.0, -1.5),\n velocityCubeSpread: new THREE.Vector3(0.5, 0.5, 0.5),\n accelerationBase: new THREE.Vector3(0.3, -1.5, -2.5),\n texture: this.particleTexture.current,\n angleBase: 0,\n angleSpread: (90 / 180) * Math.PI,\n angleVelocityBase: 0,\n angleVelocitySpread: ((360 * 1) / 180) * Math.PI,\n sizeTween: { times: [0, 1], values: [0.005, 0.01] },\n opacityTween: { times: [1, 2], values: [1, 0] },\n colorTween: {\n times: [0.5, 2],\n values: [new THREE.Vector3(0, 0, 0.9), new THREE.Vector3(0, 0, 0.95)],\n },\n particlesPerSecond: 1000,\n particleDeathAge: 2,\n })\n particle.name = `${firefighterId}_water`\n particle.rotation.set(0, Math.PI * 1.05, 0)\n particle.position.set(0.05, 1.25, 1.5)\n return particle\n }\n}\n","import * as THREE from 'three/webgpu'\nimport type { FireArea, FireSceneConfig } from '../typing'\n\n/** 单位立方体的 8 个顶点,各轴 -0.5 ~ 0.5 */\nconst UNIT_BOX_VERTICES: [number, number, number][] = [\n [-0.5, -0.5, -0.5],\n [0.5, -0.5, -0.5],\n [0.5, -0.5, 0.5],\n [-0.5, -0.5, 0.5],\n [-0.5, 0.5, -0.5],\n [0.5, 0.5, -0.5],\n [0.5, 0.5, 0.5],\n [-0.5, 0.5, 0.5],\n]\n\n/**\n * 由起火区域的 matrix 求它的 8 个顶点。\n */\nexport function getAreaVertices(matrix: number[]): THREE.Vector3[] {\n const matrix4 = new THREE.Matrix4().fromArray(matrix)\n return UNIT_BOX_VERTICES.map((vertex) => new THREE.Vector3(...vertex).applyMatrix4(matrix4))\n}\n\n/**\n * 由起火区域的 matrix 求它的轴对齐包围盒。\n */\nexport function getAreaBox3(matrix: number[]): THREE.Box3 {\n return new THREE.Box3().setFromPoints(getAreaVertices(matrix))\n}\n\n/**\n * 求进场时应该观察的起火区域。\n */\nexport function getEntryArea(config: FireSceneConfig | undefined | null): FireArea | undefined {\n if (!config) return undefined\n const firstStep = config.ignite_sequences?.[0]\n const firstModel = firstStep && config.models?.find((model) => model.id === firstStep.model_id)\n const area = firstModel?.area_id && config.areas?.find((it) => it.id === firstModel.area_id)\n return area || config.areas?.[0]\n}\n","import * as THREE from 'three/webgpu'\nimport type { FireControl } from './FireControl'\nimport { FIRE_ACTION_DURATION_MS, FIRE_SPREAD_SPEED } from './constants'\nimport type { FireModel, FireSceneConfig, FireSequenceKind, FireSequenceStep, FireSpreadBounds } from './typing'\nimport { getAreaBox3 } from './utils/areaBounds'\n\n/** 播放器配置 */\nexport interface FireSequencePlayerOptions {\n /** 整条序列播完(最后一段动画也结束)后触发 */\n onSequenceEnd?: (kind: FireSequenceKind) => void\n}\n\n/**\n * 消防演绎时间轴播放器\n */\nexport class FireScenePlayer {\n private fireControl: FireControl\n private config: FireSceneConfig\n private options: FireSequencePlayerOptions\n\n private timers: ReturnType<typeof setTimeout>[] = []\n /** 当前正在播放的过程 */\n private playingKind: FireSequenceKind | null = null\n /** 已经触发过的动画段,停止时按它逐段去停 */\n private executedSteps: { kind: FireSequenceKind; model: FireModel }[] = []\n\n constructor(fireControl: FireControl, config: FireSceneConfig, options?: FireSequencePlayerOptions) {\n this.fireControl = fireControl\n this.config = config\n this.options = options ?? {}\n }\n\n /** 当前是否正在播放 */\n public get playing(): boolean {\n return this.playingKind !== null\n }\n\n /**\n * 播放一条序列。\n */\n public play(kind: FireSequenceKind): void {\n this.stop()\n this.playingKind = kind\n\n const steps = kind === 'ignite' ? this.config.ignite_sequences : this.config.extinguish_sequences\n if (steps.length === 0) {\n this.playingKind = null\n return\n }\n\n let absoluteMs = 0\n // 整条序列真正结束的时刻 = 各段「开始时刻 + 该段时长」的最大值\n let endMs = 0\n steps.forEach((step, index) => {\n absoluteMs += step.delay_ms\n const startsAt = absoluteMs\n const timer = setTimeout(() => {\n const model = this.runStep(kind, step)\n if (model) this.executedSteps.push({ kind, model })\n }, startsAt)\n this.timers.push(timer)\n\n endMs = Math.max(endMs, startsAt + (FIRE_ACTION_DURATION_MS[kind][this.findModel(step)?.type ?? 'fire'] ?? 0))\n })\n\n this.timers.push(\n setTimeout(() => {\n this.playingKind = null\n this.options.onSequenceEnd?.(kind)\n }, endMs),\n )\n }\n\n /**\n * 中断播放\n */\n public stop(): void {\n this.timers.forEach((timer) => clearTimeout(timer))\n this.timers = []\n this.playingKind = null\n\n const executed = this.executedSteps\n this.executedSteps = []\n executed.forEach(({ kind, model }) => this.stopStep(kind, model))\n }\n\n public dispose(): void {\n this.stop()\n }\n\n /** 停掉一段已经触发的动画 */\n private stopStep(kind: FireSequenceKind, model: FireModel): void {\n // 起火过程产生的实体由调用方 clearAll 统一清理,这里只回收灭火过程引入的动画\n if (kind === 'ignite') return\n\n if (model.type === 'firefighter') this.fireControl.removeFirefighter(model.id)\n else if (model.type === 'fire') this.fireControl.stopExtinguishFire(model.id)\n else this.fireControl.stopDissipateSmoke(model.id)\n }\n\n private findModel(step: FireSequenceStep): FireModel | undefined {\n return this.config.models.find((item) => item.id === step.model_id)\n }\n\n /**\n * 计算扩散范围\n */\n private getAreaBounds(model: FireModel): FireSpreadBounds | undefined {\n const area = this.config.areas.find((item) => item.id === model.area_id)\n if (!area) return undefined\n\n const box = getAreaBox3(area.matrix)\n return [box.min.x, box.min.y, box.min.z, box.max.x, box.max.y, box.max.z]\n }\n\n /** 执行一段动画 */\n private runStep(kind: FireSequenceKind, step: FireSequenceStep): FireModel | undefined {\n const model = this.findModel(step)\n if (!model) return\n\n if (!this.fireControl.hasParticleTexture) {\n console.warn('[FireScenePlugin] 粒子贴图未配置,跳过本段动画。请先调用 updateResourceConfig')\n return\n }\n\n const position: [number, number, number] = [model.position.x, model.position.y, model.position.z]\n const duration = FIRE_ACTION_DURATION_MS[kind][model.type]\n\n if (kind === 'ignite') {\n if (model.type === 'fire') {\n const bounds = this.getAreaBounds(model)\n this.fireControl.addFire(model.id, position, { size: model.scale, fadeInMs: duration })\n if (bounds) this.fireControl.igniteFire(model.id, bounds, { spreadSpeed: FIRE_SPREAD_SPEED })\n } else if (model.type === 'smoke') {\n const bounds = this.getAreaBounds(model)\n this.fireControl.addSmoke(model.id, position, { intensity: model.scale, fadeInMs: duration })\n if (bounds) this.fireControl.spreadSmoke(model.id, bounds, { spreadSpeed: FIRE_SPREAD_SPEED })\n }\n } else {\n if (model.type === 'firefighter') {\n if (!this.fireControl.hasWaterGunModel) {\n console.warn('[FireScenePlugin] 消防员模型未配置,跳过本段动画。请先调用 updateResourceConfig')\n return\n }\n void this.fireControl\n .addFirefighter({\n id: model.id,\n position,\n rotation: new THREE.Euler(model.rotation.x, model.rotation.y, model.rotation.z),\n scale: model.scale,\n spray: true,\n })\n .catch((error) => console.error('[FireScenePlugin] 消防员加载失败', error))\n } else if (model.type === 'fire') {\n this.fireControl.extinguishFire(model.id, { duration })\n } else if (model.type === 'smoke') {\n this.fireControl.dissipateSmoke(model.id, { duration })\n }\n }\n\n // 每段动画开始时都把镜头带到该段的实体\n void this.fireControl.focusEntity(model.id)\n\n return model\n }\n}\n"],"mappings":"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"}
@@ -18,6 +18,6 @@ function n(t) {
18
18
  return e(t)?.loaded;
19
19
  }
20
20
  //#endregion
21
- export { t };
21
+ export { t as n, n as t };
22
22
 
23
- //# sourceMappingURL=fiveModelLoad-mg-TnpnM.js.map
23
+ //# sourceMappingURL=fiveModelLoad-BUIBYxzp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fiveModelLoad-mg-TnpnM.js","names":["getFiveModel","waitFiveModelLoaded","signal","fiveModelIsLoaded","five","finish","handleFiveModelLoaded","resolve","model"],"sources":["../../src/shared-utils/five/fiveModelLoad.ts"],"sourcesContent":["import type { Five, Model } from '@realsee/five-webgpu'\nimport { getFiveModel } from './getFiveModel'\n\n/**\n * @description: 等待 five model 加载完成\n */\nexport async function waitFiveModelLoaded(five: Five, signal?: AbortSignal) {\n return new Promise<void>((resolve) => {\n if (signal?.aborted || fiveModelIsLoaded(five)) {\n resolve()\n return\n }\n const finish = () => {\n five.off('modelLoaded', handleFiveModelLoaded)\n signal?.removeEventListener('abort', finish)\n resolve()\n }\n const handleFiveModelLoaded = (model: Model) => {\n if (model === getFiveModel(five)) finish()\n }\n five.on('modelLoaded', handleFiveModelLoaded)\n signal?.addEventListener('abort', finish, { once: true })\n })\n}\n\n/**\n * @note five 6.0 修复了 多次 load work 时,`five.model.loaded` 不会变为 `false` 的问题,不再需要 `five.model.name === five.work?.model.file` 的判断了\n */\nexport function fiveModelIsLoaded(five: Five) {\n return getFiveModel(five)?.loaded\n}\n"],"mappings":";;AAMA,eAAsBC,EAAoB,GAAY,GAAsB;CAC1E,OAAO,IAAI,SAAe,MAAY;EACpC,IAAIC,GAAQ,WAAWC,EAAkBC,CAAI,GAAG;GAC9C,EAAQ;GACR;EACF;EACA,IAAMC,UAAe;GAGnB,AAFAD,EAAK,IAAI,eAAeE,CAAqB,GAC7CJ,GAAQ,oBAAoB,SAASG,CAAM,GAC3CE,EAAQ;EACV,GACMD,KAAyB,MAAiB;GAC9C,AAAIE,MAAUR,EAAaI,CAAI,KAAGC,EAAO;EAC3C;EAEA,AADAD,EAAK,GAAG,eAAeE,CAAqB,GAC5CJ,GAAQ,iBAAiB,SAASG,GAAQ,EAAE,MAAM,GAAK,CAAC;CAC1D,CAAC;AACH;AAKA,SAAgBF,EAAkB,GAAY;CAC5C,OAAOH,EAAaI,CAAI,CAAC,EAAE;AAC7B"}
1
+ {"version":3,"file":"fiveModelLoad-BUIBYxzp.js","names":["getFiveModel","waitFiveModelLoaded","signal","fiveModelIsLoaded","five","finish","handleFiveModelLoaded","resolve","model"],"sources":["../../src/shared-utils/five/fiveModelLoad.ts"],"sourcesContent":["import type { Five, Model } from '@realsee/five-webgpu'\nimport { getFiveModel } from './getFiveModel'\n\n/**\n * @description: 等待 five model 加载完成\n */\nexport async function waitFiveModelLoaded(five: Five, signal?: AbortSignal) {\n return new Promise<void>((resolve) => {\n if (signal?.aborted || fiveModelIsLoaded(five)) {\n resolve()\n return\n }\n const finish = () => {\n five.off('modelLoaded', handleFiveModelLoaded)\n signal?.removeEventListener('abort', finish)\n resolve()\n }\n const handleFiveModelLoaded = (model: Model) => {\n if (model === getFiveModel(five)) finish()\n }\n five.on('modelLoaded', handleFiveModelLoaded)\n signal?.addEventListener('abort', finish, { once: true })\n })\n}\n\n/**\n * @note five 6.0 修复了 多次 load work 时,`five.model.loaded` 不会变为 `false` 的问题,不再需要 `five.model.name === five.work?.model.file` 的判断了\n */\nexport function fiveModelIsLoaded(five: Five) {\n return getFiveModel(five)?.loaded\n}\n"],"mappings":";;AAMA,eAAsBC,EAAoB,GAAY,GAAsB;CAC1E,OAAO,IAAI,SAAe,MAAY;EACpC,IAAIC,GAAQ,WAAWC,EAAkBC,CAAI,GAAG;GAC9C,EAAQ;GACR;EACF;EACA,IAAMC,UAAe;GAGnB,AAFAD,EAAK,IAAI,eAAeE,CAAqB,GAC7CJ,GAAQ,oBAAoB,SAASG,CAAM,GAC3CE,EAAQ;EACV,GACMD,KAAyB,MAAiB;GAC9C,AAAIE,MAAUR,EAAaI,CAAI,KAAGC,EAAO;EAC3C;EAEA,AADAD,EAAK,GAAG,eAAeE,CAAqB,GAC5CJ,GAAQ,iBAAiB,SAASG,GAAQ,EAAE,MAAM,GAAK,CAAC;CAC1D,CAAC;AACH;AAKA,SAAgBF,EAAkB,GAAY;CAC5C,OAAOH,EAAaI,CAAI,CAAC,EAAE;AAC7B"}
@@ -1,9 +1,9 @@
1
- import { t as e } from "./fiveModelLoad-mg-TnpnM.js";
1
+ import { n as e } from "./fiveModelLoad-BUIBYxzp.js";
2
2
  import { t } from "./throttle-YRIkRKaX.js";
3
- import { i as n } from "./defaultUrls-CjKkS9k9.js";
4
- import { i as r, n as i, r as a, t as o } from "./changeMode-BVGYCoqu.js";
3
+ import { a as n } from "./defaultUrls-CfMtGzqM.js";
4
+ import { i as r, n as i, r as a, t as o } from "./changeMode-D_I2AOjH.js";
5
5
  import { t as s } from "./equal-BiDAilPV.js";
6
- import { t as c } from "./BasePluginWithData-9z4tpAT4.js";
6
+ import { t as c } from "./BasePluginWithData-D_0W46_q.js";
7
7
  import { C as l, D as u, F as d, G as f, H as p, J as m, K as h, L as g, M as _, N as v, P as y, Q as b, R as x, U as S, V as C, W as w, X as T, Y as E, _ as D, b as O, ct as k, et as A, f as j, g as M, i as N, it as P, j as F, k as I, m as L, n as R, o as z, p as B, q as V, r as H, rt as U, st as W, t as G, tt as K, x as q, y as ee, z as J } from "./component.svelte-D5LYqt50.js";
8
8
  import { t as Y } from "./rad2Deg-DutG55Wb.js";
9
9
  import { i as te, n as ne, r as re, t as ie } from "./fontSize-DMhRSrtx.js";
@@ -6056,4 +6056,4 @@ var kn = class extends c {
6056
6056
  //#endregion
6057
6057
  export { an as a, Mt as c, An as i, Q as l, jn as n, Bt as o, Nn as r, Rt as s, Mn as t };
6058
6058
 
6059
- //# sourceMappingURL=floorplan-KWlIsTvO.js.map
6059
+ //# sourceMappingURL=floorplan-C8BGw87S.js.map