1
This commit is contained in:
BIN
ScreenShot_2026-05-17_130307_268.png
Normal file
BIN
ScreenShot_2026-05-17_130307_268.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 818 KiB |
30
index.html
30
index.html
@ -297,10 +297,14 @@
|
||||
</div>
|
||||
<div class="category-content">
|
||||
<div class="option-group">
|
||||
<button class="option-btn" data-option="size-1">3x3米</button>
|
||||
<button class="option-btn" data-option="size-2">4x4米</button>
|
||||
<button class="option-btn" data-option="size-3">5x5米</button>
|
||||
<button class="option-btn" data-option="size-4">6x6米</button>
|
||||
<button class="option-btn" data-option="size-1">3*3</button>
|
||||
<button class="option-btn" data-option="size-2">3x6</button>
|
||||
<button class="option-btn" data-option="size-3">10x13EM星空篷</button>
|
||||
<button class="option-btn" data-option="size-4">全铁3x6</button>
|
||||
<button class="option-btn" data-option="size-1">10x12</button>
|
||||
<button class="option-btn" data-option="size-2">10x10星空篷</button>
|
||||
<button class="option-btn" data-option="size-3">10x13星空篷</button>
|
||||
<button class="option-btn" data-option="size-4">10x20星空篷</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -346,8 +350,8 @@
|
||||
</div>
|
||||
<div class="category-content">
|
||||
<div class="option-group">
|
||||
<button class="option-btn" data-option="color-1">222222</button>
|
||||
<button class="option-btn" data-option="color-2">灰色</button>
|
||||
<button class="option-btn" data-option="color-1">Charcoal</button>
|
||||
<button class="option-btn" data-option="color-2">Cherry</button>
|
||||
<button class="option-btn" data-option="color-3">黑色</button>
|
||||
<button class="option-btn" data-option="color-4">木色</button>
|
||||
</div>
|
||||
@ -450,7 +454,7 @@
|
||||
<script type="module" src="./index.js"></script>
|
||||
<script type="module">
|
||||
import { kernel } from './src/main.ts';
|
||||
import { init, getAutoLoadModelList,getPlacementZone,executeEvent ,getHotspot} from './index.js';
|
||||
import { init, getAutoLoadModelList, getPlacementZone, getEvent, getHotspot,executeEvent2 } from './index.js';
|
||||
|
||||
await init()
|
||||
await getAutoLoadModelList()
|
||||
@ -531,11 +535,19 @@
|
||||
const result = await response.json();
|
||||
if (result.code === 200) {
|
||||
console.log(result.data);
|
||||
const { enable_placement_zone } = result.data;
|
||||
sku = currentText;
|
||||
// await initPlacementZoneConfig();
|
||||
if (enable_placement_zone) {
|
||||
getPlacementZone(currentText)
|
||||
}
|
||||
else {
|
||||
executeEvent2(result)
|
||||
}
|
||||
|
||||
getPlacementZone(currentText)
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@ -846,7 +858,7 @@
|
||||
|
||||
// 监听放置区域点击事件
|
||||
kernel.on('dropzone:click', async (dropzone_data) => {
|
||||
executeEvent(dropzone_data,sku)
|
||||
getEvent(dropzone_data, sku)
|
||||
});
|
||||
|
||||
|
||||
|
||||
80
index.js
80
index.js
@ -1,3 +1,4 @@
|
||||
import { EXRCubeTexture } from '@babylonjs/core';
|
||||
import { kernel } from './src/main.ts';
|
||||
|
||||
//初始化
|
||||
@ -47,7 +48,7 @@ export const getAutoLoadModelList = async () => {
|
||||
}
|
||||
|
||||
kernel.model.add({
|
||||
modelId: model.id,
|
||||
modelId: model.category,
|
||||
modelUrl: model.file_url,
|
||||
modelControlType: model.model_control_type,
|
||||
|
||||
@ -80,10 +81,7 @@ export const getPlacementZone = async (sku) => {
|
||||
}
|
||||
|
||||
//执行事件
|
||||
export const executeEvent = async (dropzone_data, sku) => {
|
||||
const { wallName, index, transform } = dropzone_data;
|
||||
const { position, rotation } = transform;
|
||||
|
||||
export const getEvent = async (dropzone_data, sku) => {
|
||||
// 将模型放置到该区域
|
||||
try {
|
||||
const response = await fetch(`http://localhost:3001/api/product-configs/by-sku/${sku}`);
|
||||
@ -94,6 +92,19 @@ export const executeEvent = async (dropzone_data, sku) => {
|
||||
console.log('关联事件:', result.data.events);
|
||||
|
||||
// 使用 for...of 循环以支持 await
|
||||
await executeEvent(dropzone_data, result)
|
||||
} else {
|
||||
console.log(`未查询到数据`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`查询SKU配置或替换模型失败:`, error);
|
||||
}
|
||||
}
|
||||
export const executeEvent = async (dropzone_data, result) => {
|
||||
|
||||
const { wallName, index, transform } = dropzone_data;
|
||||
const { position, rotation } = transform;
|
||||
|
||||
for (const event of result.data.events) {
|
||||
if (event.event_type === 'change_model') {
|
||||
console.log(event.target_data);
|
||||
@ -107,7 +118,7 @@ export const executeEvent = async (dropzone_data, sku) => {
|
||||
|
||||
// 先记录模型放置(会自动处理替换逻辑)
|
||||
kernel.dropZone.recordModelPlacement(wallName, index, modelId);
|
||||
|
||||
console.log(Math.abs(rotation.y - 90) ,Math.abs(rotation.y - 90) > 5 ? 'x' : 'z' );
|
||||
// 加载并放置模型
|
||||
await kernel.model.add({
|
||||
modelId: modelId,
|
||||
@ -115,7 +126,7 @@ export const executeEvent = async (dropzone_data, sku) => {
|
||||
modelControlType: model_control_type,
|
||||
drag: {
|
||||
enable: true,
|
||||
axis: Math.abs((rotation.y - 0)) < 90 ? 'x' : 'z',
|
||||
axis:rotation.y === 0 || rotation.y === 180 ? 'x' : 'z',
|
||||
step: 0.1,
|
||||
},
|
||||
transform: {
|
||||
@ -134,7 +145,6 @@ export const executeEvent = async (dropzone_data, sku) => {
|
||||
|
||||
kernel.material.apply({
|
||||
target: materialName,
|
||||
modelId: modelId, // 指定模型ID,只修改该模型的材质
|
||||
albedoColor: color,
|
||||
albedoTexture: color_map_url,
|
||||
normalMap: normal_map_url,
|
||||
@ -143,12 +153,58 @@ export const executeEvent = async (dropzone_data, sku) => {
|
||||
console.log(`百叶模型颜色已替换为 ${color}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(`未查询到数据`);
|
||||
}
|
||||
|
||||
export const executeEvent2 = async (result) => {
|
||||
kernel.dropZone.clearZones();
|
||||
kernel.model.removeAll();
|
||||
for (const event of result.data.events) {
|
||||
const { target_data } = event;
|
||||
if (event.event_type === 'change_model') {
|
||||
console.log(event.target_data);
|
||||
|
||||
const { id, name, file_url, model_control_type, category, placement_zone } = event.target_data;
|
||||
console.log('替换百叶模型:', event);
|
||||
console.log('替换百叶模型类型:', category);
|
||||
|
||||
if (placement_zone) {
|
||||
const { alpha, border_color, color, show_border, thickness, walls } = placement_zone
|
||||
kernel.dropZone.setData({
|
||||
|
||||
color: color,
|
||||
alpha: +alpha,
|
||||
thickness: thickness,
|
||||
showBorder: !show_border,
|
||||
borderColor: border_color,
|
||||
walls: walls
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`查询SKU配置或替换模型失败:`, error);
|
||||
// 加载并放置模型
|
||||
await kernel.model.replace({
|
||||
modelId: target_data.category,
|
||||
modelUrl: target_data.file_url,
|
||||
modelControlType: target_data.model_control_type,
|
||||
})
|
||||
|
||||
console.log(`百叶模型已放置为 ${name}`);
|
||||
}
|
||||
|
||||
if (event.event_type === 'change_color') {
|
||||
const materialName = event.material_name;
|
||||
const { color, color_map_url, normal_map_url } = event.target_data;
|
||||
console.log('替换百叶模型颜色:', event.target_data);
|
||||
|
||||
kernel.material.apply({
|
||||
target: materialName,
|
||||
albedoColor: color,
|
||||
albedoTexture: color_map_url,
|
||||
normalMap: normal_map_url,
|
||||
});
|
||||
|
||||
console.log(`百叶模型颜色已替换为 ${color}`);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -498,6 +498,28 @@ export class AppModel extends Monobehiver {
|
||||
console.log(`Model removed: ${modelName}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有已添加的模型并释放内存
|
||||
* 主要用于切换尺寸后清除不适用的配件
|
||||
*/
|
||||
removeAll(): void {
|
||||
const modelNames = this.modelDic.Keys();
|
||||
console.log(`开始清除所有模型,共 ${modelNames.length} 个模型`);
|
||||
|
||||
modelNames.forEach(modelName => {
|
||||
const meshes = this.modelDic.Get(modelName);
|
||||
if (meshes?.length) {
|
||||
this.getModelTransformTargets(meshes).forEach(mesh => mesh.dispose(false, true));
|
||||
}
|
||||
});
|
||||
|
||||
this.modelDic.Clear();
|
||||
this.modelMetadataDic.Clear();
|
||||
this.mainApp.gameManager?.updateDictionaries();
|
||||
|
||||
console.log('所有模型已清除,内存已释放');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型元数据
|
||||
* @param modelName 模型名称
|
||||
|
||||
@ -223,6 +223,7 @@ export class AppPlacementWall {
|
||||
this.scene
|
||||
);
|
||||
line.color = new Color3(1, 1, 1); // 白色
|
||||
line.isPickable = false; // 禁用边框的点击
|
||||
this.borderLines.push(line);
|
||||
});
|
||||
}
|
||||
@ -265,6 +266,7 @@ export class AppPlacementWall {
|
||||
this.scene
|
||||
);
|
||||
line.color = lineColor;
|
||||
line.isPickable = false; // 禁用边框的点击
|
||||
this.borderLines.push(line);
|
||||
});
|
||||
}
|
||||
|
||||
@ -751,7 +751,6 @@ export class GameManager extends Monobehiver {
|
||||
*/
|
||||
applyMaterial(options: {
|
||||
target: string;
|
||||
modelId?: string; // 新增:指定模型ID,只修改该模型的材质
|
||||
albedoColor?: string;
|
||||
albedoTexture?: string;
|
||||
normalMap?: string;
|
||||
@ -761,24 +760,8 @@ export class GameManager extends Monobehiver {
|
||||
}): void {
|
||||
this.updateDictionaries();
|
||||
|
||||
// 1. 查找目标材质
|
||||
// 查找目标材质(支持精确匹配和前缀匹配)
|
||||
const targetMaterials: PBRMaterial[] = [];
|
||||
|
||||
if (options.modelId) {
|
||||
// 如果指定了模型ID,只查找该模型的材质
|
||||
const materialName = `${options.target}_${options.modelId}`;
|
||||
this.materialDic.Values().forEach(material => {
|
||||
if (material.name === materialName) {
|
||||
targetMaterials.push(material);
|
||||
}
|
||||
});
|
||||
|
||||
if (targetMaterials.length === 0) {
|
||||
console.warn(`Material not found for model ${options.modelId}: ${materialName}`);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// 没有指定模型ID,查找所有匹配的材质(旧逻辑)
|
||||
this.materialDic.Values().forEach(material => {
|
||||
if (material.name === options.target || material.name.startsWith(`${options.target}_`)) {
|
||||
targetMaterials.push(material);
|
||||
@ -789,9 +772,8 @@ export class GameManager extends Monobehiver {
|
||||
console.warn(`Material not found: ${options.target}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 应用材质属性到目标材质
|
||||
// 应用材质属性到目标材质
|
||||
targetMaterials.forEach(material => {
|
||||
// 应用颜色
|
||||
if (options.albedoColor) {
|
||||
@ -828,6 +810,6 @@ export class GameManager extends Monobehiver {
|
||||
material.markDirty();
|
||||
});
|
||||
|
||||
console.log(`Material applied to: ${options.target}${options.modelId ? ` (model: ${options.modelId})` : ''}`, options);
|
||||
console.log(`Material applied to ${targetMaterials.length} material(s): ${options.target}`, options);
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,6 +58,16 @@ export class KernelAdapter {
|
||||
*/
|
||||
findModelNameByMesh: (mesh: any): string | undefined => {
|
||||
return this.mainApp.appModel.findModelNameByMesh(mesh);
|
||||
},
|
||||
/**
|
||||
* 清除所有已添加的模型并释放内存
|
||||
* 主要用于切换尺寸后清除不适用的配件
|
||||
* @example
|
||||
* // 切换尺寸时清除所有配件
|
||||
* kernel.model.removeAll();
|
||||
*/
|
||||
removeAll: (): void => {
|
||||
this.mainApp.appModel.removeAll();
|
||||
}
|
||||
};
|
||||
|
||||
@ -69,7 +79,6 @@ export class KernelAdapter {
|
||||
*/
|
||||
apply: (options: {
|
||||
target: string;
|
||||
modelId?: string; // 可选:指定模型ID,只修改该模型的材质
|
||||
albedoColor?: string;
|
||||
albedoTexture?: string;
|
||||
normalMap?: string;
|
||||
|
||||
Reference in New Issue
Block a user