@ray-js/robot-map-sdk 0.0.3-beta-12 → 0.0.3-beta-13

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 (42) hide show
  1. package/dist/application/MapApplication.js +1 -1
  2. package/dist/components/Map/RoomFill.js +1 -1
  3. package/dist/components/RoomFloorType/index.js +1 -1
  4. package/dist/components/RoomInfo/RoomName.js +1 -1
  5. package/dist/components/RoomInfo/RoomProperty.js +1 -1
  6. package/dist/components/RoomInfo/RoomSelectionIndicator.js +1 -1
  7. package/dist/constant/config.js +1 -1
  8. package/dist/index.d.ts +26 -6
  9. package/dist/index.rjs.js +1 -1
  10. package/dist/managers/MapManager.js +1 -1
  11. package/dist/managers/RoomManager.js +1 -1
  12. package/dist/utils/algorithm.js +1 -1
  13. package/dist-app/assets/{index-BCC761Na.js → index-DEl6eabz.js} +1 -1
  14. package/dist-app/index.html +1 -1
  15. package/dist-docs/404.html +2 -2
  16. package/dist-docs/assets/{app.896xnLF3.js → app.D-obOMzx.js} +1 -1
  17. package/dist-docs/assets/chunks/@localSearchIndexroot.DjeFOaBq.js +1 -0
  18. package/dist-docs/assets/chunks/{VPLocalSearchBox.D2USf4cd.js → VPLocalSearchBox.BlP3UL6y.js} +1 -1
  19. package/dist-docs/assets/chunks/{theme.CMExH5VI.js → theme.DifRD7r0.js} +2 -2
  20. package/dist-docs/assets/{guide_advanced-usage.md.DUawnQ9c.js → guide_advanced-usage.md.CUkMfTh6.js} +4 -3
  21. package/dist-docs/assets/{guide_advanced-usage.md.DUawnQ9c.lean.js → guide_advanced-usage.md.CUkMfTh6.lean.js} +1 -1
  22. package/dist-docs/assets/{guide_getting-started.md.JQJjuJPZ.js → guide_getting-started.md.DpAaFNd5.js} +1 -1
  23. package/dist-docs/assets/reference_config.md.BAU8soPd.js +41 -0
  24. package/dist-docs/assets/{reference_config.md.DGFTKy3W.lean.js → reference_config.md.BAU8soPd.lean.js} +1 -1
  25. package/dist-docs/assets/{reference_methods.md.B71e_LYO.js → reference_methods.md.Cw2UFl8i.js} +3 -6
  26. package/dist-docs/assets/{reference_methods.md.B71e_LYO.lean.js → reference_methods.md.Cw2UFl8i.lean.js} +1 -1
  27. package/dist-docs/guide/advanced-usage.html +8 -7
  28. package/dist-docs/guide/concepts.html +3 -3
  29. package/dist-docs/guide/getting-started.html +5 -5
  30. package/dist-docs/hashmap.json +1 -1
  31. package/dist-docs/index.html +3 -3
  32. package/dist-docs/reference/callbacks.html +3 -3
  33. package/dist-docs/reference/config.html +5 -5
  34. package/dist-docs/reference/data.html +3 -3
  35. package/dist-docs/reference/methods.html +6 -9
  36. package/dist-docs/reference/runtime.html +3 -3
  37. package/dist-docs/reference/types.html +3 -3
  38. package/dist-docs/reference/utils.html +3 -3
  39. package/package.json +1 -1
  40. package/dist-docs/assets/chunks/@localSearchIndexroot.Cr-cfrpg.js +0 -1
  41. package/dist-docs/assets/reference_config.md.DGFTKy3W.js +0 -41
  42. /package/dist-docs/assets/{guide_getting-started.md.JQJjuJPZ.lean.js → guide_getting-started.md.DpAaFNd5.lean.js} +0 -0
