可以替换模型

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

@ -3,7 +3,8 @@
"allow": [ "allow": [
"Bash(cd /d/VscodeProject/zhengte.babylonjs-sdk && npm run build 2>&1 | head -50)", "Bash(cd /d/VscodeProject/zhengte.babylonjs-sdk && npm run build 2>&1 | head -50)",
"Bash(find \"D:\\\\VscodeProject\\\\zhengte.babylonjs-sdk\\\\src\" -name \"*.ts\" -type f -exec grep -l \"class Dictionary\" {} \\\\;)", "Bash(find \"D:\\\\VscodeProject\\\\zhengte.babylonjs-sdk\\\\src\" -name \"*.ts\" -type f -exec grep -l \"class Dictionary\" {} \\\\;)",
"Bash(find \"D:\\\\VscodeProject\\\\zhengte.babylonjs-sdk\\\\src\" -name \"*.ts\" -type f -exec grep -l \"class.*Kernel\\\\|export.*kernel\" {} \\\\;)" "Bash(find \"D:\\\\VscodeProject\\\\zhengte.babylonjs-sdk\\\\src\" -name \"*.ts\" -type f -exec grep -l \"class.*Kernel\\\\|export.*kernel\" {} \\\\;)",
"Bash(npm run *)"
] ]
} }
} }

View File

@ -856,9 +856,10 @@
// 监听放置区域点击事件 // 监听放置区域点击事件
kernel.on('dropzone:click', async (dropzone_data) => { kernel.on('dropzone:click', async (dropzone_data) => {
console.log(dropzone_data); console.log('点击了放置区域:', dropzone_data);
const { position, rotation } = dropzone_data.transform; const { wallName, index, transform } = dropzone_data;
const { position, rotation } = transform;
// 将模型放置到该区域 // 将模型放置到该区域
try { try {
@ -872,28 +873,35 @@
// 使用 for...of 循环以支持 await // 使用 for...of 循环以支持 await
for (const event of result.data.events) { for (const event of result.data.events) {
if (event.event_type === 'change_model') { if (event.event_type === 'change_model') {
console.log( event.target_data); console.log(event.target_data);
const {id, name,file_url, model_control_type, category } = event.target_data; const {id, name, file_url, model_control_type, category } = event.target_data;
console.log('替换百叶模型:', event); console.log('替换百叶模型:', event);
console.log('替换百叶模型类型:', category); console.log('替换百叶模型类型:', category);
// 生成唯一的模型ID
const modelId = id + '_' + Date.now();
// 先记录模型放置(会自动处理替换逻辑)
kernel.dropZone.recordModelPlacement(wallName, index, modelId);
// 加载并放置模型
await kernel.model.add({ await kernel.model.add({
modelId: id+Date.now(), modelId: modelId,
modelUrl: file_url, modelUrl: file_url,
modelControlType: model_control_type, modelControlType: model_control_type,
drag: { drag: {
enable: true, enable: true,
axis: 'x', axis: 'x',
step: 0.1, step: 0.1,
} },
,
transform: { transform: {
position: position, position: position,
rotation: rotation, rotation: rotation,
} }
}); });
console.log(`百叶模型已替换${name}`); console.log(`百叶模型已放置${name}`);
} }
if (event.event_type === 'change_color') { if (event.event_type === 'change_color') {

View File

@ -1,5 +1,6 @@
import { Scene, Vector3 } from '@babylonjs/core'; import { Scene, Vector3 } from '@babylonjs/core';
import { AppPlacementWall, WallConfig, PlacementZoneInfo } from './AppPlacementWall'; import { AppPlacementWall, WallConfig, PlacementZoneInfo } from './AppPlacementWall';
import { AppModel } from './AppModel';
/** /**
* 放置区域配置 * 放置区域配置
@ -19,20 +20,94 @@ export interface DropZoneConfig {
export class AppDropZone { export class AppDropZone {
private scene: Scene; private scene: Scene;
private placementWall: AppPlacementWall; 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) { constructor(scene: Scene) {
this.scene = scene; this.scene = scene;
this.placementWall = new AppPlacementWall(scene); this.placementWall = new AppPlacementWall(scene);
} }
/**
* 初始化模型管理器(内部使用)
*/
setModelManager(appModel: AppModel): void {
this.appModel = appModel;
}
/** /**
* 生成放置区域 * 生成放置区域
* @param config 配置参数 * @param config 配置参数
*/ */
generateDropZones(config: DropZoneConfig): PlacementZoneInfo[] { 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); 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 { clearAll(): void {
// 清除所有模型
if (this.appModel) {
this.zoneModelMap.forEach(modelId => {
this.appModel!.removeByName(modelId);
});
}
// 清除映射
this.zoneModelMap.clear();
this.wallDivisionsMap.clear();
this.placementWall.clearAll(); this.placementWall.clearAll();
} }

View File

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

View File

@ -374,6 +374,12 @@ export class KernelAdapter {
inZone: false, inZone: false,
zone: null zone: null
}; };
},
/**
* 记录模型放置到区域(内部使用,自动处理替换)
*/
recordModelPlacement: (wallName: string, index: number, modelId: string): void => {
this.mainApp.appDropZone.recordModelPlacement(wallName, index, modelId);
} }
}; };