1
This commit is contained in:
@ -135,27 +135,25 @@ const getEvent = async (dropzone_data, sku) => {
|
||||
|
||||
//点击放置区域执行事件
|
||||
const executeEvent = async (dropzone_data, result) => {
|
||||
const kernel = getKernel();
|
||||
const kernel = getKernel();
|
||||
|
||||
const { wallName, index, transform } = dropzone_data;
|
||||
const { position, rotation } = transform;
|
||||
|
||||
let modelId = null; // 在外部声明,用于在两个循环之间传递
|
||||
let modelName = null;
|
||||
// 第一次循环:处理 change_model
|
||||
for (const event of result.data.events) {
|
||||
if (event.event_type === 'change_model') {
|
||||
console.log(event.target_data);
|
||||
|
||||
const { id, name, file_url, model_control_type, category } = event.target_data;
|
||||
console.log('替换百叶模型:', event);
|
||||
console.log('替换百叶模型类型:', category);
|
||||
const { name, file_url, model_control_type, category } = event.target_data;
|
||||
|
||||
// 生成唯一的模型ID
|
||||
const modelId = id + '_' + Date.now();
|
||||
modelId = Date.now();
|
||||
modelName = name;
|
||||
kernel.dropZone.recordModelPlacement(wallName, index, name + '_' + modelId);
|
||||
|
||||
// 先记录模型放置(会自动处理替换逻辑)
|
||||
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({
|
||||
modelName: name,
|
||||
modelId: modelId,
|
||||
modelUrl: file_url,
|
||||
modelControlType: model_control_type,
|
||||
@ -170,21 +168,24 @@ const executeEvent = async (dropzone_data, result) => {
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`百叶模型已放置为 ${name}`);
|
||||
console.log(`百叶模型已放置为 ${name + '_' + modelId}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 第二次循环:处理 change_color(此时模型已加载完成)
|
||||
for (const event of result.data.events) {
|
||||
if (event.event_type === 'change_color') {
|
||||
const materialName = event.material_name;
|
||||
const { color, color_map_url, normal_map_url, metallic, roughness } = event.target_data;
|
||||
console.log('替换百叶模型颜色:', event.target_data);
|
||||
|
||||
kernel.material.apply({
|
||||
target: materialName,
|
||||
modelId: modelName + '_' + modelId, // 传入 modelId,只替换该模型的材质
|
||||
albedoColor: color,
|
||||
albedoTexture: color_map_url,
|
||||
normalMap: normal_map_url,
|
||||
metallic: metallic,
|
||||
roughness: roughness
|
||||
metallic: +metallic,
|
||||
roughness: +roughness
|
||||
});
|
||||
|
||||
console.log(`百叶模型颜色已替换为 ${color}`);
|
||||
@ -277,15 +278,13 @@ const isModelExists = (modelId) => {
|
||||
if (event.event_type === 'change_color') {
|
||||
const materialName = event.material_name;
|
||||
const { color, color_map_url, normal_map_url, metallic, roughness } = event.target_data;
|
||||
console.log('替换百叶模型颜色:', event.target_data);
|
||||
console.log('替换模型颜色:', event.target_data);
|
||||
|
||||
kernel.material.apply({
|
||||
target: materialName,
|
||||
albedoColor: color,
|
||||
albedoTexture: color_map_url,
|
||||
normalMap: normal_map_url,
|
||||
metallic: metallic,
|
||||
roughness: roughness
|
||||
});
|
||||
|
||||
console.log(`百叶模型颜色已替换为 ${color}`);
|
||||
|
||||
@ -333,11 +333,14 @@
|
||||
</div>
|
||||
<div class="category-content">
|
||||
<div class="option-group">
|
||||
<button class="option-btn" data-option="louver-1">整体</button>
|
||||
<button class="option-btn" data-option="louver-2">3m百叶</button>
|
||||
<button class="option-btn" data-option="louver-1">SPFPDS13FTW</button>
|
||||
<button class="option-btn" data-option="louver-2">SPFPDS13FTC</button>
|
||||
<button class="option-btn" data-option="louver-3">3m下拉帘</button>
|
||||
<button class="option-btn" data-option="louver-4">百叶4</button>
|
||||
<button class="option-btn" data-option="louver-4">卷帘小</button>
|
||||
<button class="option-btn" data-option="louver-4">SPFSW13FTW</button>
|
||||
<button class="option-btn" data-option="louver-4">SPFSW10FTW</button>
|
||||
<button class="option-btn" data-option="louver-4">SPFPDS10FTC</button>
|
||||
<button class="option-btn" data-option="louver-4">SPFPDS10FTW</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -350,10 +353,14 @@
|
||||
</div>
|
||||
<div class="category-content">
|
||||
<div class="option-group">
|
||||
<button class="option-btn" data-option="color-1">SPF111S1010C</button>
|
||||
<button class="option-btn" data-option="color-2">SPF111S1010W</button>
|
||||
13
|
||||
<button class="option-btn" data-option="color-1">SPF111S1013W</button>
|
||||
<button class="option-btn" data-option="color-2">SPF111S1013C</button>
|
||||
<button class="option-btn" data-option="color-3">SPF111S1013TA</button>
|
||||
10
|
||||
<button class="option-btn" data-option="color-1">SPF111S1010W</button>
|
||||
<button class="option-btn" data-option="color-2">SPF111S1010C</button>
|
||||
<button class="option-btn" data-option="color-3">SPF111S1010TA</button>
|
||||
<button class="option-btn" data-option="color-4">木色</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -761,23 +768,24 @@
|
||||
}
|
||||
});
|
||||
|
||||
// 移除按钮事件
|
||||
document.getElementById('remove-model-btn').addEventListener('click', function () {
|
||||
var pickedMesh = window.getCurrentPickedMesh();
|
||||
if (pickedMesh) {
|
||||
var meshName = pickedMesh.name;
|
||||
var success = kernel.model.remove(meshName);
|
||||
if (success) {
|
||||
console.log('模型已移除');
|
||||
// 关闭信息框
|
||||
kernel.domTo3D.detach('model-info');
|
||||
} else {
|
||||
console.log('移除失败:未找到该网格所属的模型');
|
||||
}
|
||||
} else {
|
||||
console.log('没有选中的网格');
|
||||
}
|
||||
});
|
||||
// 移除按钮事件
|
||||
document.getElementById('remove-model-btn').addEventListener('click', () => {
|
||||
const pickedMesh = window.getCurrentPickedMesh();
|
||||
if (pickedMesh) {
|
||||
const meshName = pickedMesh.name;
|
||||
const modelName = kernel.model.findModelNameByMesh(pickedMesh);
|
||||
const success = kernel.model.removeByName(modelName);
|
||||
if (success) {
|
||||
console.log('模型已移除');
|
||||
// 关闭信息框
|
||||
kernel.domTo3D.detach('model-info');
|
||||
} else {
|
||||
console.log('移除失败:未找到该网格所属的模型');
|
||||
}
|
||||
} else {
|
||||
console.log('没有选中的网格');
|
||||
}
|
||||
});
|
||||
|
||||
// 生成放置区域按钮事件
|
||||
var dropZoneVisible = false;
|
||||
|
||||
358552
examples/index.global.js
358552
examples/index.global.js
File diff suppressed because one or more lines are too long
33
index.html
33
index.html
@ -341,6 +341,15 @@
|
||||
<button class="option-btn" data-option="louver-4">SPFPDS10FTC</button>
|
||||
<button class="option-btn" data-option="louver-4">SPFPDS10FTW</button>
|
||||
|
||||
|
||||
|
||||
<div>13</div>
|
||||
<button class="option-btn" data-option="color-1">SPFPDS13FTW</button>
|
||||
<button class="option-btn" data-option="color-2">SPFPDS13FTC</button>
|
||||
<div>10</div>
|
||||
<button class="option-btn" data-option="color-1">SPFPDS10FTW</button>
|
||||
<button class="option-btn" data-option="color-2">SPFPDS10FTC</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -352,13 +361,9 @@
|
||||
</div>
|
||||
<div class="category-content">
|
||||
<div class="option-group">
|
||||
13
|
||||
<div>13</div>
|
||||
<button class="option-btn" data-option="color-1">SPF111S1013W</button>
|
||||
<button class="option-btn" data-option="color-2">SPF111S1013C</button>
|
||||
<button class="option-btn" data-option="color-3">SPF111S1013TA</button>
|
||||
10
|
||||
<button class="option-btn" data-option="color-1">SPF111S1010W</button>
|
||||
<button class="option-btn" data-option="color-2">SPF111S1010C</button>
|
||||
<div>10</div>
|
||||
<button class="option-btn" data-option="color-3">SPF111S1010TA</button>
|
||||
|
||||
</div>
|
||||
@ -461,7 +466,10 @@
|
||||
<script type="module" src="./index.js"></script>
|
||||
<script type="module">
|
||||
import { kernel } from './src/main.ts';
|
||||
import { initApp, init, getAutoLoadModelList, getPlacementZone, getEvent, getHotspot, executeEvent2, getProductConfig } from './index.js';
|
||||
import { initApp, init, getAutoLoadModelList, getPlacementZone, getEvent, getHotspot, executeEvent2, getProductConfig, getSkuByModelId } from './index.js';
|
||||
|
||||
// 将 getSkuByModelId 挂载到 window 对象,供事件处理器使用
|
||||
window.getSkuByModelId = getSkuByModelId;
|
||||
|
||||
// 注入 kernel 实例到业务逻辑
|
||||
initApp(kernel);
|
||||
@ -754,13 +762,9 @@
|
||||
// 移除按钮事件
|
||||
document.getElementById('remove-model-btn').addEventListener('click', () => {
|
||||
const pickedMesh = window.getCurrentPickedMesh();
|
||||
console.log(pickedMesh);
|
||||
|
||||
if (pickedMesh) {
|
||||
const meshName = pickedMesh.name;
|
||||
const modelName = kernel.model.findModelNameByMesh(pickedMesh);
|
||||
console.log(modelName);
|
||||
|
||||
const success = kernel.model.removeByName(modelName);
|
||||
if (success) {
|
||||
console.log('模型已移除');
|
||||
@ -873,6 +877,13 @@
|
||||
kernel.on('model:click', (data) => {
|
||||
console.log('模型点击事件', data);
|
||||
console.log('模型控制类型:', data.modelControlType);
|
||||
|
||||
// 获取模型关联的 SKU
|
||||
const modelName = data.modelName;
|
||||
const sku = window.getSkuByModelId(modelName);
|
||||
console.log('点击的模型ID:', modelName);
|
||||
console.log('关联的SKU:', sku || '未找到关联的SKU');
|
||||
|
||||
switch (data.modelControlType) {
|
||||
case "color":
|
||||
// DOM 2D转3D 示例:点击模型时显示信息框
|
||||
|
||||
37
index.js
37
index.js
@ -1,9 +1,13 @@
|
||||
import { EXRCubeTexture } from '@babylonjs/core';
|
||||
import apiConfig from './src/config.js';
|
||||
import { setSkuMapping, getSkuByModelId, clearSkuMapping, clearAllSkuMappings } from './src/skuMapping.js';
|
||||
|
||||
// 存储 kernel 实例
|
||||
let kernelInstance = null;
|
||||
|
||||
// 导出 SKU 映射相关函数,方便外部使用
|
||||
export { getSkuByModelId, clearSkuMapping, clearAllSkuMappings };
|
||||
|
||||
/**
|
||||
* 初始化应用逻辑 - 注入 kernel 实例
|
||||
* @param {Object} kernel - SDK kernel 实例
|
||||
@ -131,7 +135,7 @@ export const getEvent = async (dropzone_data, sku) => {
|
||||
console.log('关联事件:', result.data.events);
|
||||
|
||||
// 使用 for...of 循环以支持 await
|
||||
await executeEvent(dropzone_data, result)
|
||||
await executeEvent(dropzone_data, result, sku)
|
||||
} else {
|
||||
console.log(`未查询到数据`);
|
||||
}
|
||||
@ -141,8 +145,7 @@ export const getEvent = async (dropzone_data, sku) => {
|
||||
}
|
||||
|
||||
//点击放置区域执行事件 一般是换配件
|
||||
//点击放置区域执行事件 一般是换配件
|
||||
export const executeEvent = async (dropzone_data, result) => {
|
||||
export const executeEvent = async (dropzone_data, result, sku) => {
|
||||
const kernel = getKernel();
|
||||
|
||||
const { wallName, index, transform } = dropzone_data;
|
||||
@ -160,6 +163,9 @@ export const executeEvent = async (dropzone_data, result) => {
|
||||
modelName = name;
|
||||
kernel.dropZone.recordModelPlacement(wallName, index, name + '_' + modelId);
|
||||
|
||||
// 记录模型ID到SKU的映射
|
||||
setSkuMapping(modelId, sku);
|
||||
|
||||
await kernel.model.add({
|
||||
modelName: name,
|
||||
modelId: modelId,
|
||||
@ -192,8 +198,8 @@ export const executeEvent = async (dropzone_data, result) => {
|
||||
albedoColor: color,
|
||||
albedoTexture: color_map_url,
|
||||
normalMap: normal_map_url,
|
||||
metallic: metallic,
|
||||
roughness: roughness
|
||||
metallic: +metallic,
|
||||
roughness: +roughness
|
||||
});
|
||||
|
||||
console.log(`百叶模型颜色已替换为 ${color}`);
|
||||
@ -203,7 +209,7 @@ export const executeEvent = async (dropzone_data, result) => {
|
||||
|
||||
|
||||
//一般是换棚子/换颜色/设置放置区域
|
||||
export const executeEvent2 = async (result) => {
|
||||
export const executeEvent2 = async (result, sku) => {
|
||||
const kernel = getKernel();
|
||||
|
||||
// 检查是否有模型更换事件
|
||||
@ -219,16 +225,16 @@ export const executeEvent2 = async (result) => {
|
||||
console.log(`检查模型 ${name + '_' + category} 是否存在:`, modelAlreadyExists);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(hasModelChange && !modelAlreadyExists);
|
||||
kernel.dropZone.hide();
|
||||
// 只有在需要更换模型且模型不存在时才清除
|
||||
if (hasModelChange && !modelAlreadyExists) {
|
||||
console.log('模型不存在,执行清除操作');
|
||||
|
||||
kernel.model.removeAll();
|
||||
} else if (modelAlreadyExists) {
|
||||
kernel.dropZone.hide();
|
||||
console.log('模型已存在,跳过清除操作,仅更新材质');
|
||||
}
|
||||
// 清除所有 SKU 映射
|
||||
clearAllSkuMappings();
|
||||
}
|
||||
|
||||
// 先处理所有 change_model 事件
|
||||
for (const event of result.data.events) {
|
||||
@ -259,6 +265,9 @@ export const executeEvent2 = async (result) => {
|
||||
});
|
||||
}
|
||||
|
||||
// 记录模型ID到SKU的映射
|
||||
setSkuMapping(category, sku);
|
||||
|
||||
// 加载并放置模型(使用 category 作为 modelId)
|
||||
await kernel.model.add({
|
||||
modelName: name,
|
||||
@ -276,15 +285,13 @@ export const executeEvent2 = async (result) => {
|
||||
if (event.event_type === 'change_color') {
|
||||
const materialName = event.material_name;
|
||||
const { color, color_map_url, normal_map_url, metallic, roughness } = event.target_data;
|
||||
console.log('替换百叶模型颜色:', event.target_data);
|
||||
console.log('替换模型颜色:', event.target_data);
|
||||
|
||||
kernel.material.apply({
|
||||
target: materialName,
|
||||
albedoColor: color,
|
||||
albedoTexture: color_map_url,
|
||||
normalMap: normal_map_url,
|
||||
metallic: metallic,
|
||||
roughness: roughness
|
||||
});
|
||||
|
||||
console.log(`百叶模型颜色已替换为 ${color}`);
|
||||
@ -341,7 +348,7 @@ export const getProductConfig = async (sku) => {
|
||||
getPlacementZone(sku)
|
||||
}
|
||||
else {
|
||||
executeEvent2(result)
|
||||
executeEvent2(result, sku)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@ -787,9 +787,11 @@ export class GameManager extends Monobehiver {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
// 没有提供 modelId,全局查找(保持向后兼容)
|
||||
this.materialDic.Values().forEach(material => {
|
||||
if (material.name === options.target || material.name.startsWith(`${options.target}_`)) {
|
||||
console.log(material.name);
|
||||
targetMaterials.push(material);
|
||||
}
|
||||
});
|
||||
@ -799,7 +801,7 @@ export class GameManager extends Monobehiver {
|
||||
console.warn(`Material not found: ${options.target}${options.modelId ? ` in model ${options.modelId}` : ''}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(options);
|
||||
// 应用材质属性到目标材质
|
||||
targetMaterials.forEach(material => {
|
||||
// 应用颜色
|
||||
@ -818,36 +820,37 @@ export class GameManager extends Monobehiver {
|
||||
}
|
||||
}
|
||||
|
||||
// 应用法线贴图
|
||||
if (options.normalMap !== undefined) {
|
||||
if (options.normalMap) {
|
||||
material.bumpTexture = new Texture(options.normalMap);
|
||||
} else {
|
||||
// 传入空字符串或 null 时清空贴图
|
||||
material.bumpTexture = null;
|
||||
}
|
||||
}
|
||||
// // 应用法线贴图
|
||||
// if (options.normalMap !== undefined) {
|
||||
// if (options.normalMap) {
|
||||
// material.bumpTexture = new Texture(options.normalMap);
|
||||
// } else {
|
||||
// // 传入空字符串或 null 时清空贴图
|
||||
// material.bumpTexture = null;
|
||||
// }
|
||||
// }
|
||||
|
||||
// 应用金属度贴图
|
||||
if (options.metallicTexture !== undefined) {
|
||||
if (options.metallicTexture) {
|
||||
material.metallicTexture = new Texture(options.metallicTexture);
|
||||
} else {
|
||||
// 传入空字符串或 null 时清空贴图
|
||||
material.metallicTexture = null;
|
||||
}
|
||||
}
|
||||
// // 应用金属度贴图
|
||||
// if (options.metallicTexture !== undefined) {
|
||||
// if (options.metallicTexture) {
|
||||
// material.metallicTexture = new Texture(options.metallicTexture);
|
||||
// } else {
|
||||
// // 传入空字符串或 null 时清空贴图
|
||||
// material.metallicTexture = null;
|
||||
// }
|
||||
// }
|
||||
|
||||
// 应用粗糙度值
|
||||
if (options.roughness !== undefined) {
|
||||
material.roughness = options.roughness;
|
||||
}
|
||||
|
||||
// 应用金属度值
|
||||
if (options.metallic !== undefined) {
|
||||
material.metallic = options.metallic;
|
||||
}
|
||||
// if (options.roughness !== undefined) {
|
||||
// material.roughness = options.roughness;
|
||||
// }
|
||||
|
||||
// // 应用金属度值
|
||||
// if (options.metallic !== undefined) {
|
||||
// material.metallic = options.metallic;
|
||||
// }
|
||||
// alert(typeof options.metallic + ' ' + typeof options.roughness);
|
||||
|
||||
// 强制刷新材质
|
||||
material.markDirty();
|
||||
});
|
||||
|
||||
69
src/skuMapping.js
Normal file
69
src/skuMapping.js
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* SKU 映射管理模块
|
||||
* 用于维护模型ID与SKU之间的映射关系
|
||||
*/
|
||||
|
||||
// 存储模型ID到SKU的映射
|
||||
const modelIdToSkuMap = new Map();
|
||||
|
||||
/**
|
||||
* 记录模型ID与SKU的映射关系
|
||||
* @param {string} modelId - 模型ID
|
||||
* @param {string} sku - SKU编码
|
||||
*/
|
||||
export const setSkuMapping = (modelId, sku) => {
|
||||
if (!modelId || !sku) {
|
||||
console.warn('modelId 和 sku 不能为空');
|
||||
return;
|
||||
}
|
||||
modelIdToSkuMap.set(modelId, sku);
|
||||
console.log(`已记录映射: ${modelId} -> ${sku}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据模型ID获取关联的SKU
|
||||
* @param {string} modelId - 模型ID
|
||||
* @returns {string|undefined} SKU编码,未找到返回 undefined
|
||||
*/
|
||||
export const getSkuByModelId = (modelId) => {
|
||||
return modelIdToSkuMap.get(modelId);
|
||||
};
|
||||
|
||||
/**
|
||||
* 清除指定模型ID的SKU映射
|
||||
* @param {string} modelId - 模型ID
|
||||
* @returns {boolean} 是否成功删除
|
||||
*/
|
||||
export const clearSkuMapping = (modelId) => {
|
||||
const deleted = modelIdToSkuMap.delete(modelId);
|
||||
if (deleted) {
|
||||
console.log(`已清除映射: ${modelId}`);
|
||||
}
|
||||
return deleted;
|
||||
};
|
||||
|
||||
/**
|
||||
* 清除所有SKU映射
|
||||
*/
|
||||
export const clearAllSkuMappings = () => {
|
||||
const count = modelIdToSkuMap.size;
|
||||
modelIdToSkuMap.clear();
|
||||
console.log(`已清除所有映射,共 ${count} 条`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取所有映射关系(用于调试)
|
||||
* @returns {Object} 映射关系对象
|
||||
*/
|
||||
export const getAllMappings = () => {
|
||||
return Object.fromEntries(modelIdToSkuMap);
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查模型ID是否有映射
|
||||
* @param {string} modelId - 模型ID
|
||||
* @returns {boolean} 是否存在映射
|
||||
*/
|
||||
export const hasSkuMapping = (modelId) => {
|
||||
return modelIdToSkuMap.has(modelId);
|
||||
};
|
||||
Reference in New Issue
Block a user