可以替换模型

This commit is contained in:
2026-05-13 16:27:16 +08:00
parent fea24ad19a
commit 8f833be426
5 changed files with 113 additions and 10 deletions

View File

@ -1,5 +1,6 @@
import { Scene, Vector3 } from '@babylonjs/core';
import { AppPlacementWall, WallConfig, PlacementZoneInfo } from './AppPlacementWall';
import { AppModel } from './AppModel';
/**
* 放置区域配置
@ -19,20 +20,94 @@ export interface DropZoneConfig {
export class AppDropZone {
private scene: Scene;
private placementWall: AppPlacementWall;
private appModel: AppModel | null = null;
// 内部映射:放置区域 -> 模型ID
private zoneModelMap: Map<string, string> = new Map();
// 墙面 -> 当前分割数
private wallDivisionsMap: Map<string, number> = new Map();
constructor(scene: Scene) {
this.scene = scene;
this.placementWall = new AppPlacementWall(scene);
}
/**
* 初始化模型管理器(内部使用)
*/
setModelManager(appModel: AppModel): void {
this.appModel = appModel;
}
/**
* 生成放置区域
* @param config 配置参数
*/
generateDropZones(config: DropZoneConfig): PlacementZoneInfo[] {
// 检查每个墙面的分割数是否改变,如果改变则卸载该墙面的所有模型
config.walls.forEach(wall => {
const oldDivisions = this.wallDivisionsMap.get(wall.name);
if (oldDivisions !== undefined && oldDivisions !== wall.divisions) {
// 分割数改变,卸载该墙面的所有模型
this.unloadWallModels(wall.name);
console.log(`墙面 ${wall.name} 分割数从 ${oldDivisions} 改为 ${wall.divisions},已卸载所有模型`);
}
// 更新分割数记录
this.wallDivisionsMap.set(wall.name, wall.divisions);
});
return this.placementWall.generatePlacementAreas(config);
}
/**
* 卸载指定墙面的所有模型(内部方法)
*/
private unloadWallModels(wallName: string): void {
if (!this.appModel) return;
const modelsToUnload: string[] = [];
// 找出该墙面的所有模型
this.zoneModelMap.forEach((modelId, zoneKey) => {
if (zoneKey.startsWith(`${wallName}[`)) {
modelsToUnload.push(modelId);
}
});
// 卸载模型并清除映射
modelsToUnload.forEach(modelId => {
this.appModel!.removeByName(modelId);
// 清除该模型的映射
this.zoneModelMap.forEach((value, key) => {
if (value === modelId) {
this.zoneModelMap.delete(key);
}
});
});
if (modelsToUnload.length > 0) {
console.log(`已卸载墙面 ${wallName}${modelsToUnload.length} 个模型`);
}
}
/**
* 记录模型放置到区域(内部方法,在点击事件中自动调用)
*/
recordModelPlacement(wallName: string, index: number, modelId: string): void {
const zoneKey = `${wallName}[${index}]`;
// 检查该区域是否已有模型
const existingModelId = this.zoneModelMap.get(zoneKey);
if (existingModelId && this.appModel) {
// 卸载旧模型
console.log(`区域 ${zoneKey} 已有模型 ${existingModelId},将替换为 ${modelId}`);
this.appModel.removeByName(existingModelId);
}
// 记录新模型
this.zoneModelMap.set(zoneKey, modelId);
}
/**
* 获取所有放置区域
*/
@ -79,6 +154,17 @@ export class AppDropZone {
* 清除所有放置区域
*/
clearAll(): void {
// 清除所有模型
if (this.appModel) {
this.zoneModelMap.forEach(modelId => {
this.appModel!.removeByName(modelId);
});
}
// 清除映射
this.zoneModelMap.clear();
this.wallDivisionsMap.clear();
this.placementWall.clearAll();
}

View File

@ -95,6 +95,8 @@ export class MainApp {
this.appModel.initManagers();
// 在场景创建后初始化 AppDropZone
this.appDropZone = new AppDropZone(this.appScene.object);
// 设置模型管理器引用
this.appDropZone.setModelManager(this.appModel);
this.update();
EventBridge.sceneReady({ scene: this.appScene.object });
}