@@ -1 +1 @@
1
- import{Application as e,isMobile as t,Assets as n}from"pixi.js";import{Interaction as a}from"./Interaction.js";import{merge as r}from"lodash-es";import{proxy as i}from"valtio/vanilla";import{MAIN_INSTANCE_KEY as o}from"../constant/index.js";import s from"mitt";import{Logger as c}from"../utils/logger.js";import{AppContext as h}from"./AppService.js";import{nanoid as d}from"nanoid/non-secure";import{calculateLineEndpoints as p,areStructuredRoomsAdjacent as m,areMultipleRoomsConnected as l,areRasterRoomsAdjacent as g}from"../utils/algorithm.js";import{ViewportContainer as u}from"./ViewportContainer.js";import{AppContainer as w}from"./AppContainer.js";import{MapManager as f}from"../managers/MapManager.js";import{PathManager as M}from"../managers/PathManager.js";import{HeatmapManager as y}from"../managers/HeatmapManager.js";import{ControlsManager as x}from"../managers/ControlsManager.js";import{DetectedObjectManager as S}from"../managers/DetectedObjectManager.js";import{CustomElementsManager as v}from"../managers/CustomElementsManager.js";import{RoomManager as b}from"../managers/RoomManager.js";import{getOptimalAntialiasingStrategy as P}from"../utils/browser.js";import{DEFAULT_CONFIG as C,DEFAULT_RUNTIME_CONFIG as R}from"../constant/config.js";class O extends e{mapState=null;components={};managers={};config=C;runtime;scaleMin=.5;scaleMax=5;events={};instanceKey;containerElement;emitter=s();tickerState={renderReasons:new Set,renderTimer:null};pendingAsyncRender=!1;isFirstMapDraw=!0;constructor(e=o){super(),this.instanceKey=e,h.registerInstance(e,this),globalThis.__PIXI_APP__=this}async initialize(e){return h.provideAsync(this,async()=>{const{resizeTo:n,events:a,config:s,runtime:c={},...h}=e;this.config=r(this.config,s??{}),this.runtime=i(Object.assign({},R,c));const d=this.instanceKey===o;this.containerElement=n;const p=d?{textureGCMaxIdle:t.any?180:3600,textureGCCheckCountMax:t.any?100:50,autoStart:!1,eventFeatures:{move:!0,globalMove:!1,click:!0,wheel:!0}}:{textureGCMaxIdle:60,textureGCCheckCountMax:10,autoStart:!1,eventFeatures:{move:!1,globalMove:!1,click:!1,wheel:!1}};await this.init({resizeTo:d?n:void 0,preferWebGLVersion:2,resolution:window.devicePixelRatio||1,antialias:P(),autoDensity:!0,backgroundColor:this.config.global.backgroundColor,...p,...h}),this.preloadAssets(),this.scaleMax=this.config.interaction.zoomRange.max,this.scaleMin=this.config.interaction.zoomRange.min,this.events=a,this.initializeViewportContainer(),this.initializeInteraction(),this.initializeAppContainer(),this.managers.mapManager=new f,this.managers.heatmapManager=new y,this.managers.pathManager=new M,this.managers.controlsManager=new x,this.managers.detectedObjectManager=new S,this.managers.customElementsManager=new v,this.managers.roomsManager=new b,document.addEventListener("visibilitychange",this.onVisibilityChange)})}async drawMap(e){return h.provideAsync(this,async()=>{c.log("[Map] drawMap",e);const{size:t,resolution:n,origin:a}=e;a[0]===this.mapState?.origin.x&&a[1]===this.mapState?.origin.y||(this.managers.pathManager.updatePositionByOrigin(...a),this.managers.controlsManager.updatePositionByOrigin(...a),this.managers.detectedObjectManager.updatePositionByOrigin(...a),this.managers.customElementsManager.updatePositionByOrigin(...a)),this.mapState={id:e.id,status:1===e.status,origin:{x:a[0],y:a[1]},charger:{x:e.charger.coordinate[0],y:e.charger.coordinate[1]},chargerDirection:e.charger.angle??0,resolution:n,width:t[0],height:t[1]},this.isFirstMapDraw&&(this.isFirstMapDraw=!1,this.events?.onMapFirstDrawed?.(this.mapState)),this.events?.onMapDrawed?.(this.mapState),await this.managers.mapManager.drawMap(e),this.renderOnce()})}async drawRasterMap(e){return h.provideAsync(this,async()=>{c.log("[Map] drawRasterMap",e);const{mapHeader:t,mapData:n}=e,{originX:a,originY:r}=t;a===this.mapState?.origin.x&&r===this.mapState?.origin.y||(this.managers.pathManager.updatePositionByOrigin(a,r),this.managers.controlsManager.updatePositionByOrigin(a,r),this.managers.detectedObjectManager.updatePositionByOrigin(a,r),this.managers.customElementsManager.updatePositionByOrigin(a,r)),this.mapState={id:t.id,status:t.mapStable,origin:{x:a,y:r},charger:{x:t.chargeX,y:t.chargeY},chargerDirection:t.chargeDirection??0,resolution:100*t.mapResolution,width:t.mapWidth,height:t.mapHeight,version:t.version},this.isFirstMapDraw&&(this.isFirstMapDraw=!1,this.events?.onMapFirstDrawed?.(this.mapState)),this.events?.onMapDrawed?.(this.mapState),await this.managers.mapManager.drawRasterMap(n.parsed,this.mapState),this.renderOnce()})}drawPath(e){return h.provide(this,()=>{c.log("[Path] drawPath",e),this.events?.onPathDrawed?.({id:e.pathHeader.pathId,type:e.pathHeader.type,direction:e.pathHeader.direction,count:e.pathHeader.count,initFlag:e.pathHeader.initFlag,robotPosition:e.pathPoints[e.pathPoints.length-1]??null}),this.managers.pathManager.draw(e),this.renderOnce()})}async drawRoomProperty(e){return h.provide(this,()=>{c.log("[Room] drawRoomProperty",e),this.events?.onRoomPropertiesDrawed?.(e),this.managers.roomsManager.drawRoomProperty(e),this.renderOnceNextFrame()})}drawHeatmap({mapData:e,heatmapPoints:t,useGradient:n=!0}){return h.provide(this,()=>{c.log("[Heatmap] drawHeatmap",t),this.managers.heatmapManager.draw({mapData:e,heatmapPoints:t,useGradient:n}),this.renderOnce()})}drawForbiddenSweepZones(e){return h.provide(this,()=>{c.log("[Controls] drawForbiddenSweepZones",e),this.managers.controlsManager.drawForbiddenSweepZones(e),this.renderOnceNextFrame()})}drawForbiddenMopZones(e){return h.provide(this,()=>{c.log("[Controls] drawForbiddenMopZones",e),this.managers.controlsManager.drawForbiddenMopZones(e),this.renderOnceNextFrame()})}drawCleanZones(e){return h.provide(this,()=>{c.log("[Controls] drawCleanZones",e),this.managers.controlsManager.drawCleanZones(e),this.renderOnceNextFrame()})}drawVirtualWalls(e){return h.provide(this,()=>{c.log("[Controls] drawVirtualWalls",e),this.managers.controlsManager.drawVirtualWalls(e),this.renderOnceNextFrame()})}drawSpots(e){return h.provide(this,()=>{c.log("[Controls] drawSpots",e),this.managers.controlsManager.drawSpots(e),this.renderOnceNextFrame()})}async drawDetectedObjects(e){return h.provideAsync(this,async()=>{c.log("[DetectedObject] drawDetectedObjects",e),await this.managers.detectedObjectManager.drawDetectedObjects(e),this.renderOnceNextFrame()})}async drawCustomElements(e){return h.provideAsync(this,async()=>{c.log("[CustomElements] drawCustomElements",e),await this.managers.customElementsManager.drawCustomElements(e),this.renderOnceNextFrame()})}getForbiddenSweepZones(){return this.managers.controlsManager.getForbiddenSweepZones()}getForbiddenMopZones(){return this.managers.controlsManager.getForbiddenMopZones()}getCleanZones(){return this.managers.controlsManager.getCleanZones()}getVirtualWalls(){return this.managers.controlsManager.getVirtualWalls()}getSpots(){return this.managers.controlsManager.getSpots()}getEffectiveDividerPoints(){return this.managers.controlsManager.getEffectiveDividerPoints()}getDividerEndPoints(){return this.managers.controlsManager.getDividerEndPoints()}resetPanZoom(){this.components.interaction.setPanZoom()}fitMapToView(e,t=!1){return h.provide(this,()=>{if(!e||e.minX===e.maxX||e.minY===e.maxY)return void c.warn("地图边界无效,无法自动适配视图");const n=this.config.map.autoPaddingPercent||.1,a=this.getViewportBounds(),r=e.maxX-e.minX,i=e.maxY-e.minY,o=a.width,s=a.height,h=o*(1-2*n)/r,d=s*(1-2*n)/i,p=Math.min(h,d),m=Math.max(this.config.interaction.fitMinScale,this.scaleMin),l=Math.min(this.config.interaction.fitMaxScale,this.scaleMax),g=Math.max(m,Math.min(l,p)),u=o/2-(e.minX+r/2)*g,w=s/2-(e.minY+i/2)*g;this.components.interaction.setPanZoom({targetPosition:{x:u,y:w},targetScale:{x:g,y:g},setCenter:!0,setScale:!0},t)})}getViewportBounds(){return this.components.viewportContainer?.getViewportBounds()||{x:0,y:0,width:this.renderer.width,height:this.renderer.height}}updateRuntime(e){Object.assign(this.runtime,e),this.renderOnceNextFrame()}metersToPixels(e){return this.mapState?.resolution?e*(1/(this.mapState.resolution/100)):(c.warn("Map resolution not available, using default resolution (5cm/pixel)"),20*e)}pixelsToMeters(e){return this.mapState?.resolution?e*(this.mapState.resolution/100):(c.warn("Map resolution not available, using default resolution (5cm/pixel)"),.05*e)}toFixedSize(e,t){return e/(t??this.components.appContainer.scale.x)}fromFixedSize(e,t){return e*(t??this.components.appContainer.scale.x)}getViewportCenterPoint(){if(!this.mapState)return c.warn("Map state not available, cannot calculate center point"),null;const e=this.getViewportBounds(),t=e.x+e.width/2,n=e.y+e.height/2,a=this.components.appContainer,r=a.scale.x,i=(t-a.x)/r,o=(n-a.y)/r;return{x:i-this.mapState.origin.x,y:o-this.mapState.origin.y}}getMapCenterPoint(){if(!this.mapState)return c.warn("Map state not available, cannot calculate map center point"),null;const e=this.managers.mapManager.mapBounds;if(e.minX===1/0||e.minY===1/0||e.maxX===-1/0||e.maxY===-1/0)return c.warn("Invalid map bounds, cannot calculate map center point"),null;const t=(e.minX+e.maxX)/2,n=(e.minY+e.maxY)/2;return{x:t-this.mapState.origin.x,y:n-this.mapState.origin.y}}getWallPointsByViewportCenter(e){const{width:t=this.config.controls.virtualWall.minWidth,direction:n="horizontal",offsetX:a=0,offsetY:r=0}=e||{},i=this.getViewportCenterPoint()||{x:0,y:0},o=this.metersToPixels(t);return p(i.x,i.y,o,n).map(e=>({x:e.x+a,y:e.y+r}))}getForbiddenSweepZonePointsByViewportCenter(e){const t=this.config.controls.forbiddenSweepZone,{size:n=t.minSize,offsetX:a=0,offsetY:r=0}=e||{};return this.generateZonePoints(n,a,r)}getForbiddenMopZonePointsByViewportCenter(e){const t=this.config.controls.forbiddenMopZone,{size:n=t.minSize,offsetX:a=0,offsetY:r=0}=e||{};return this.generateZonePoints(n,a,r)}getCleanZonePointsByViewportCenter(e){const t=this.config.controls.cleanZone,{size:n=t.minSize,offsetX:a=0,offsetY:r=0}=e||{};return this.generateZonePoints(n,a,r)}getSpotPointByViewportCenter(e){const{offsetX:t=0,offsetY:n=0}=e||{},a=this.getViewportCenterPoint()||{x:0,y:0};return{x:a.x+t,y:a.y+n}}areRoomsAdjacent(e,t=3){return h.provide(this,()=>{if(!e||0===e.length)return c.warn("[Room] No room IDs provided"),!1;if(1===e.length)return!0;const n=Array.from(new Set(e));return 1===n.length||(void 0!==this.mapState?.version?this.areRasterRoomsAdjacentInternal(n,t):this.areStructuredRoomsAdjacentInternal(n,t))})}areStructuredRoomsAdjacentInternal(e,t){const n=[];for(const t of e){const e=this.managers.mapManager.getRoomById(t);if(!e)return c.warn(`[Room] Room ${t} not found in map`),!1;if(!e.outlinePoints||0===e.outlinePoints.length)return c.warn(`[Room] Room ${t} has no outline points`),!1;n.push({id:t,points:e.outlinePoints})}const a=[];for(let e=0;e<n.length;e++)for(let r=e+1;r<n.length;r++){const i=n[e],o=n[r];m(i.points,o.points,t)&&a.push([e,r])}return l(n.length,a)}areRasterRoomsAdjacentInternal(e,t){if(!this.mapState)return c.warn("[Room] Map state not available"),!1;const n=this.mapState.width,a=[];for(const t of e){const e=this.managers.mapManager.getRasterRoomPixels(t);if(!e)return c.warn(`[Room] Room ${t} pixel data not found in raster map`),!1;a.push({id:t,pixels:e})}const r=[];for(let e=0;e<a.length;e++)for(let i=e+1;i<a.length;i++){const o=a[e],s=a[i];g(o.pixels,s.pixels,n,t)&&r.push([e,i])}return l(a.length,r)}async snapshot(){this.render(),await new Promise(e=>setTimeout(e,0));const{snapshot:e}=this.config;return await this.renderer.extract.base64({target:this.components.appContainer,format:e.format,quality:e.quality,resolution:e.resolution,antialias:e.antialias})}async snapshotByData({map:e,path:t,roomProperties:n,customElements:a,forbiddenSweepZones:r,forbiddenMopZones:i,virtualWalls:o,detectedObjects:s},h={}){const p=`SNAPSHOT_${d()}`;c.log(`[MapApplication] ${p} snapshot start`);const m=new O(p);try{if(await m.initialize({config:this.config,runtime:h}),!e)throw new Error("Map data is required");if(e.startsWith("7b22")){const{decodeMapStructured:t}=await import("@ray-js/robot-protocol"),n=t(e);await m.drawMap(n)}else{const{decodeMap:t}=await import("@ray-js/robot-protocol"),n=t(e);if(!n)throw new Error("Failed to decode raster map data");await m.drawRasterMap(n)}if(t){const{decodePath:e}=await import("@ray-js/robot-protocol"),n=e(t);m.drawPath(n)}n&&n.length>0&&m.drawRoomProperty(n),r&&r.length>0&&m.drawForbiddenSweepZones(r),i&&i.length>0&&m.drawForbiddenMopZones(i),o&&o.length>0&&m.drawVirtualWalls(o),s&&s.length>0&&await m.drawDetectedObjects(s),a&&a.length>0&&await m.drawCustomElements(a);const d=await m.snapshot();return c.log(`[MapApplication] ${p} snapshot completed successfully`),d}catch(e){throw c.error(`[MapApplication] ${p} snapshot other map failed:`,e),e}finally{c.log(`[MapApplication] ${p} destroy`),m.destroy()}}renderOnce(){c.log("[Pixi] renderOnce"),this.render()}renderOnceNextFrame(){this.pendingAsyncRender||(this.pendingAsyncRender=!0,requestAnimationFrame(()=>{c.log("[Pixi] renderOnceNextFrame"),this.render(),this.pendingAsyncRender=!1}))}requestRender(e,t=!1){t?(this.tickerState.renderReasons.add(e),this.ticker.started||(c.debug(`🎬 [Ticker] START: ${e}`),this.ticker.start())):this.renderOnceNextFrame()}stopRender(e){this.tickerState.renderReasons.delete(e),0===this.tickerState.renderReasons.size&&this.scheduleStopRender("final",100)}destroy(){h.unregisterInstance(this.instanceKey),this.tickerState.renderTimer&&clearTimeout(this.tickerState.renderTimer),this.tickerState.renderReasons.clear(),this.emitter.all.clear(),document.removeEventListener("visibilitychange",this.onVisibilityChange),this.managers.pathManager.destroy(),this.managers.mapManager.destroy(),this.managers.controlsManager.destroy(),this.managers.detectedObjectManager.destroy(),this.managers.customElementsManager.destroy(),this.managers.roomsManager.destroy(),this.components.interaction.destroy(),this.components.viewportContainer.destroy(),this.components.appContainer.destroy(),super.destroy()}initializeViewportContainer(){this.components.viewportContainer=new u(this.config,this.containerElement),this.stage.addChild(this.components.viewportContainer)}initializeAppContainer(){this.components.appContainer=new w,this.components.interaction.addChild(this.components.appContainer)}initializeInteraction(){this.components.interaction=new a,this.components.viewportContainer.addChild(this.components.interaction)}scheduleStopRender(e,t){this.tickerState.renderTimer&&clearTimeout(this.tickerState.renderTimer),this.tickerState.renderTimer=setTimeout(()=>{this.tickerState.renderReasons.delete(e),0===this.tickerState.renderReasons.size&&(c.debug("⏸️ [Ticker] STOP"),this.ticker.stop())},t)}generateZonePoints(e,t,n){const a=this.getViewportCenterPoint()||{x:0,y:0},r=this.metersToPixels(e)/2,i=a.x+t,o=a.y+n;return[{x:i-r,y:o-r},{x:i+r,y:o-r},{x:i+r,y:o+r},{x:i-r,y:o+r}]}preloadAssets(){const e=this.config.robot.icon.src,t=this.config.chargingStation.icon.src,a=[];n.add({alias:"robot",src:e}),a.push("robot"),n.add({alias:"chargingStation",src:t}),a.push("chargingStation"),n.add({alias:"deleteIcon",src:this.config.controls.deleteIconSrc}),a.push("deleteIcon"),n.add({alias:"rotateIcon",src:this.config.controls.rotateIconSrc}),a.push("rotateIcon"),n.add({alias:"scaleIcon",src:this.config.controls.scaleIconSrc}),a.push("scaleIcon"),n.add({alias:"moveIcon",src:this.config.controls.moveIconSrc}),a.push("moveIcon"),n.add({alias:"checkmark",src:this.config.room.selectionIndicator.iconSrc}),a.push("checkmark"),n.add({alias:"spotIcon",src:this.config.controls.spot.iconSrc}),a.push("spotIcon"),this.config.room.property.cleanMode.assets.forEach((e,t)=>{const r=`cleanMode_${t}`;n.add({alias:r,src:e}),a.push(r)}),this.config.room.property.suction.assets.forEach((e,t)=>{const r=`fan_${t}`;n.add({alias:r,src:e}),a.push(r)}),this.config.room.property.cistern.assets.forEach((e,t)=>{const r=`water_${t}`;n.add({alias:r,src:e}),a.push(r)}),this.config.room.property.cleanTimes.assets.forEach((e,t)=>{const r=`cleanTimes${t+1}`;n.add({alias:r,src:e}),a.push(r)}),this.config.room.floorType.assets.forEach((e,t)=>{if(!e)return;const r=`floorType${t}`;n.add({alias:r,src:e}),a.push(r)}),n.backgroundLoad(a)}onVisibilityChange=()=>{"visible"===document.visibilityState||this.components.interaction?.clearTouches()}}export{O as MapApplication};
1
+ import{Application as e,isMobile as t,Assets as n}from"pixi.js";import{Interaction as a}from"./Interaction.js";import{merge as r}from"lodash-es";import{proxy as i}from"valtio/vanilla";import{MAIN_INSTANCE_KEY as o}from"../constant/index.js";import s from"mitt";import{Logger as c}from"../utils/logger.js";import{AppContext as h}from"./AppService.js";import{nanoid as d}from"nanoid/non-secure";import{calculateLineEndpoints as p,areStructuredRoomsAdjacent as m,areMultipleRoomsConnected as l,areRasterRoomsAdjacent as g}from"../utils/algorithm.js";import{ViewportContainer as u}from"./ViewportContainer.js";import{AppContainer as w}from"./AppContainer.js";import{MapManager as f}from"../managers/MapManager.js";import{PathManager as M}from"../managers/PathManager.js";import{HeatmapManager as y}from"../managers/HeatmapManager.js";import{ControlsManager as x}from"../managers/ControlsManager.js";import{DetectedObjectManager as S}from"../managers/DetectedObjectManager.js";import{CustomElementsManager as v}from"../managers/CustomElementsManager.js";import{RoomManager as b}from"../managers/RoomManager.js";import{getOptimalAntialiasingStrategy as P}from"../utils/browser.js";import{DEFAULT_CONFIG as C,DEFAULT_RUNTIME_CONFIG as R}from"../constant/config.js";class O extends e{mapState=null;components={};managers={};config=C;runtime;scaleMin=.5;scaleMax=5;events={};instanceKey;containerElement;emitter=s();tickerState={renderReasons:new Set,renderTimer:null};pendingAsyncRender=!1;isFirstMapDraw=!0;constructor(e=o){super(),this.instanceKey=e,h.registerInstance(e,this),globalThis.__PIXI_APP__=this}async initialize(e){return h.provideAsync(this,async()=>{const{resizeTo:n,events:a,config:s,runtime:c={},...h}=e;this.config=r(this.config,s??{}),this.runtime=i(Object.assign({},R,c));const d=this.instanceKey===o;this.containerElement=n;const p=d?{textureGCMaxIdle:t.any?180:3600,textureGCCheckCountMax:t.any?100:50,autoStart:!1,eventFeatures:{move:!0,globalMove:!1,click:!0,wheel:!0}}:{textureGCMaxIdle:60,textureGCCheckCountMax:10,autoStart:!1,eventFeatures:{move:!1,globalMove:!1,click:!1,wheel:!1}};await this.init({resizeTo:d?n:void 0,preferWebGLVersion:2,resolution:window.devicePixelRatio||1,antialias:P(),autoDensity:!0,backgroundColor:this.config.global.backgroundColor,...p,...h}),this.preloadAssets(),this.scaleMax=this.config.interaction.zoomRange.max,this.scaleMin=this.config.interaction.zoomRange.min,this.events=a,this.initializeViewportContainer(),this.initializeInteraction(),this.initializeAppContainer(),this.managers.mapManager=new f,this.managers.heatmapManager=new y,this.managers.pathManager=new M,this.managers.controlsManager=new x,this.managers.detectedObjectManager=new S,this.managers.customElementsManager=new v,this.managers.roomsManager=new b,document.addEventListener("visibilitychange",this.onVisibilityChange)})}async drawMap(e){return h.provideAsync(this,async()=>{c.log("[Map] drawMap",e);const{size:t,resolution:n,origin:a}=e;a[0]===this.mapState?.origin.x&&a[1]===this.mapState?.origin.y||(this.managers.pathManager.updatePositionByOrigin(...a),this.managers.controlsManager.updatePositionByOrigin(...a),this.managers.detectedObjectManager.updatePositionByOrigin(...a),this.managers.customElementsManager.updatePositionByOrigin(...a)),this.mapState={id:e.id,status:1===e.status,origin:{x:a[0],y:a[1]},charger:{x:e.charger.coordinate[0],y:e.charger.coordinate[1]},chargerDirection:e.charger.angle??0,resolution:n,width:t[0],height:t[1]},this.isFirstMapDraw&&(this.isFirstMapDraw=!1,this.events?.onMapFirstDrawed?.(this.mapState)),this.events?.onMapDrawed?.(this.mapState),await this.managers.mapManager.drawMap(e),this.renderOnce()})}async drawRasterMap(e){return h.provideAsync(this,async()=>{c.log("[Map] drawRasterMap",e);const{mapHeader:t,mapData:n}=e,{originX:a,originY:r}=t;a===this.mapState?.origin.x&&r===this.mapState?.origin.y||(this.managers.pathManager.updatePositionByOrigin(a,r),this.managers.controlsManager.updatePositionByOrigin(a,r),this.managers.detectedObjectManager.updatePositionByOrigin(a,r),this.managers.customElementsManager.updatePositionByOrigin(a,r)),this.mapState={id:t.id,status:t.mapStable,origin:{x:a,y:r},charger:{x:t.chargeX,y:t.chargeY},chargerDirection:t.chargeDirection??0,resolution:100*t.mapResolution,width:t.mapWidth,height:t.mapHeight,version:t.version},this.isFirstMapDraw&&(this.isFirstMapDraw=!1,this.events?.onMapFirstDrawed?.(this.mapState)),this.events?.onMapDrawed?.(this.mapState),await this.managers.mapManager.drawRasterMap(n.parsed,this.mapState),this.renderOnce()})}drawPath(e){return h.provide(this,()=>{c.log("[Path] drawPath",e),this.events?.onPathDrawed?.({id:e.pathHeader.pathId,type:e.pathHeader.type,direction:e.pathHeader.direction,count:e.pathHeader.count,initFlag:e.pathHeader.initFlag,robotPosition:e.pathPoints[e.pathPoints.length-1]??null}),this.managers.pathManager.draw(e),this.renderOnce()})}async drawRoomProperty(e){return h.provide(this,()=>{c.log("[Room] drawRoomProperty",e),this.events?.onRoomPropertiesDrawed?.(e),this.managers.roomsManager.drawRoomProperty(e),this.renderOnceNextFrame()})}drawHeatmap({mapData:e,heatmapPoints:t,useGradient:n=!0}){return h.provide(this,()=>{c.log("[Heatmap] drawHeatmap",t),this.managers.heatmapManager.draw({mapData:e,heatmapPoints:t,useGradient:n}),this.renderOnce()})}drawForbiddenSweepZones(e){return h.provide(this,()=>{c.log("[Controls] drawForbiddenSweepZones",e),this.managers.controlsManager.drawForbiddenSweepZones(e),this.renderOnceNextFrame()})}drawForbiddenMopZones(e){return h.provide(this,()=>{c.log("[Controls] drawForbiddenMopZones",e),this.managers.controlsManager.drawForbiddenMopZones(e),this.renderOnceNextFrame()})}drawCleanZones(e){return h.provide(this,()=>{c.log("[Controls] drawCleanZones",e),this.managers.controlsManager.drawCleanZones(e),this.renderOnceNextFrame()})}drawVirtualWalls(e){return h.provide(this,()=>{c.log("[Controls] drawVirtualWalls",e),this.managers.controlsManager.drawVirtualWalls(e),this.renderOnceNextFrame()})}drawSpots(e){return h.provide(this,()=>{c.log("[Controls] drawSpots",e),this.managers.controlsManager.drawSpots(e),this.renderOnceNextFrame()})}async drawDetectedObjects(e){return h.provideAsync(this,async()=>{c.log("[DetectedObject] drawDetectedObjects",e),await this.managers.detectedObjectManager.drawDetectedObjects(e),this.renderOnceNextFrame()})}async drawCustomElements(e){return h.provideAsync(this,async()=>{c.log("[CustomElements] drawCustomElements",e),await this.managers.customElementsManager.drawCustomElements(e),this.renderOnceNextFrame()})}getForbiddenSweepZones(){return this.managers.controlsManager.getForbiddenSweepZones()}getForbiddenMopZones(){return this.managers.controlsManager.getForbiddenMopZones()}getCleanZones(){return this.managers.controlsManager.getCleanZones()}getVirtualWalls(){return this.managers.controlsManager.getVirtualWalls()}getSpots(){return this.managers.controlsManager.getSpots()}getEffectiveDividerPoints(){return this.managers.controlsManager.getEffectiveDividerPoints()}getDividerEndPoints(){return this.managers.controlsManager.getDividerEndPoints()}resetPanZoom(){this.components.interaction.setPanZoom()}fitMapToView(e,t=!1){return h.provide(this,()=>{if(!e||e.minX===e.maxX||e.minY===e.maxY)return void c.warn("地图边界无效,无法自动适配视图");const n=this.config.map.autoPaddingPercent||.1,a=this.getViewportBounds(),r=e.maxX-e.minX,i=e.maxY-e.minY,o=a.width,s=a.height,h=o*(1-2*n)/r,d=s*(1-2*n)/i,p=Math.min(h,d),m=Math.max(this.config.interaction.fitMinScale,this.scaleMin),l=Math.min(this.config.interaction.fitMaxScale,this.scaleMax),g=Math.max(m,Math.min(l,p)),u=o/2-(e.minX+r/2)*g,w=s/2-(e.minY+i/2)*g;this.components.interaction.setPanZoom({targetPosition:{x:u,y:w},targetScale:{x:g,y:g},setCenter:!0,setScale:!0},t)})}getViewportBounds(){return this.components.viewportContainer?.getViewportBounds()||{x:0,y:0,width:this.renderer.width,height:this.renderer.height}}updateRuntime(e){Object.assign(this.runtime,e),this.renderOnceNextFrame()}metersToPixels(e){return this.mapState?.resolution?e*(1/(this.mapState.resolution/100)):(c.warn("Map resolution not available, using default resolution (5cm/pixel)"),20*e)}pixelsToMeters(e){return this.mapState?.resolution?e*(this.mapState.resolution/100):(c.warn("Map resolution not available, using default resolution (5cm/pixel)"),.05*e)}toFixedSize(e,t){return e/(t??this.components.appContainer.scale.x)}fromFixedSize(e,t){return e*(t??this.components.appContainer.scale.x)}getViewportCenterPoint(){if(!this.mapState)return c.warn("Map state not available, cannot calculate center point"),null;const e=this.getViewportBounds(),t=e.x+e.width/2,n=e.y+e.height/2,a=this.components.appContainer,r=a.scale.x,i=(t-a.x)/r,o=(n-a.y)/r;return{x:i-this.mapState.origin.x,y:o-this.mapState.origin.y}}getMapCenterPoint(){if(!this.mapState)return c.warn("Map state not available, cannot calculate map center point"),null;const e=this.managers.mapManager.mapBounds;if(e.minX===1/0||e.minY===1/0||e.maxX===-1/0||e.maxY===-1/0)return c.warn("Invalid map bounds, cannot calculate map center point"),null;const t=(e.minX+e.maxX)/2,n=(e.minY+e.maxY)/2;return{x:t-this.mapState.origin.x,y:n-this.mapState.origin.y}}getWallPointsByViewportCenter(e){const{width:t=this.config.controls.virtualWall.minWidth,direction:n="horizontal",offsetX:a=0,offsetY:r=0}=e||{},i=this.getViewportCenterPoint()||{x:0,y:0},o=this.metersToPixels(t);return p(i.x,i.y,o,n).map(e=>({x:e.x+a,y:e.y+r}))}getForbiddenSweepZonePointsByViewportCenter(e){const t=this.config.controls.forbiddenSweepZone,{size:n=t.minSize,offsetX:a=0,offsetY:r=0}=e||{};return this.generateZonePoints(n,a,r)}getForbiddenMopZonePointsByViewportCenter(e){const t=this.config.controls.forbiddenMopZone,{size:n=t.minSize,offsetX:a=0,offsetY:r=0}=e||{};return this.generateZonePoints(n,a,r)}getCleanZonePointsByViewportCenter(e){const t=this.config.controls.cleanZone,{size:n=t.minSize,offsetX:a=0,offsetY:r=0}=e||{};return this.generateZonePoints(n,a,r)}getSpotPointByViewportCenter(e){const{offsetX:t=0,offsetY:n=0}=e||{},a=this.getViewportCenterPoint()||{x:0,y:0};return{x:a.x+t,y:a.y+n}}areRoomsAdjacent(e){const t=this.config.map.adjacencyThreshold;return h.provide(this,()=>{if(!e||0===e.length)return c.warn("[Room] No room IDs provided"),!1;if(1===e.length)return!0;const n=Array.from(new Set(e));return 1===n.length||(void 0!==this.mapState?.version?this.areRasterRoomsAdjacentInternal(n,t):this.areStructuredRoomsAdjacentInternal(n,t))})}areStructuredRoomsAdjacentInternal(e,t){const n=[];for(const t of e){const e=this.managers.mapManager.getRoomById(t);if(!e)return c.warn(`[Room] Room ${t} not found in map`),!1;if(!e.outlinePoints||0===e.outlinePoints.length)return c.warn(`[Room] Room ${t} has no outline points`),!1;n.push({id:t,points:e.outlinePoints})}const a=[];for(let e=0;e<n.length;e++)for(let r=e+1;r<n.length;r++){const i=n[e],o=n[r];m(i.points,o.points,t)&&a.push([e,r])}return l(n.length,a)}areRasterRoomsAdjacentInternal(e,t){if(!this.mapState)return c.warn("[Room] Map state not available"),!1;const n=this.mapState.width,a=[];for(const t of e){const e=this.managers.mapManager.getRasterRoomPixels(t);if(!e)return c.warn(`[Room] Room ${t} pixel data not found in raster map`),!1;a.push({id:t,pixels:e})}const r=[];for(let e=0;e<a.length;e++)for(let i=e+1;i<a.length;i++){const o=a[e],s=a[i];g(o.pixels,s.pixels,n,t)&&r.push([e,i])}return l(a.length,r)}async snapshot(){this.render(),await new Promise(e=>setTimeout(e,0));const{snapshot:e}=this.config;return await this.renderer.extract.base64({target:this.components.appContainer,format:e.format,quality:e.quality,resolution:e.resolution,antialias:e.antialias})}async snapshotByData({map:e,path:t,roomProperties:n,customElements:a,forbiddenSweepZones:r,forbiddenMopZones:i,virtualWalls:o,detectedObjects:s},h={}){const p=`SNAPSHOT_${d()}`;c.log(`[MapApplication] ${p} snapshot start`);const m=new O(p);try{if(await m.initialize({config:this.config,runtime:h}),!e)throw new Error("Map data is required");if(e.startsWith("7b22")){const{decodeMapStructured:t}=await import("@ray-js/robot-protocol"),n=t(e);await m.drawMap(n)}else{const{decodeMap:t}=await import("@ray-js/robot-protocol"),n=t(e);if(!n)throw new Error("Failed to decode raster map data");await m.drawRasterMap(n)}if(t){const{decodePath:e}=await import("@ray-js/robot-protocol"),n=e(t);m.drawPath(n)}n&&n.length>0&&m.drawRoomProperty(n),r&&r.length>0&&m.drawForbiddenSweepZones(r),i&&i.length>0&&m.drawForbiddenMopZones(i),o&&o.length>0&&m.drawVirtualWalls(o),s&&s.length>0&&await m.drawDetectedObjects(s),a&&a.length>0&&await m.drawCustomElements(a);const d=await m.snapshot();return c.log(`[MapApplication] ${p} snapshot completed successfully`),d}catch(e){throw c.error(`[MapApplication] ${p} snapshot other map failed:`,e),e}finally{c.log(`[MapApplication] ${p} destroy`),m.destroy()}}renderOnce(){c.log("[Pixi] renderOnce"),this.render()}renderOnceNextFrame(){this.pendingAsyncRender||(this.pendingAsyncRender=!0,requestAnimationFrame(()=>{c.log("[Pixi] renderOnceNextFrame"),this.render(),this.pendingAsyncRender=!1}))}requestRender(e,t=!1){t?(this.tickerState.renderReasons.add(e),this.ticker.started||(c.debug(`🎬 [Ticker] START: ${e}`),this.ticker.start())):this.renderOnceNextFrame()}stopRender(e){this.tickerState.renderReasons.delete(e),0===this.tickerState.renderReasons.size&&this.scheduleStopRender("final",100)}destroy(){h.unregisterInstance(this.instanceKey),this.tickerState.renderTimer&&clearTimeout(this.tickerState.renderTimer),this.tickerState.renderReasons.clear(),this.emitter.all.clear(),document.removeEventListener("visibilitychange",this.onVisibilityChange),this.managers.pathManager.destroy(),this.managers.mapManager.destroy(),this.managers.controlsManager.destroy(),this.managers.detectedObjectManager.destroy(),this.managers.customElementsManager.destroy(),this.managers.roomsManager.destroy(),this.components.interaction.destroy(),this.components.viewportContainer.destroy(),this.components.appContainer.destroy(),super.destroy()}initializeViewportContainer(){this.components.viewportContainer=new u(this.config,this.containerElement),this.stage.addChild(this.components.viewportContainer)}initializeAppContainer(){this.components.appContainer=new w,this.components.interaction.addChild(this.components.appContainer)}initializeInteraction(){this.components.interaction=new a,this.components.viewportContainer.addChild(this.components.interaction)}scheduleStopRender(e,t){this.tickerState.renderTimer&&clearTimeout(this.tickerState.renderTimer),this.tickerState.renderTimer=setTimeout(()=>{this.tickerState.renderReasons.delete(e),0===this.tickerState.renderReasons.size&&(c.debug("⏸️ [Ticker] STOP"),this.ticker.stop())},t)}generateZonePoints(e,t,n){const a=this.getViewportCenterPoint()||{x:0,y:0},r=this.metersToPixels(e)/2,i=a.x+t,o=a.y+n;return[{x:i-r,y:o-r},{x:i+r,y:o-r},{x:i+r,y:o+r},{x:i-r,y:o+r}]}preloadAssets(){const e=this.config.robot.icon.src,t=this.config.chargingStation.icon.src,a=[];n.add({alias:"robot",src:e}),a.push("robot"),n.add({alias:"chargingStation",src:t}),a.push("chargingStation"),n.add({alias:"deleteIcon",src:this.config.controls.deleteIconSrc}),a.push("deleteIcon"),n.add({alias:"rotateIcon",src:this.config.controls.rotateIconSrc}),a.push("rotateIcon"),n.add({alias:"scaleIcon",src:this.config.controls.scaleIconSrc}),a.push("scaleIcon"),n.add({alias:"moveIcon",src:this.config.controls.moveIconSrc}),a.push("moveIcon"),n.add({alias:"checkmark",src:this.config.room.selectionIndicator.iconSrc}),a.push("checkmark"),n.add({alias:"spotIcon",src:this.config.controls.spot.iconSrc}),a.push("spotIcon"),this.config.room.property.cleanMode.assets.forEach((e,t)=>{const r=`cleanMode_${t}`;n.add({alias:r,src:e}),a.push(r)}),this.config.room.property.suction.assets.forEach((e,t)=>{const r=`fan_${t}`;n.add({alias:r,src:e}),a.push(r)}),this.config.room.property.cistern.assets.forEach((e,t)=>{const r=`water_${t}`;n.add({alias:r,src:e}),a.push(r)}),this.config.room.property.cleanTimes.assets.forEach((e,t)=>{const r=`cleanTimes${t+1}`;n.add({alias:r,src:e}),a.push(r)}),this.config.room.floorType.assets.forEach((e,t)=>{if(!e)return;const r=`floorType${t}`;n.add({alias:r,src:e}),a.push(r)}),n.backgroundLoad(a)}onVisibilityChange=()=>{"visible"===document.visibilityState||this.components.interaction?.clearTouches()}}export{O as MapApplication};
@@ -1 +1 @@
1
- import{Container as t,Graphics as o,GraphicsContext as e}from"pixi.js";import{RASTER_CHUNK_SIZE as i}from"../../constant/index.js";import{LAYER_ROOM_FILL as s}from"../../application/AppContainer.js";import{ClickHandler as r}from"../../mixins/ClickHandler.js";import{Logger as a}from"../../utils/logger.js";import{useAppService as n}from"../../application/AppService.js";class l extends t{roomGraphicsMap=new Map;roomContextMap=new Map;roomClickHandlerMap=new Map;unsubscribeFns=[];mapWidth=0;rasterRoomDataMap=new Map;constructor(){super({isRenderGroup:!0}),n().appContainer.addToLayer(s,this)}draw(t){const i=n();this.clearRooms();const s=i.roomConfig,{selectRoomIds:a,enableRoomSelection:l}=i.runtimeSnapshot;t.forEach((t,i)=>{const n=t.id>=255,c=new o,h=new e,p=new e;if(n)h.setFillStyle({color:t.color}),p.setFillStyle({color:t.color});else{const t=i%s.colors.active.length,o=i%s.colors.inactive.length,e=s.colors.active[t],r=s.colors.inactive[o];h.setFillStyle({color:e}),p.setFillStyle({color:r})}if(h.poly(t.polyPoints).fill(),p.poly(t.polyPoints).fill(),t.outlinePoints.forEach(t=>{h.rect(t.x,t.y,1,1).fill(),p.rect(t.x,t.y,1,1).fill()}),c.context=n?h:l&&!a.includes(t.id)?p:h,!n){const o=new r(c,{clickThreshold:10,onClick:()=>{this.handleRoomClick(t.id)}});this.roomClickHandlerMap.set(t.id,o)}this.roomGraphicsMap.set(t.id,c),this.roomContextMap.set(t.id,{activeContext:h,inactiveContext:p}),this.addChild(c)})}drawRaster(t){const o=n();if(this.clearRooms(),this.mapWidth=t.width,0===t.sortedRooms.length)return;const{selectRoomIds:e,enableRoomSelection:i}=o.runtimeSnapshot;t.sortedRooms.forEach(t=>{this.drawRasterRoom(t,i,e)})}drawRasterRoom(t,s,a){const{roomId:n,pixelIndices:l,activeColor:c,inactiveColor:h}=t,p=new o,m=new e,d=new e;m.setFillStyle({color:c}),d.setFillStyle({color:h}),this.drawPixelPointsInBatches(m,l,i,this.mapWidth),this.drawPixelPointsInBatches(d,l,i,this.mapWidth);const f="number"==typeof n,C=!s||f&&a.includes(n);if(p.context=s&&f&&!C?d:m,f){const t=new r(p,{clickThreshold:10,onClick:()=>{this.handleRoomClick(n)}});this.roomClickHandlerMap.set(n,t)}this.roomGraphicsMap.set(n,p),this.roomContextMap.set(n,{activeContext:m,inactiveContext:d}),this.rasterRoomDataMap.set(n,t),this.addChild(p)}drawPixelPointsInBatches(t,o,e,i){for(let s=0;s<o.length;s+=e){const r=Math.min(s+e,o.length);for(let e=s;e<r;e++){const s=o[e],r=s%i,a=Math.floor(s/i);t.rect(r,a,1,1)}t.fill()}}handleRoomClick(t){const o=n();o.events?.onClickRoom?.(o.getRoomData(t)??{id:t})}setRoomStateBySelectIds(t){const o=n(),{enableRoomSelection:e}=o.runtimeSnapshot;this.roomGraphicsMap.forEach((o,i)=>{if("number"==typeof i){const s=!e||t.includes(i),r=this.roomContextMap.get(i);r&&(o.context=s?r.activeContext:r.inactiveContext)}})}setRoomState(t,o){const e=this.roomGraphicsMap.get(t),i=this.roomContextMap.get(t);e&&i?"number"==typeof t&&(e.context=o?i.activeContext:i.inactiveContext):a.warn(`Room ${t} not found`)}setAllRoomsState(t){this.roomGraphicsMap.forEach((o,e)=>{"number"==typeof e&&this.setRoomState(e,t)})}getRoomGraphicsMap(){const t=new Map;return this.roomGraphicsMap.forEach((o,e)=>{"number"==typeof e&&t.set(e,o)}),t}getRasterRoomData(t){return this.rasterRoomDataMap.get(t)||null}getMapWidth(){return this.mapWidth}clearRooms(){0===this.children.length&&0===this.roomGraphicsMap.size||(this.removeChildren(),this.roomClickHandlerMap.forEach(t=>{try{t.destroy()}catch(t){a.warn("Error destroying click handler:",t)}}),this.roomClickHandlerMap.clear(),this.roomGraphicsMap.clear(),this.roomContextMap.clear(),this.rasterRoomDataMap.clear())}destroy(){this.unsubscribeFns.forEach(t=>t()),this.unsubscribeFns=[],this.clearRooms(),super.destroy()}}export{l as RoomFill};
1
+ import{Container as o,Graphics as t,GraphicsContext as e}from"pixi.js";import{RASTER_CHUNK_SIZE as i}from"../../constant/index.js";import{LAYER_ROOM_FILL as s}from"../../application/AppContainer.js";import{ClickHandler as r}from"../../mixins/ClickHandler.js";import{Logger as a}from"../../utils/logger.js";import{useAppService as n}from"../../application/AppService.js";class l extends o{roomGraphicsMap=new Map;roomContextMap=new Map;roomClickHandlerMap=new Map;unsubscribeFns=[];mapWidth=0;rasterRoomDataMap=new Map;constructor(){super({isRenderGroup:!0}),n().appContainer.addToLayer(s,this)}draw(o){const i=n();this.clearRooms();const s=i.roomConfig,{selectRoomIds:a,enableRoomSelection:l}=i.runtimeSnapshot;o.forEach(o=>{const i=o.id>=255,n=new t,c=new e,h=new e;if(i)c.setFillStyle({color:o.color}),h.setFillStyle({color:o.color});else{const t=o.colorIndex??0,e=s.colors.active[t%s.colors.active.length],i=s.colors.inactive[t%s.colors.inactive.length];c.setFillStyle({color:e}),h.setFillStyle({color:i})}if(c.poly(o.polyPoints).fill(),h.poly(o.polyPoints).fill(),o.outlinePoints.forEach(o=>{c.rect(o.x,o.y,1,1).fill(),h.rect(o.x,o.y,1,1).fill()}),n.context=i?c:l&&!a.includes(o.id)?h:c,!i){const t=new r(n,{clickThreshold:10,onClick:()=>{this.handleRoomClick(o.id)}});this.roomClickHandlerMap.set(o.id,t)}this.roomGraphicsMap.set(o.id,n),this.roomContextMap.set(o.id,{activeContext:c,inactiveContext:h}),this.addChild(n)})}drawRaster(o){const t=n();if(this.clearRooms(),this.mapWidth=o.width,0===o.sortedRooms.length)return;const{selectRoomIds:e,enableRoomSelection:i}=t.runtimeSnapshot;o.sortedRooms.forEach(o=>{this.drawRasterRoom(o,i,e)})}drawRasterRoom(o,s,a){const{roomId:n,pixelIndices:l,activeColor:c,inactiveColor:h}=o,p=new t,m=new e,d=new e;m.setFillStyle({color:c}),d.setFillStyle({color:h}),this.drawPixelPointsInBatches(m,l,i,this.mapWidth),this.drawPixelPointsInBatches(d,l,i,this.mapWidth);const f="number"==typeof n,C=!s||f&&a.includes(n);if(p.context=s&&f&&!C?d:m,f){const o=new r(p,{clickThreshold:10,onClick:()=>{this.handleRoomClick(n)}});this.roomClickHandlerMap.set(n,o)}this.roomGraphicsMap.set(n,p),this.roomContextMap.set(n,{activeContext:m,inactiveContext:d}),this.rasterRoomDataMap.set(n,o),this.addChild(p)}drawPixelPointsInBatches(o,t,e,i){for(let s=0;s<t.length;s+=e){const r=Math.min(s+e,t.length);for(let e=s;e<r;e++){const s=t[e],r=s%i,a=Math.floor(s/i);o.rect(r,a,1,1)}o.fill()}}handleRoomClick(o){const t=n();t.events?.onClickRoom?.(t.getRoomData(o)??{id:o})}setRoomStateBySelectIds(o){const t=n(),{enableRoomSelection:e}=t.runtimeSnapshot;this.roomGraphicsMap.forEach((t,i)=>{if("number"==typeof i){const s=!e||o.includes(i),r=this.roomContextMap.get(i);r&&(t.context=s?r.activeContext:r.inactiveContext)}})}setRoomState(o,t){const e=this.roomGraphicsMap.get(o),i=this.roomContextMap.get(o);e&&i?"number"==typeof o&&(e.context=t?i.activeContext:i.inactiveContext):a.warn(`Room ${o} not found`)}setAllRoomsState(o){this.roomGraphicsMap.forEach((t,e)=>{"number"==typeof e&&this.setRoomState(e,o)})}getRoomGraphicsMap(){const o=new Map;return this.roomGraphicsMap.forEach((t,e)=>{"number"==typeof e&&o.set(e,t)}),o}getRasterRoomData(o){return this.rasterRoomDataMap.get(o)||null}getMapWidth(){return this.mapWidth}clearRooms(){0===this.children.length&&0===this.roomGraphicsMap.size||(this.removeChildren(),this.roomClickHandlerMap.forEach(o=>{try{o.destroy()}catch(o){a.warn("Error destroying click handler:",o)}}),this.roomClickHandlerMap.clear(),this.roomGraphicsMap.clear(),this.roomContextMap.clear(),this.rasterRoomDataMap.clear())}destroy(){this.unsubscribeFns.forEach(o=>o()),this.unsubscribeFns=[],this.clearRooms(),super.destroy()}}export{l as RoomFill};
@@ -1 +1 @@
1
- import{Container as o,Assets as r,TilingSprite as e,Graphics as t}from"pixi.js";import{calculateMergedBounds as s}from"../../utils/algorithm.js";import{LAYER_ROOM_FLOOR_TYPE as a}from"../../application/AppContainer.js";import{Logger as p}from"../../utils/logger.js";import{useAppService as i}from"../../application/AppService.js";class l extends o{floorTypeMap=new Map;floorTypeMasks=new Map;floorTypeToRooms=new Map;constructor(){super({isRenderGroup:!0}),i().appContainer.addToLayer(a,this)}async createFloorTypes(o){if(!i().runtimeSnapshot.showRoomFloorType)return;this.clearFloorTypes();const r=this.groupRoomsByFloorType(o),e=[];for(const[o,t]of r)e.push(this.createMergedFloorType(o,t));await Promise.all(e)}groupRoomsByFloorType(o){const r=new Map,e=i();return o.forEach((o,t)=>{const s=e.getRoomData(t),a=s?.floorType||0;a>=0&&(r.has(a)||r.set(a,[]),r.get(a).push({roomId:t,graphics:o}))}),r}async createMergedFloorType(o,t){const a=i(),{assets:l,opacity:n,scale:c}=a.roomConfig.floorType,h="floorType"+o%l.length;if(!h)return void p.warn(`No texture asset configured for floorType: ${o}`);const y=await r.load(h);if(!y)return void p.warn(`Floor material texture not found: ${h}`);const f=t.map(({graphics:o})=>o.getLocalBounds()),d=s(f),m=new e({texture:y,width:d.width,height:d.height});m.x=d.x,m.y=d.y,m.alpha=n,m.tileScale.set(c);const T=this.createMergedMask(t.map(({graphics:o})=>o));m.mask=T,this.addChild(m),this.floorTypeMap.set(o,m),this.floorTypeMasks.set(o,T),this.floorTypeToRooms.set(o,new Set(t.map(({roomId:o})=>o)))}createMergedMask(r){const e=new o;return r.forEach(o=>{const r=new t;r.context=o.context.clone(),e.addChild(r)}),e}clearFloorTypes(){this.floorTypeMap.forEach(o=>{try{this.removeChild(o),o.destroy()}catch(o){p.warn("Error destroying floor material:",o)}}),this.floorTypeMap.clear(),this.floorTypeMasks.forEach(o=>{try{o.destroy()}catch(o){p.warn("Error destroying floor mask:",o)}}),this.floorTypeMasks.clear(),this.floorTypeToRooms.clear()}destroy(){this.clearFloorTypes(),super.destroy()}}export{l as RoomFloorType};
1
+ import{Container as o,Assets as r,TilingSprite as e,Graphics as t}from"pixi.js";import{calculateMergedBounds as s}from"../../utils/algorithm.js";import{LAYER_ROOM_FLOOR_TYPE as a}from"../../application/AppContainer.js";import{Logger as p}from"../../utils/logger.js";import{useAppService as i}from"../../application/AppService.js";class l extends o{floorTypeMap=new Map;floorTypeMasks=new Map;floorTypeToRooms=new Map;constructor(){super({isRenderGroup:!0}),i().appContainer.addToLayer(a,this)}async createFloorTypes(o){if(!i().runtimeSnapshot.showRoomFloorType)return;this.clearFloorTypes();const r=this.groupRoomsByFloorType(o),e=[];for(const[o,t]of r)e.push(this.createMergedFloorType(o,t));await Promise.all(e)}groupRoomsByFloorType(o){const r=new Map,e=i();return o.forEach((o,t)=>{const s=e.getRoomData(t),a=s?.floorType||0;a>=0&&(r.has(a)||r.set(a,[]),r.get(a).push({roomId:t,graphics:o}))}),r}async createMergedFloorType(o,t){const a=i(),{assets:l,opacity:n,scale:c}=a.roomConfig.floorType,h=o%l.length,y=`floorType${h}`;if(!l[h])return void p.warn(`No texture asset configured for floorType: ${o}`);const f=await r.load(y);if(!f)return void p.warn(`Floor material texture not found: ${y}`);const d=t.map(({graphics:o})=>o.getLocalBounds()),m=s(d),T=new e({texture:f,width:m.width,height:m.height});T.x=m.x,T.y=m.y,T.alpha=n,T.tileScale.set(c);const g=this.createMergedMask(t.map(({graphics:o})=>o));T.mask=g,this.addChild(T),this.floorTypeMap.set(o,T),this.floorTypeMasks.set(o,g),this.floorTypeToRooms.set(o,new Set(t.map(({roomId:o})=>o)))}createMergedMask(r){const e=new o;return r.forEach(o=>{const r=new t;r.context=o.context.clone(),e.addChild(r)}),e}clearFloorTypes(){this.floorTypeMap.forEach(o=>{try{this.removeChild(o),o.destroy()}catch(o){p.warn("Error destroying floor material:",o)}}),this.floorTypeMap.clear(),this.floorTypeMasks.forEach(o=>{try{o.destroy()}catch(o){p.warn("Error destroying floor mask:",o)}}),this.floorTypeMasks.clear(),this.floorTypeToRooms.clear()}destroy(){this.clearFloorTypes(),super.destroy()}}export{l as RoomFloorType};
@@ -1 +1 @@
1
- import{Text as o,TextStyle as e}from"pixi.js";import{useAppService as t}from"../../application/AppService.js";class n extends o{roomId;roomIndex;constructor(o){const n=t(),{nameLabel:i,colors:r}=n.roomConfig,m=r.name[o.index%r.name.length],s=new e({fontSize:i.fontSize,fontFamily:i.fontFamily,fontWeight:i.fontWeight,fill:m,align:"center"});super({text:o.name||"Unknown",style:s}),this.roomId=o.id,this.roomIndex=o.index,this.anchor.set(.5)}updateName(o){this.text=o}updateColor(o){const e=t(),{colors:n}=e.roomConfig,i=o??n.name[this.roomIndex%n.name.length];this.style.fill=i}}export{n as RoomName};
1
+ import{Text as o,TextStyle as e}from"pixi.js";import{useAppService as n}from"../../application/AppService.js";class t extends o{roomId;roomIndex;colorIndex;constructor(o){const t=n(),{nameLabel:i,colors:r}=t.roomConfig,l=o.colorIndex??o.index,s=r.name[l%r.name.length],m=new e({fontSize:i.fontSize,fontFamily:i.fontFamily,fontWeight:i.fontWeight,fill:s,align:"center"});super({text:o.name||"Unknown",style:m}),this.roomId=o.id,this.roomIndex=o.index,this.colorIndex=l,this.anchor.set(.5)}updateName(o){this.text=o}updateColor(o){const e=n(),{colors:t}=e.roomConfig,i=o??t.name[this.colorIndex%t.name.length];this.style.fill=i}}export{t as RoomName};
@@ -1 +1 @@
1
- import{Container as e,Graphics as t,Text as i,TextStyle as o}from"pixi.js";import{useAppService as n}from"../../application/AppService.js";import{EnhancedSprite as s}from"../Base/EnhancedSprite.js";class r extends e{background;cleanModeIcon;suctionIcon;cisternIcon;cleanTimesIcon;orderContainer;orderBackground;orderText;bubble=null;isFolded=!1;roomId;constructor(r){super();const l=n(),c=l.roomConfig;this.roomId=r.id,this.background=new t;const{property:h,colors:{propertyTheme:d}}=c;c.property.foldable&&(this.bubble=new t);const a=d[r.index%d.length];this.cleanModeIcon=new s,this.cleanModeIcon.tint=a,this.cleanModeIcon.anchor.set(0,0),this.suctionIcon=new s,this.suctionIcon.tint=a,this.suctionIcon.anchor.set(0,0),this.cisternIcon=new s,this.cisternIcon.tint=a,this.cisternIcon.anchor.set(0,0),this.cleanTimesIcon=new s,this.cleanTimesIcon.tint=a,this.cleanTimesIcon.anchor.set(0,0),this.orderContainer=new e,this.orderBackground=new t,this.orderText=new i({text:"",style:new o({fontSize:h.cleanOrder.fontSize,fontFamily:h.cleanOrder.fontFamily,fontWeight:h.cleanOrder.fontWeight,fill:h.cleanOrder.color,align:"center",trim:!0})}),this.orderText.anchor.set(.5,.5),this.orderContainer.addChild(this.orderBackground),this.orderContainer.addChild(this.orderText),this.addChild(this.background),this.bubble&&this.addChild(this.bubble),this.addChild(this.cleanModeIcon),this.addChild(this.suctionIcon),this.addChild(this.cisternIcon),this.addChild(this.cleanTimesIcon),this.addChild(this.orderContainer),this.visible=l.runtimeSnapshot.showRoomProperty,this.updateProperty(r)}async updateProperty(e){await this.updateIcons(e),this.updateBackground()}getDisplayElements(e){const t=n(),{displayOrders:i}=t.roomConfig.property,{showRoomOrder:o,showRoomProperty:s}=t.runtimeSnapshot,r=e.order||0,l=o&&r>0,c=s&&i.includes("cleanMode"),h=s&&i.includes("suction"),d=s&&i.includes("cistern"),a=s&&i.includes("cleanTimes")&&e.cleanTimes>0,u={cleanMode:{element:this.cleanModeIcon,show:c,isOrder:!1},suction:{element:this.suctionIcon,show:h,isOrder:!1},cistern:{element:this.cisternIcon,show:d,isOrder:!1},cleanTimes:{element:this.cleanTimesIcon,show:a,isOrder:!1}},b=[];return l&&b.push({element:this.orderContainer,show:!0,isOrder:!0}),i.forEach(e=>{const t=u[e];t&&t.show&&b.push(t)}),{shouldShowOrder:l,shouldShowCleanMode:c,shouldShowSuction:h,shouldShowCistern:d,shouldShowCleanTimes:a,elementsToShow:b,orderValue:r}}async updateIcons(e){const t=n(),{iconWidth:i,iconHeight:o,container:s,cleanOrder:r,foldable:l,iconGap:c}=t.roomConfig.property,{propertyTheme:h}=t.roomConfig.colors,{paddingHorizontal:d,paddingVertical:a}=s,{shouldShowOrder:u,shouldShowCleanMode:b,shouldShowSuction:p,shouldShowCistern:g,shouldShowCleanTimes:m,elementsToShow:I,orderValue:C}=this.getDisplayElements(e);this.orderContainer.visible=u,this.cleanModeIcon.visible=b,this.suctionIcon.visible=p,this.cisternIcon.visible=g,this.cleanTimesIcon.visible=m,l&&this.isFolded&&(this.orderContainer.visible=!1,this.cleanModeIcon.visible=!1,this.suctionIcon.visible=!1,this.cisternIcon.visible=!1,this.cleanTimesIcon.visible=!1);const f=[];if(b&&f.push(this.cleanModeIcon.loadTextureAndSetSize(`cleanMode_${e.cleanMode}`,{width:i,height:o,sizeFixed:!1})),p&&f.push(this.suctionIcon.loadTextureAndSetSize(`fan_${e.suction}`,{width:i,height:o,sizeFixed:!1})),g&&f.push(this.cisternIcon.loadTextureAndSetSize(`water_${e.cistern}`,{width:i,height:o,sizeFixed:!1})),m){const t=e.cleanTimes||1;f.push(this.cleanTimesIcon.loadTextureAndSetSize(`cleanTimes${t}`,{width:i,height:o,sizeFixed:!1}))}await Promise.all(f),u&&(this.orderText.text=C.toString(),this.orderBackground.clear(),this.orderBackground.setFillStyle({color:h[e.index%h.length]}),this.orderBackground.circle(i/2,o/2,i/2).fill(),this.orderText.position.set(i/2,o/2));let w=d;I.forEach((e,t)=>{const{element:o,isOrder:n}=e;o.position.set(w,a),w+=i,t<I.length-1&&(w+=n?r.gapRight:c)})}updateBackground(){const e=n().roomConfig,{container:t,foldable:i}=e.property,{borderRadius:o,tailHeight:s,tailWidth:r,backgroundColor:l}=t,c=this.calculateContentWidth(),h=this.calculateContentHeight(),d=Math.min(r,c/2);if(this.background.clear(),this.bubble&&this.bubble.clear(),this.background.setFillStyle({color:l}),this.background.roundRect(0,0,c,h,o).fill(),i&&this.bubble){const e=(c-d)/2;this.bubble.setFillStyle({color:l}),this.bubble.poly([e,h-1,e+d,h-1,e+d/2,h+s]).fill()}}calculateContentWidth(){const e=n(),{iconWidth:t,container:i,cleanOrder:o,iconGap:s}=e.roomConfig.property,{paddingHorizontal:r}=i,l=e.getRoomData(this.roomId);if(!l)return 2*r;const{elementsToShow:c}=this.getDisplayElements(l);let h=r;return c.forEach((e,i)=>{const{isOrder:n}=e;h+=t,i<c.length-1&&(h+=n?o.gapRight:s)}),h+=r,h}calculateContentHeight(){const e=n().roomConfig,{iconHeight:t,container:i}=e.property;return i.paddingVertical+t+i.paddingVertical}getTotalHeight(){const e=n(),{foldable:t,container:i}=e.roomConfig.property,{tailHeight:o}=i;return this.calculateContentHeight()+(t?o:0)}getTotalWidth(){return this.calculateContentWidth()}setFolded(e){const t=n(),{foldable:i}=t.roomConfig.property;if(i)if(this.isFolded=e,e)this.background.visible=!1,this.cleanModeIcon.visible=!1,this.suctionIcon.visible=!1,this.cisternIcon.visible=!1,this.cleanTimesIcon.visible=!1,this.orderContainer.visible=!1,this.bubble&&(this.bubble.visible=!0,this.bubble.rotation=Math.PI,this.repositionFoldedBubble());else{this.background.visible=!0,this.bubble&&(this.bubble.visible=!0,this.bubble.rotation=0,this.bubble.position.set(0,0)),this.updateBackground();const e=t.getRoomData(this.roomId);e&&this.updateIcons(e)}}isFoldedState(){const e=n(),{foldable:t}=e.roomConfig.property;return!!t&&this.isFolded}repositionFoldedBubble(){const e=n(),{foldable:t}=e.roomConfig.property;if(!t||!this.bubble)return;const i=e.roomConfig,{tailHeight:o}=i.property.container,s=this.calculateContentWidth(),r=this.calculateContentHeight(),l=s/2;this.bubble.position.set(l,r+o/2)}destroy(){this.cleanModeIcon?.destroy(),this.suctionIcon?.destroy(),this.cisternIcon?.destroy(),this.cleanTimesIcon?.destroy(),super.destroy()}}export{r as RoomProperty};
1
+ import{Container as e,Graphics as t,Text as o,TextStyle as i}from"pixi.js";import{useAppService as n}from"../../application/AppService.js";import{EnhancedSprite as s}from"../Base/EnhancedSprite.js";class r extends e{background;cleanModeIcon;suctionIcon;cisternIcon;cleanTimesIcon;orderContainer;orderBackground;orderText;bubble=null;isFolded=!1;roomId;colorIndex;constructor(r){super();const l=n(),c=l.roomConfig;this.roomId=r.id,this.colorIndex=r.colorIndex??r.index,this.background=new t;const{property:h,colors:{propertyTheme:d}}=c;c.property.foldable&&(this.bubble=new t);const a=d[this.colorIndex%d.length];this.cleanModeIcon=new s,this.cleanModeIcon.tint=a,this.cleanModeIcon.anchor.set(0,0),this.suctionIcon=new s,this.suctionIcon.tint=a,this.suctionIcon.anchor.set(0,0),this.cisternIcon=new s,this.cisternIcon.tint=a,this.cisternIcon.anchor.set(0,0),this.cleanTimesIcon=new s,this.cleanTimesIcon.tint=a,this.cleanTimesIcon.anchor.set(0,0),this.orderContainer=new e,this.orderBackground=new t,this.orderText=new o({text:"",style:new i({fontSize:h.cleanOrder.fontSize,fontFamily:h.cleanOrder.fontFamily,fontWeight:h.cleanOrder.fontWeight,fill:h.cleanOrder.color,align:"center",trim:!0})}),this.orderText.anchor.set(.5,.5),this.orderContainer.addChild(this.orderBackground),this.orderContainer.addChild(this.orderText),this.addChild(this.background),this.bubble&&this.addChild(this.bubble),this.addChild(this.cleanModeIcon),this.addChild(this.suctionIcon),this.addChild(this.cisternIcon),this.addChild(this.cleanTimesIcon),this.addChild(this.orderContainer),this.visible=l.runtimeSnapshot.showRoomProperty,this.updateProperty(r)}async updateProperty(e){await this.updateIcons(e),this.updateBackground()}getDisplayElements(e){const t=n(),{displayOrders:o}=t.roomConfig.property,{showRoomOrder:i,showRoomProperty:s}=t.runtimeSnapshot,r=e.order||0,l=i&&r>0,c=s&&o.includes("cleanMode"),h=s&&o.includes("suction"),d=s&&o.includes("cistern"),a=s&&o.includes("cleanTimes")&&e.cleanTimes>0,u={cleanMode:{element:this.cleanModeIcon,show:c,isOrder:!1},suction:{element:this.suctionIcon,show:h,isOrder:!1},cistern:{element:this.cisternIcon,show:d,isOrder:!1},cleanTimes:{element:this.cleanTimesIcon,show:a,isOrder:!1}},b=[];return l&&b.push({element:this.orderContainer,show:!0,isOrder:!0}),o.forEach(e=>{const t=u[e];t&&t.show&&b.push(t)}),{shouldShowOrder:l,shouldShowCleanMode:c,shouldShowSuction:h,shouldShowCistern:d,shouldShowCleanTimes:a,elementsToShow:b,orderValue:r}}async updateIcons(e){const t=n(),{iconWidth:o,iconHeight:i,container:s,cleanOrder:r,foldable:l,iconGap:c}=t.roomConfig.property,{propertyTheme:h}=t.roomConfig.colors,{paddingHorizontal:d,paddingVertical:a}=s,{shouldShowOrder:u,shouldShowCleanMode:b,shouldShowSuction:p,shouldShowCistern:g,shouldShowCleanTimes:m,elementsToShow:I,orderValue:C}=this.getDisplayElements(e);this.orderContainer.visible=u,this.cleanModeIcon.visible=b,this.suctionIcon.visible=p,this.cisternIcon.visible=g,this.cleanTimesIcon.visible=m,l&&this.isFolded&&(this.orderContainer.visible=!1,this.cleanModeIcon.visible=!1,this.suctionIcon.visible=!1,this.cisternIcon.visible=!1,this.cleanTimesIcon.visible=!1);const f=[];if(b&&f.push(this.cleanModeIcon.loadTextureAndSetSize(`cleanMode_${e.cleanMode}`,{width:o,height:i,sizeFixed:!1})),p&&f.push(this.suctionIcon.loadTextureAndSetSize(`fan_${e.suction}`,{width:o,height:i,sizeFixed:!1})),g&&f.push(this.cisternIcon.loadTextureAndSetSize(`water_${e.cistern}`,{width:o,height:i,sizeFixed:!1})),m){const t=e.cleanTimes||1;f.push(this.cleanTimesIcon.loadTextureAndSetSize(`cleanTimes${t}`,{width:o,height:i,sizeFixed:!1}))}await Promise.all(f),u&&(this.orderText.text=C.toString(),this.orderBackground.clear(),this.orderBackground.setFillStyle({color:h[this.colorIndex%h.length]}),this.orderBackground.circle(o/2,i/2,o/2).fill(),this.orderText.position.set(o/2,i/2));let w=d;I.forEach((e,t)=>{const{element:i,isOrder:n}=e;i.position.set(w,a),w+=o,t<I.length-1&&(w+=n?r.gapRight:c)})}updateBackground(){const e=n().roomConfig,{container:t,foldable:o}=e.property,{borderRadius:i,tailHeight:s,tailWidth:r,backgroundColor:l}=t,c=this.calculateContentWidth(),h=this.calculateContentHeight(),d=Math.min(r,c/2);if(this.background.clear(),this.bubble&&this.bubble.clear(),this.background.setFillStyle({color:l}),this.background.roundRect(0,0,c,h,i).fill(),o&&this.bubble){const e=(c-d)/2;this.bubble.setFillStyle({color:l}),this.bubble.poly([e,h-1,e+d,h-1,e+d/2,h+s]).fill()}}calculateContentWidth(){const e=n(),{iconWidth:t,container:o,cleanOrder:i,iconGap:s}=e.roomConfig.property,{paddingHorizontal:r}=o,l=e.getRoomData(this.roomId);if(!l)return 2*r;const{elementsToShow:c}=this.getDisplayElements(l);let h=r;return c.forEach((e,o)=>{const{isOrder:n}=e;h+=t,o<c.length-1&&(h+=n?i.gapRight:s)}),h+=r,h}calculateContentHeight(){const e=n().roomConfig,{iconHeight:t,container:o}=e.property;return o.paddingVertical+t+o.paddingVertical}getTotalHeight(){const e=n(),{foldable:t,container:o}=e.roomConfig.property,{tailHeight:i}=o;return this.calculateContentHeight()+(t?i:0)}getTotalWidth(){return this.calculateContentWidth()}setFolded(e){const t=n(),{foldable:o}=t.roomConfig.property;if(o)if(this.isFolded=e,e)this.background.visible=!1,this.cleanModeIcon.visible=!1,this.suctionIcon.visible=!1,this.cisternIcon.visible=!1,this.cleanTimesIcon.visible=!1,this.orderContainer.visible=!1,this.bubble&&(this.bubble.visible=!0,this.bubble.rotation=Math.PI,this.repositionFoldedBubble());else{this.background.visible=!0,this.bubble&&(this.bubble.visible=!0,this.bubble.rotation=0,this.bubble.position.set(0,0)),this.updateBackground();const e=t.getRoomData(this.roomId);e&&this.updateIcons(e)}}isFoldedState(){const e=n(),{foldable:t}=e.roomConfig.property;return!!t&&this.isFolded}repositionFoldedBubble(){const e=n(),{foldable:t}=e.roomConfig.property;if(!t||!this.bubble)return;const o=e.roomConfig,{tailHeight:i}=o.property.container,s=this.calculateContentWidth(),r=this.calculateContentHeight(),l=s/2;this.bubble.position.set(l,r+i/2)}destroy(){this.cleanModeIcon?.destroy(),this.suctionIcon?.destroy(),this.cisternIcon?.destroy(),this.cleanTimesIcon?.destroy(),super.destroy()}}export{r as RoomProperty};
@@ -1 +1 @@
1
- import{Container as t,Graphics as o}from"pixi.js";import{useAppService as i}from"../../application/AppService.js";import{EnhancedSprite as e}from"../Base/EnhancedSprite.js";class c extends t{background;checkmarkIcon;bubble;roomId;constructor(t){super();const c=i().roomConfig;this.roomId=t.id,this.background=new o,this.bubble=new o;const{colors:{selectionIndicatorIcon:n}}=c;this.checkmarkIcon=new e,this.checkmarkIcon.tint=n[t.index%n.length],this.checkmarkIcon.anchor.set(0,0),this.addChild(this.background),this.addChild(this.bubble),this.addChild(this.checkmarkIcon),this.updateIndicator(t)}async updateIndicator(t){const o=i(),{roomSelectionMode:e,enableRoomSelection:c,selectRoomIds:n}=o.runtimeSnapshot;if(!c||"checkmark"!==e)return void(this.visible=!1);const r=n.includes(t.id);await this.showCheckmarkMode(r),this.updateBackground()}async showCheckmarkMode(t){const o=i(),{selectionIndicator:e}=o.roomConfig,{iconWidth:c,iconHeight:n}=e;if(t){this.visible=!0,this.checkmarkIcon.visible=!0,await this.checkmarkIcon.loadTextureAndSetSize("checkmark",{width:c,height:n,sizeFixed:!1});const t=e.containerWidth/2,o=e.containerHeight/2;this.checkmarkIcon.position.set(t-c/2,o-n/2)}else this.visible=!1}updateBackground(){const t=i(),{selectionIndicator:o,colors:e}=t.roomConfig,{containerWidth:c,containerHeight:n,strokeWidth:r,strokeColor:s,borderRadius:a,tailHeight:h,tailWidth:d}=o,l=t.getRoomData(this.roomId);if(!l)return;const k=e.selectionIndicatorBackground[l.index%e.selectionIndicatorBackground.length];if(this.background.clear(),this.bubble.clear(),this.background.setFillStyle({color:k}).roundRect(0,0,c,n,a).fill().setStrokeStyle({color:s,width:r,alignment:0}).stroke(),h>0&&d>0){const t=(c-d)/2;this.bubble.setFillStyle({color:s});const o=n+r;this.bubble.poly([t,o-1,t+d,o-1,t+d/2,o+h]).fill()}}getTotalHeight(){const t=i(),{selectionIndicator:o}=t.roomConfig,{containerHeight:e,tailHeight:c,strokeWidth:n}=o;return e+n+(c>0?c:0)}getTotalWidth(){const t=i(),{selectionIndicator:o}=t.roomConfig;return o.containerWidth}destroy(){this.checkmarkIcon?.destroy(),super.destroy()}}export{c as RoomSelectionIndicator};
1
+ import{Container as t,Graphics as o}from"pixi.js";import{useAppService as i}from"../../application/AppService.js";import{EnhancedSprite as e}from"../Base/EnhancedSprite.js";class c extends t{background;checkmarkIcon;bubble;roomId;constructor(t){super();const c=i().roomConfig;this.roomId=t.id,this.background=new o,this.bubble=new o;const{colors:{selectionIndicatorIcon:n}}=c;this.checkmarkIcon=new e,this.checkmarkIcon.tint=n[t.index%n.length],this.checkmarkIcon.anchor.set(0,0),this.addChild(this.background),this.addChild(this.bubble),this.addChild(this.checkmarkIcon),this.updateIndicator(t)}async updateIndicator(t){const o=i(),{roomSelectionMode:e,enableRoomSelection:c,selectRoomIds:n}=o.runtimeSnapshot;if(!c||"checkmark"!==e)return void(this.visible=!1);const r=n.includes(t.id);await this.showCheckmarkMode(r),this.updateBackground()}async showCheckmarkMode(t){const o=i(),{selectionIndicator:e}=o.roomConfig,{iconWidth:c,iconHeight:n}=e;if(t){this.visible=!0,this.checkmarkIcon.visible=!0,await this.checkmarkIcon.loadTextureAndSetSize("checkmark",{width:c,height:n,sizeFixed:!1});const t=e.containerWidth/2,o=e.containerHeight/2;this.checkmarkIcon.position.set(t-c/2,o-n/2)}else this.visible=!1}updateBackground(){const t=i(),{selectionIndicator:o,colors:e}=t.roomConfig,{containerWidth:c,containerHeight:n,strokeWidth:r,strokeColor:s,borderRadius:a,tailHeight:h,tailWidth:d}=o,l=t.getRoomData(this.roomId);if(!l)return;const k=l.colorIndex??l.index,m=e.selectionIndicatorBackground[k%e.selectionIndicatorBackground.length];if(this.background.clear(),this.bubble.clear(),this.background.setFillStyle({color:m}).roundRect(0,0,c,n,a).fill().setStrokeStyle({color:s,width:r,alignment:0}).stroke(),h>0&&d>0){const t=(c-d)/2;this.bubble.setFillStyle({color:s});const o=n+r;this.bubble.poly([t,o-1,t+d,o-1,t+d/2,o+h]).fill()}}getTotalHeight(){const t=i(),{selectionIndicator:o}=t.roomConfig,{containerHeight:e,tailHeight:c,strokeWidth:n}=o;return e+n+(c>0?c:0)}getTotalWidth(){const t=i(),{selectionIndicator:o}=t.roomConfig;return o.containerWidth}destroy(){this.checkmarkIcon?.destroy(),super.destroy()}}export{c as RoomSelectionIndicator};
@@ -1 +1 @@
1
- import e from"../assets/chargingStation.png.js";import o from"../assets/robot.png.js";import t from"../assets/fan0.png.js";import i from"../assets/fan1.png.js";import r from"../assets/fan2.png.js";import s from"../assets/fan3.png.js";import a from"../assets/fan4.png.js";import n from"../assets/water0.png.js";import f from"../assets/water1.png.js";import l from"../assets/water2.png.js";import d from"../assets/water3.png.js";import c from"../assets/cleanMode0.png.js";import h from"../assets/cleanMode1.png.js";import p from"../assets/cleanMode2.png.js";import m from"../assets/cleanMode3.png.js";import g from"../assets/cleanTimes1.png.js";import b from"../assets/cleanTimes2.png.js";import S from"../assets/controlScale.png.js";import C from"../assets/controlDelete.png.js";import u from"../assets/controlRotate.png.js";import W from"../assets/controlMove.png.js";import k from"../assets/checkmark.png.js";import y from"../assets/spot.png.js";import D from"../assets/floorType1.png.js";import j from"../assets/floorType2.png.js";import x from"../assets/floorType3.png.js";import F from"../assets/carpet.png.js";import A from"../assets/sleep.json.js";import{SPECIAL_ROOM_IDS as O}from"@ray-js/robot-protocol";const w="system-ui, -apple-system, sans-serif",R=["#d7bb46","#4990d7","#58a789","#749cd7","#f2646c","#91be76","#4ec7b1","#4bb3c8","#e7858a","#7fa96e","#efa667","#a3d774","#6b82d8","#75b551","#b392cd","#ed5454"],P={global:{containerTop:"0px",containerLeft:"0px",containerWidth:"100%",containerHeight:"100%",backgroundColor:"#f6f6f6"},map:{autoPaddingPercent:.05,obstacleColor:"#999999",freeColor:"#ebebeb"},room:{colors:{active:["#fae9a3","#a6d0fa","#9ce3c8","#d1e2fa","#fed8da","#d4f0c3","#a1f3e4","#a0e5f3","#fee6e8","#c1e5b1","#fee9d7","#e4fad1","#c8d3fa","#b8ea9c","#f0e5f9","#fdc4c4"],inactive:["#fef5d2","#d5e9fe","#c0f2df","#e7f0fe","#fef0f1","#f0fbe9","#ccfbf3","#caf3fc","#fff3f4","#def5d4","#fef1e6","#f2fee7","#e6ebfe","#d5f7c2","#f3e9fb","#fee2e2"],name:R,propertyTheme:R,selectionIndicatorBackground:R,selectionIndicatorIcon:["#ffffff"],[O.NO_ROOM_DATA]:"#ebebeb",[O.ROOM_GAP]:"#ebebeb",[O.OBSTACLE_ROOM]:"#ebebeb",[O.UNKNOWN_ROOM]:"#ebebeb"},nameLabel:{fontSize:10,fontFamily:w,fontWeight:"500"},property:{displayOrders:["cleanMode","suction","cistern","cleanTimes"],iconWidth:12,iconHeight:12,foldable:!0,offsetX:0,offsetY:4,iconGap:0,container:{backgroundColor:"#ffffff",paddingVertical:1.5,paddingHorizontal:1.5,borderRadius:16,tailHeight:2,tailWidth:10},suction:{assets:[t,i,r,s,a]},cistern:{assets:[n,f,l,d]},cleanMode:{assets:[c,h,p,m]},cleanTimes:{assets:[g,b]},cleanOrder:{color:"#ffffff",fontFamily:w,fontWeight:"400",fontSize:8,gapRight:2}},selectionIndicator:{iconSrc:k,iconWidth:12,iconHeight:12,containerWidth:16,containerHeight:16,strokeWidth:2,strokeColor:"#ffffff",borderRadius:16,offsetY:4,offsetX:0,tailHeight:2,tailWidth:6},floorType:{assets:["",D,j,x],opacity:.1,scale:.2}},path:{lineWidthFixed:!1,incrementalThreshold:5,commonPath:{color:16777215,width:.5},transitionPath:{color:"transparent",width:.5},chargePath:{color:"transparent",width:.5}},carpet:{src:F,opacity:.5,scale:.2},robot:{icon:{sizeFixed:!1,width:8,height:8,src:o},speed:0,rotationCorrection:0,sleepAnimation:{jsonSrc:A,framePrefix:"sleep_",width:16,height:16,sizeFixed:!1,frameCount:96,offsetX:8,offsetY:-8},ringSize:1,ringColor:"rgba(255, 68, 68, 0.2)",ringStrokeWidth:1,ringStrokeColor:"#ffffff",ringStrokeDashed:!0,ringStrokeDashArray:[4,4]},chargingStation:{icon:{sizeFixed:!1,width:8,height:8,src:e},rotationCorrection:0,ringSize:1,ringColor:"rgba(255, 68, 68, 0.2)",ringStrokeWidth:1,ringStrokeColor:"#ffffff",ringStrokeDashed:!0,ringStrokeDashArray:[4,4]},interaction:{zoomRange:{min:.5,max:8},fitMinScale:1,fitMaxScale:4,enableDoubleTapZoom:!0},controls:{iconWrapperWidth:24,iconWrapperHeight:24,iconWrapperBorderRadius:16,iconWidth:12,iconHeight:12,deleteIconSrc:C,rotateIconSrc:u,scaleIconSrc:S,moveIconSrc:W,moveButtonOffset:30,textFontSize:12,textFontFamily:w,textFontWeight:"400",unitLabel:"m",forbiddenSweepZone:{minSize:1,iconWrapperFillColor:"#ff4444",strokeColor:"#ff4444",strokeWidth:2,fillColor:"rgba(255, 68, 68, 0.1)",outlineOffset:16,outlineStrokeColor:"#ff4444",outlineStrokeWidth:2,outlineDashed:!0,outlineDashArray:[4,3],outlineFillColor:"rgba(255, 68, 68, 0.05)",textColor:"#ff4444",textPosition:"bottom",textOffset:10,editing:{isDashed:!1,dashArray:[0,0]},normal:{isDashed:!1,dashArray:[0,0]}},forbiddenMopZone:{minSize:1,iconWrapperFillColor:"#fe8a07",strokeColor:"#fe8a07",strokeWidth:2,fillColor:"rgba(254, 138, 7, 0.1)",outlineOffset:16,outlineStrokeColor:"#fe8a07",outlineStrokeWidth:2,outlineDashed:!0,outlineDashArray:[4,3],outlineFillColor:"rgba(254, 138, 7, 0.05)",textColor:"#fe8a07",textPosition:"bottom",textOffset:10,editing:{isDashed:!1,dashArray:[0,0]},normal:{isDashed:!1,dashArray:[0,0]}},cleanZone:{minSize:1,iconWrapperFillColor:"#5d68fe",strokeColor:"#5d68fe",strokeWidth:2,fillColor:"rgba(93, 104, 254, 0.1)",outlineOffset:16,outlineStrokeColor:"#5d68fe",outlineStrokeWidth:2,outlineDashed:!0,outlineDashArray:[4,3],outlineFillColor:"rgba(93, 104, 254, 0.05)",textColor:"#5d68fe",textPosition:"bottom",textOffset:10,editing:{isDashed:!1,dashArray:[0,0]},normal:{isDashed:!1,dashArray:[0,0]}},virtualWall:{iconWrapperFillColor:"#ff4444",lineWidth:2,lineColor:"#ff4444",hitAreaThickness:30,outlineOffset:16,outlineStrokeColor:"#ff4444",outlineStrokeWidth:2,outlineDashed:!0,outlineDashArray:[4,3],outlineFillColor:"rgba(255, 68, 68, 0.05)",minWidth:1,textColor:"#ff4444",textOffset:10,editing:{isDashed:!1,dashArray:[0,0]},normal:{isDashed:!1,dashArray:[0,0]}},spot:{iconSrc:y,iconSize:8,size:1,strokeColor:"#5d68fe",strokeWidth:2,fillColor:"rgba(93, 104, 254, 0.1)",textColor:"#5d68fe",textPosition:"bottom",textOffset:10,editing:{isDashed:!1,dashArray:[0,0]},normal:{isDashed:!1,dashArray:[0,0]}}},divider:{lineColor:"#ff4444",dashLineWidth:2,dashLineDashArray:[4,3],solidLineWidth:2,endPointSize:12,endPointColor:"#ff4444",endPointStrokeColor:"#ffffff",endPointStrokeWidth:2,hitAreaThickness:30,resetDividerWhenOutOfRoom:!0,defaultExtension:20,defaultDirection:"horizontal"},detectedObject:{height:43,width:38,interactive:!1},heatmap:{cellSize:2,maxDistance:14,smoothIterations:10,heatmapAlpha:.8,colorGradients:["#FF3B30","#FF7A00","#FFA100","#FFD700","#99DD70","#2EC070","#40E0D0","#88D0E9"]},snapshot:{format:"png",quality:1,antialias:!0,resolution:window?.devicePixelRatio||1}},z={dividingRoomId:null,enableRoomSelection:!1,editingForbiddenSweepZoneIds:[],editingForbiddenMopZoneIds:[],editingCleanZoneIds:[],editingVirtualWallIds:[],editingSpotIds:[],roomPropertyFoldIds:[],roomSelectionMode:"checkmark",selectRoomIds:[],showRoomProperty:!1,showRoomOrder:!0,showRoomName:!0,showPath:!0,showChargingStation:!0,showRoomFloorType:!0,showCarpet:!0,showChargingStationRing:!1,showRobotRing:!1,showRobotSleepAnimation:!1};export{P as DEFAULT_CONFIG,z as DEFAULT_RUNTIME_CONFIG,w as TEXT_FONT_FAMILY};
1
+ import o from"../assets/chargingStation.png.js";import e from"../assets/robot.png.js";import t from"../assets/fan0.png.js";import i from"../assets/fan1.png.js";import r from"../assets/fan2.png.js";import s from"../assets/fan3.png.js";import n from"../assets/fan4.png.js";import a from"../assets/water0.png.js";import f from"../assets/water1.png.js";import l from"../assets/water2.png.js";import d from"../assets/water3.png.js";import c from"../assets/cleanMode0.png.js";import h from"../assets/cleanMode1.png.js";import p from"../assets/cleanMode2.png.js";import m from"../assets/cleanMode3.png.js";import g from"../assets/cleanTimes1.png.js";import b from"../assets/cleanTimes2.png.js";import S from"../assets/controlScale.png.js";import C from"../assets/controlDelete.png.js";import u from"../assets/controlRotate.png.js";import W from"../assets/controlMove.png.js";import k from"../assets/checkmark.png.js";import y from"../assets/spot.png.js";import D from"../assets/floorType1.png.js";import j from"../assets/floorType2.png.js";import x from"../assets/floorType3.png.js";import F from"../assets/carpet.png.js";import A from"../assets/sleep.json.js";import{SPECIAL_ROOM_IDS as O}from"@ray-js/robot-protocol";const w="system-ui, -apple-system, sans-serif",R=["#2563b8","#26966b","#7c3fb8","#d97706"],P={global:{containerTop:"0px",containerLeft:"0px",containerWidth:"100%",containerHeight:"100%",backgroundColor:"#f6f6f6"},map:{autoPaddingPercent:.05,adjacencyThreshold:3,obstacleColor:"#999999",freeColor:"#ebebeb"},room:{colors:{active:["#a8c8f5","#9de5c7","#d4b9f7","#ffd399"],inactive:["#d6e7fc","#d1f4e5","#ece0fb","#fff0d9"],name:R,propertyTheme:R,selectionIndicatorBackground:R,selectionIndicatorIcon:["#ffffff","#ffffff","#ffffff","#ffffff"],[O.NO_ROOM_DATA]:"#ebebeb",[O.ROOM_GAP]:"#ebebeb",[O.OBSTACLE_ROOM]:"#ebebeb",[O.UNKNOWN_ROOM]:"#ebebeb"},nameLabel:{fontSize:10,fontFamily:w,fontWeight:"500"},property:{displayOrders:["cleanMode","suction","cistern","cleanTimes"],iconWidth:12,iconHeight:12,foldable:!0,offsetX:0,offsetY:4,iconGap:0,container:{backgroundColor:"#ffffff",paddingVertical:1.5,paddingHorizontal:1.5,borderRadius:16,tailHeight:2,tailWidth:10},suction:{assets:[t,i,r,s,n]},cistern:{assets:[a,f,l,d]},cleanMode:{assets:[c,h,p,m]},cleanTimes:{assets:[g,b]},cleanOrder:{color:"#ffffff",fontFamily:w,fontWeight:"400",fontSize:8,gapRight:2}},selectionIndicator:{iconSrc:k,iconWidth:12,iconHeight:12,containerWidth:16,containerHeight:16,strokeWidth:2,strokeColor:"#ffffff",borderRadius:16,offsetY:4,offsetX:0,tailHeight:2,tailWidth:6},floorType:{assets:["",D,j,x],opacity:.1,scale:.2}},path:{lineWidthFixed:!1,incrementalThreshold:5,commonPath:{color:16777215,width:.5},transitionPath:{color:"transparent",width:.5},chargePath:{color:"transparent",width:.5}},carpet:{src:F,opacity:.5,scale:.2},robot:{icon:{sizeFixed:!1,width:8,height:8,src:e},speed:0,rotationCorrection:0,sleepAnimation:{jsonSrc:A,framePrefix:"sleep_",width:16,height:16,sizeFixed:!1,frameCount:96,offsetX:8,offsetY:-8},ringSize:1,ringColor:"rgba(255, 68, 68, 0.2)",ringStrokeWidth:1,ringStrokeColor:"#ffffff",ringStrokeDashed:!0,ringStrokeDashArray:[4,4]},chargingStation:{icon:{sizeFixed:!1,width:8,height:8,src:o},rotationCorrection:0,ringSize:1,ringColor:"rgba(255, 68, 68, 0.2)",ringStrokeWidth:1,ringStrokeColor:"#ffffff",ringStrokeDashed:!0,ringStrokeDashArray:[4,4]},interaction:{zoomRange:{min:.5,max:8},fitMinScale:1,fitMaxScale:4,enableDoubleTapZoom:!0},controls:{iconWrapperWidth:24,iconWrapperHeight:24,iconWrapperBorderRadius:16,iconWidth:12,iconHeight:12,deleteIconSrc:C,rotateIconSrc:u,scaleIconSrc:S,moveIconSrc:W,moveButtonOffset:30,textFontSize:12,textFontFamily:w,textFontWeight:"400",unitLabel:"m",forbiddenSweepZone:{minSize:1,iconWrapperFillColor:"#ff4444",strokeColor:"#ff4444",strokeWidth:2,fillColor:"rgba(255, 68, 68, 0.1)",outlineOffset:16,outlineStrokeColor:"#ff4444",outlineStrokeWidth:2,outlineDashed:!0,outlineDashArray:[4,3],outlineFillColor:"rgba(255, 68, 68, 0.05)",textColor:"#ff4444",textPosition:"bottom",textOffset:10,editing:{isDashed:!1,dashArray:[0,0]},normal:{isDashed:!1,dashArray:[0,0]}},forbiddenMopZone:{minSize:1,iconWrapperFillColor:"#fe8a07",strokeColor:"#fe8a07",strokeWidth:2,fillColor:"rgba(254, 138, 7, 0.1)",outlineOffset:16,outlineStrokeColor:"#fe8a07",outlineStrokeWidth:2,outlineDashed:!0,outlineDashArray:[4,3],outlineFillColor:"rgba(254, 138, 7, 0.05)",textColor:"#fe8a07",textPosition:"bottom",textOffset:10,editing:{isDashed:!1,dashArray:[0,0]},normal:{isDashed:!1,dashArray:[0,0]}},cleanZone:{minSize:1,iconWrapperFillColor:"#5d68fe",strokeColor:"#5d68fe",strokeWidth:2,fillColor:"rgba(93, 104, 254, 0.1)",outlineOffset:16,outlineStrokeColor:"#5d68fe",outlineStrokeWidth:2,outlineDashed:!0,outlineDashArray:[4,3],outlineFillColor:"rgba(93, 104, 254, 0.05)",textColor:"#5d68fe",textPosition:"bottom",textOffset:10,editing:{isDashed:!1,dashArray:[0,0]},normal:{isDashed:!1,dashArray:[0,0]}},virtualWall:{iconWrapperFillColor:"#ff4444",lineWidth:2,lineColor:"#ff4444",hitAreaThickness:30,outlineOffset:16,outlineStrokeColor:"#ff4444",outlineStrokeWidth:2,outlineDashed:!0,outlineDashArray:[4,3],outlineFillColor:"rgba(255, 68, 68, 0.05)",minWidth:1,textColor:"#ff4444",textOffset:10,editing:{isDashed:!1,dashArray:[0,0]},normal:{isDashed:!1,dashArray:[0,0]}},spot:{iconSrc:y,iconSize:8,size:1,strokeColor:"#5d68fe",strokeWidth:2,fillColor:"rgba(93, 104, 254, 0.1)",textColor:"#5d68fe",textPosition:"bottom",textOffset:10,editing:{isDashed:!1,dashArray:[0,0]},normal:{isDashed:!1,dashArray:[0,0]}}},divider:{lineColor:"#ff4444",dashLineWidth:2,dashLineDashArray:[4,3],solidLineWidth:2,endPointSize:12,endPointColor:"#ff4444",endPointStrokeColor:"#ffffff",endPointStrokeWidth:2,hitAreaThickness:30,resetDividerWhenOutOfRoom:!0,defaultExtension:20,defaultDirection:"horizontal"},detectedObject:{height:43,width:38,interactive:!1},heatmap:{cellSize:2,maxDistance:14,smoothIterations:10,heatmapAlpha:.8,colorGradients:["#FF3B30","#FF7A00","#FFA100","#FFD700","#99DD70","#2EC070","#40E0D0","#88D0E9"]},snapshot:{format:"png",quality:1,antialias:!0,resolution:window?.devicePixelRatio||1}},z={dividingRoomId:null,enableRoomSelection:!1,editingForbiddenSweepZoneIds:[],editingForbiddenMopZoneIds:[],editingCleanZoneIds:[],editingVirtualWallIds:[],editingSpotIds:[],roomPropertyFoldIds:[],roomSelectionMode:"checkmark",selectRoomIds:[],showRoomProperty:!1,showRoomOrder:!0,showRoomName:!0,showPath:!0,showChargingStation:!0,showRoomFloorType:!0,showCarpet:!0,showChargingStationRing:!1,showRobotRing:!1,showRobotSleepAnimation:!1};export{P as DEFAULT_CONFIG,z as DEFAULT_RUNTIME_CONFIG,w as TEXT_FONT_FAMILY};
package/dist/index.d.ts CHANGED
@@ -58,6 +58,8 @@ export declare type AppConfig = {
58
58
  map: {
59
59
  /** 自动填充百分比 */
60
60
  autoPaddingPercent: number
61
+ /** 相邻房间判断阈值 */
62
+ adjacencyThreshold: number
61
63
  /** 障碍点颜色 */
62
64
  obstacleColor: ColorSource
63
65
  /** 自由区域颜色 */
@@ -522,6 +524,7 @@ declare class AppService {
522
524
  };
523
525
  get mapConfig(): {
524
526
  autoPaddingPercent: number;
527
+ adjacencyThreshold: number;
525
528
  obstacleColor: ColorSource;
526
529
  freeColor: ColorSource;
527
530
  };
@@ -1892,10 +1895,9 @@ export declare interface MapApi {
1892
1895
  * 例如:房间A和B相邻,房间B和C相邻,则认为A、B、C三个房间都相邻。
1893
1896
  *
1894
1897
  * @param roomIds - 要检测的房间ID数组
1895
- * @param threshold - 距离阈值(像素),默认为5。两个房间的边界点距离小于等于此阈值时认为相邻
1896
1898
  * @returns 是否所有指定的房间都相邻(连通)
1897
1899
  */
1898
- areRoomsAdjacent(roomIds: number[], threshold?: number): boolean;
1900
+ areRoomsAdjacent(roomIds: number[]): boolean;
1899
1901
  /**
1900
1902
  * 地图截图
1901
1903
  *
@@ -2274,7 +2276,6 @@ export declare class MapApplication extends Application implements MapApi {
2274
2276
  * 例如:房间A和B相邻,房间B和C相邻,则认为A、B、C三个房间都相邻。
2275
2277
  *
2276
2278
  * @param roomIds - 要检测的房间ID数组
2277
- * @param threshold - 距离阈值(像素),默认为3。两个房间的边界点距离小于等于此阈值时认为相邻
2278
2279
  * @returns 是否所有指定的房间都相邻(连通)
2279
2280
  *
2280
2281
  * @example
@@ -2282,11 +2283,9 @@ export declare class MapApplication extends Application implements MapApi {
2282
2283
  * // 判断两个房间是否相邻
2283
2284
  * const isAdjacent = mapApi.areRoomsAdjacent([1, 2])
2284
2285
  *
2285
- * // 判断三个房间是否相邻(连通),使用自定义阈值
2286
- * const isAdjacent = mapApi.areRoomsAdjacent([1, 2, 3], 8)
2287
2286
  * ```
2288
2287
  */
2289
- areRoomsAdjacent(roomIds: number[], threshold?: number): boolean;
2288
+ areRoomsAdjacent(roomIds: number[]): boolean;
2290
2289
  /* Excluded from this release type: areStructuredRoomsAdjacentInternal */
2291
2290
  /* Excluded from this release type: areRasterRoomsAdjacentInternal */
2292
2291
  /**
@@ -2641,6 +2640,7 @@ declare class MapManager {
2641
2640
  private lastMapId;
2642
2641
  private roomGeometryMap;
2643
2642
  private rasterRoomPixelsMap;
2643
+ private fourColorCache;
2644
2644
  private carpetData;
2645
2645
  private unsubscribeFns;
2646
2646
  constructor();
@@ -2699,6 +2699,20 @@ declare class MapManager {
2699
2699
  * @returns 像素索引数组,如果不存在则返回 undefined
2700
2700
  */
2701
2701
  getRasterRoomPixels(roomId: number): Uint32Array | undefined;
2702
+ /**
2703
+ * 验证颜色配置
2704
+ * @private
2705
+ */
2706
+ private validateColorConfig;
2707
+ /**
2708
+ * 使用四色算法分配房间颜色
2709
+ * @param roomData 房间数据数组
2710
+ * @param colorCount 可用颜色数量
2711
+ * @param mapType 地图类型
2712
+ * @returns 房间ID到颜色索引的映射
2713
+ * @private
2714
+ */
2715
+ private assignColorsUsingFourColorAlgorithm;
2702
2716
  destroy(): void;
2703
2717
  }
2704
2718
 
@@ -2935,6 +2949,8 @@ export declare type RasterRoomData = {
2935
2949
  activeColor: string
2936
2950
  /** 非激活状态颜色 */
2937
2951
  inactiveColor: string
2952
+ /** 颜色索引(用于四色算法) */
2953
+ colorIndex?: number
2938
2954
  }
2939
2955
 
2940
2956
  declare class Ring extends Graphics {
@@ -3084,6 +3100,8 @@ export declare type Room = {
3084
3100
  polyPoints: number[]
3085
3101
  /** 中心点 */
3086
3102
  centerPoint: Point
3103
+ /** 颜色索引(用于四色算法) */
3104
+ colorIndex?: number
3087
3105
  }
3088
3106
 
3089
3107
  /**
@@ -3095,6 +3113,8 @@ export declare type RoomData = RoomProperty & {
3095
3113
  centerPoint: Point | null
3096
3114
  /** 索引 */
3097
3115
  index: number
3116
+ /** 颜色索引(用于四色算法) */
3117
+ colorIndex?: number
3098
3118
  }
3099
3119
 
3100
3120
  declare class RoomFill extends Container {