From 66d705aa3ee3bd4c448839c843e747aafb8d94c0 Mon Sep 17 00:00:00 2001 From: zguiy <1415466602@qq.com> Date: Sat, 6 Jun 2026 01:15:25 +0800 Subject: [PATCH] =?UTF-8?q?bug=E4=BF=AE=E6=94=B9=E5=AE=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.js | 29 +++++---- src/babylonjs/AppDropZone.ts | 46 +++++++++------ src/babylonjs/AppPlacementWall.ts | 98 ++++++++++++++++++++----------- src/kernel/Adapter.ts | 6 ++ 4 files changed, 116 insertions(+), 63 deletions(-) diff --git a/index.js b/index.js index 832aa14..7e0f5c0 100644 --- a/index.js +++ b/index.js @@ -179,25 +179,30 @@ export const getPlacementZone = async (sku) => { console.log('[放置区域] 当前配件的墙面配置:', wall_divisions); // 将当前配件的墙面配置缓存起来(用于拖拽时查找) - wall_divisions.forEach(wall => { - wall_divisions_cache.set(wall.name, wall); - }); - console.log('[放置区域] 已缓存的所有墙面配置:', Array.from(wall_divisions_cache.keys())); + // wall_divisions.forEach(wall => { + // wall_divisions_cache.set(wall.name, wall); + // }); + // console.log('[放置区域] 已缓存的所有墙面配置:', Array.from(wall_divisions_cache.keys())); // 只使用当前配件的墙面配置,不累积显示 const filteredDivisions = wall_divisions.filter(item => division_include.includes(item.name)) console.log('[放置区域] 当前显示的墙面:', filteredDivisions); - // 只清除旧的放置区域网格,不清除模型 - kernel.dropZone.clearZones(); + // 不需要手动 clearZones,updateDivisions 会自动处理增量更新 const divisions = filteredDivisions.map(wall => ({ name: wall.name, divisions: wall.divisions })) - kernel.dropZone.updateDivisions(divisions); - // 显示放置区域 - kernel.dropZone.show(); + const zones = kernel.dropZone.updateDivisions(divisions); + + // 隐藏所有,然后只显示当前需要的墙面 + kernel.dropZone.hide(); + // 从生成的 zones 中提取完整的墙面名称 + const wallNamesToShow = new Set(zones.map(zone => zone.wallName)); + wallNamesToShow.forEach(wallName => { + kernel.dropZone.showWall(wallName); + }); } } } @@ -231,9 +236,7 @@ export const showWallFromCache = (wallName) => { if (wallConfig) { console.log(`[放置区域] 从缓存恢复墙面 ${wallName}:`, wallConfig); - // 清除旧的放置区域网格 - kernel.dropZone.clearZones(); - + // 不需要手动 clearZones,updateDivisions 会自动处理增量更新 // 重新生成该墙面的放置区域 kernel.dropZone.updateDivisions([wallConfig]); @@ -370,6 +373,8 @@ export const executeEvent2 = async (result, sku) => { kernel.model.removeAll(); // 清除所有 SKU 映射 clearAllSkuMappings(); + // 只清除放置区域的网格和数据,不删除模型(模型已经在 removeAll 中删除了) + kernel.dropZone.clearZones(); } // 先处理所有 change_model 事件 diff --git a/src/babylonjs/AppDropZone.ts b/src/babylonjs/AppDropZone.ts index d84e10b..0fb4ab5 100644 --- a/src/babylonjs/AppDropZone.ts +++ b/src/babylonjs/AppDropZone.ts @@ -35,11 +35,6 @@ export class AppDropZone { // 存储原始墙面配置(用于 updateDivisions 时恢复完整墙面列表) private originalWalls: WallConfig[] = []; - // 存储所有墙面的区域数据(持久化,不会被覆盖) - private allWallZonesData: Map = new Map(); - // 当前激活显示的墙面名称集合(用于控制显示) - private activeWallNames: Set = new Set(); - constructor(scene: Scene) { this.scene = scene; this.placementWall = new AppPlacementWall(scene); @@ -111,7 +106,7 @@ export class AppDropZone { divisionsMap[item.name] = item.divisions; }); - + // 匹配墙面名称(精确匹配) const matchWallName = (wallName: string): number | null => { // 提取墙面名称的最后部分(最后一个下划线之后) @@ -126,8 +121,8 @@ export class AppDropZone { return null; }; - // 更新配置中的墙面分割数,从原始配置中恢复墙面列表 - this.dropZoneConfig.walls = this.originalWalls + // 从原始配置中筛选出本次要更新的墙面 + const newWalls = this.originalWalls .map(wall => { const newDivisions = matchWallName(wall.name); @@ -136,24 +131,35 @@ export class AppDropZone { return null; } - return { ...wall, divisions: newDivisions }; }) - .filter(wall => wall !== null) as typeof this.dropZoneConfig.walls; // 过滤掉未配置的墙面 + .filter(wall => wall !== null) as WallConfig[]; + + // 合并到现有配置中(保留其他墙面,更新/添加本次传入的墙面) + // 先过滤掉 divisions 为 0 或未设置的墙面(避免初始状态污染) + const existingWallsMap = new Map( + this.dropZoneConfig.walls + .filter(w => w.divisions && w.divisions > 0) // 只保留有效的墙面配置 + .map(w => [w.name, w]) + ); + newWalls.forEach(wall => { + existingWallsMap.set(wall.name, wall); + }); + this.dropZoneConfig.walls = Array.from(existingWallsMap.values()); // 更新 wallDivisionsMap(重要:用于后续的自动排列和拖拽检查) this.dropZoneConfig.walls.forEach(wall => { this.wallDivisionsMap.set(wall.name, wall.divisions); }); - // 清除旧的放置区域网格(不清除模型) - this.clearZones(); - - // 重新生成放置区域 - const zones = this.generateDropZones(); + // 只生成本次传入的墙面(不生成所有墙面) + const zones = this.placementWall.generatePlacementAreas({ + ...this.dropZoneConfig, + walls: newWalls // 只传入本次要更新的墙面 + }); // 显示放置区域 this.show(); @@ -462,8 +468,8 @@ export class AppDropZone { */ show(): void { // this.placementWall.show(); - // // 禁用所有已放置模型的拾取 - // this.setModelsPickable(false); + // 禁用所有已放置模型的拾取 + this.setModelsPickable(false); } /** @@ -506,6 +512,12 @@ export class AppDropZone { * 清除所有放置区域(只清除网格,不清除模型) */ clearZones(): void { + // 清除映射(不删除模型,只清空记录) + this.zoneModelMap.clear(); + this.wallDivisionsMap.clear(); + this.wallModelDivisionsMap.clear(); + + // 清除放置区域的 mesh this.placementWall.clearAll(); } diff --git a/src/babylonjs/AppPlacementWall.ts b/src/babylonjs/AppPlacementWall.ts index beb2a92..ea4e777 100644 --- a/src/babylonjs/AppPlacementWall.ts +++ b/src/babylonjs/AppPlacementWall.ts @@ -39,7 +39,7 @@ export interface PlacementZoneInfo { export class AppPlacementWall { private scene: Scene; - private placementZones: PlacementZoneInfo[] = []; + private placementZones: Map = new Map(); private borderLines: Mesh[] = []; private onZoneClickCallback?: (zoneInfo: PlacementZoneInfo) => void; @@ -60,21 +60,31 @@ export class AppPlacementWall { borderColor = '#ffffff' } = config; - // 清除之前的放置区域 - this.clearAll(); - + // 不再清除所有区域,只清除和更新本次传入的墙面 const material = this.createMaterial(color, alpha); + const allZones: PlacementZoneInfo[] = []; walls.forEach(wall => { + // 先清除该墙面的旧数据(dispose 旧 mesh) + const oldZones = this.placementZones.get(wall.name); + if (oldZones) { + oldZones.forEach(zone => zone.mesh.dispose()); + } + + // 清除该墙面的旧边框 + this.clearWallBorders(wall.name); + + // 生成新的区域 const zones = this.generateWallZones(wall, material, thickness); - this.placementZones.push(...zones); + this.placementZones.set(wall.name, zones); + allZones.push(...zones); if (showBorder) { this.createWallBorder(wall, borderColor); } }); - return this.placementZones; + return allZones; } /** @@ -302,23 +312,26 @@ export class AppPlacementWall { * 获取所有放置区域 */ getPlacementZones(): PlacementZoneInfo[] { - return this.placementZones; + const allZones: PlacementZoneInfo[] = []; + this.placementZones.forEach(zones => { + allZones.push(...zones); + }); + return allZones; } /** * 根据墙面名称获取放置区域 */ getZonesByWall(wallName: string): PlacementZoneInfo[] { - return this.placementZones.filter(zone => zone.wallName === wallName); + return this.placementZones.get(wallName) || []; } /** * 根据索引获取特定放置区域 */ getZone(wallName: string, index: number): PlacementZoneInfo | undefined { - return this.placementZones.find( - zone => zone.wallName === wallName && zone.index === index - ); + const zones = this.placementZones.get(wallName); + return zones?.find(zone => zone.index === index); } /** @@ -331,32 +344,30 @@ export class AppPlacementWall { /** * 显示所有放置区域 */ - // show(): void { - // this.placementZones.forEach(zone => { - // zone.mesh.isVisible = true; - // }); - // this.borderLines.forEach(line => { - // line.isVisible = true; - // }); - // } + show(): void { + this.placementZones.forEach(zones => { + zones.forEach(zone => { + zone.mesh.isVisible = true; + }); + }); + this.borderLines.forEach(line => { + line.isVisible = true; + }); + } /** * 只显示指定墙面的放置区域 * @param wallName 墙面名称 */ showWall(wallName: string): void { - - // 先隐藏所有 - this.hide(); - - - console.log(this.placementZones, wallName); + // 不隐藏其他墙面,只显示指定墙面 // 只显示指定墙面的区域 - this.placementZones.forEach(zone => { - if (zone.wallName === wallName) { + const zones = this.placementZones.get(wallName); + if (zones) { + zones.forEach(zone => { zone.mesh.isVisible = true; - } - }); + }); + } // 显示该墙面的边框(根据名称过滤) this.borderLines.forEach(line => { @@ -371,22 +382,41 @@ export class AppPlacementWall { * 隐藏所有放置区域 */ hide(): void { - this.placementZones.forEach(zone => { - zone.mesh.isVisible = false; + this.placementZones.forEach(zones => { + zones.forEach(zone => { + zone.mesh.isVisible = false; + }); }); this.borderLines.forEach(line => { line.isVisible = false; }); } + /** + * 清除指定墙面的边框 + */ + private clearWallBorders(wallName: string): void { + const linesToRemove: Mesh[] = []; + this.borderLines.forEach(line => { + if (line.name.includes(`_${wallName}_`)) { + line.dispose(); + linesToRemove.push(line); + } + }); + // 从数组中移除已清除的边框 + this.borderLines = this.borderLines.filter(line => !linesToRemove.includes(line)); + } + /** * 清除所有放置区域 */ clearAll(): void { - this.placementZones.forEach(zone => { - zone.mesh.dispose(); + this.placementZones.forEach(zones => { + zones.forEach(zone => { + zone.mesh.dispose(); + }); }); - this.placementZones = []; + this.placementZones.clear(); this.borderLines.forEach(line => { line.dispose(); diff --git a/src/kernel/Adapter.ts b/src/kernel/Adapter.ts index 7cdf8c4..f0214ca 100644 --- a/src/kernel/Adapter.ts +++ b/src/kernel/Adapter.ts @@ -385,6 +385,12 @@ export class KernelAdapter { hide: (): void => { this.mainApp.appDropZone.hide(); }, + /** + * 只显示指定墙面的放置区域 + */ + showWall: (wallName: string): void => { + this.mainApp.appDropZone.showWall(wallName); + }, /** * 清除所有放置区域(只清除网格,不清除模型) */