1
This commit is contained in:
40
index.html
40
index.html
@ -275,19 +275,19 @@
|
|||||||
<div class="option-group">
|
<div class="option-group">
|
||||||
<div class="option-checkbox">
|
<div class="option-checkbox">
|
||||||
<input type="checkbox" id="louver-1" data-option="louver-1">
|
<input type="checkbox" id="louver-1" data-option="louver-1">
|
||||||
<label for="louver-1">百叶A</label>
|
<label for="louver-1">百叶1</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="option-checkbox">
|
<div class="option-checkbox">
|
||||||
<input type="checkbox" id="louver-2" data-option="louver-2">
|
<input type="checkbox" id="louver-2" data-option="louver-2">
|
||||||
<label for="louver-2">百叶B</label>
|
<label for="louver-2">百叶2</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="option-checkbox">
|
<div class="option-checkbox">
|
||||||
<input type="checkbox" id="louver-3" data-option="louver-3">
|
<input type="checkbox" id="louver-3" data-option="louver-3">
|
||||||
<label for="louver-3">百叶C</label>
|
<label for="louver-3">百叶3</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="option-checkbox">
|
<div class="option-checkbox">
|
||||||
<input type="checkbox" id="louver-4" data-option="louver-4">
|
<input type="checkbox" id="louver-4" data-option="louver-4">
|
||||||
<label for="louver-4">百叶D</label>
|
<label for="louver-4">百叶4</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -365,10 +365,11 @@
|
|||||||
|
|
||||||
// 多选复选框逻辑
|
// 多选复选框逻辑
|
||||||
document.querySelectorAll('.option-checkbox input[type="checkbox"]').forEach(checkbox => {
|
document.querySelectorAll('.option-checkbox input[type="checkbox"]').forEach(checkbox => {
|
||||||
checkbox.addEventListener('change', function () {
|
checkbox.addEventListener('change', async function () {
|
||||||
const category = this.closest('.config-category');
|
const category = this.closest('.config-category');
|
||||||
const categoryName = category.querySelector('.category-header').dataset.category;
|
const categoryName = category.querySelector('.category-header').dataset.category;
|
||||||
const optionGroup = this.closest('.option-group');
|
const optionGroup = this.closest('.option-group');
|
||||||
|
const checked = this.checked;
|
||||||
|
|
||||||
// 获取当前组所有选中的值
|
// 获取当前组所有选中的值
|
||||||
const selectedValues = Array.from(
|
const selectedValues = Array.from(
|
||||||
@ -395,17 +396,26 @@
|
|||||||
checked: this.checked,
|
checked: this.checked,
|
||||||
currentValue: this.dataset.option
|
currentValue: this.dataset.option
|
||||||
});
|
});
|
||||||
if (category === "louver") {
|
|
||||||
selectedValues.forEach(element => {
|
|
||||||
if (checked) {
|
|
||||||
kernel.model.add(element.text,`https://sdk.zguiy.com/resurces/model/${element.text}.glb`);
|
|
||||||
} else {
|
|
||||||
kernel.model.destroy(element.text);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// kernel.model.add('https://sdk.zguiy.com/resurces/model/百叶1.glb');
|
// 百叶模型加载/卸载逻辑
|
||||||
|
if (categoryName === "louver") {
|
||||||
|
const currentText = this.nextElementSibling.textContent;
|
||||||
|
const modelUrl = `https://sdk.zguiy.com/resurces/model/${currentText}.glb`;
|
||||||
|
console.log(modelUrl);
|
||||||
|
if (checked) {
|
||||||
|
// 加载模型
|
||||||
|
try {
|
||||||
|
await kernel.model.add(currentText, modelUrl);
|
||||||
|
console.log(`模型 ${currentText} 加载成功`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`模型 ${currentText} 加载失败:`, error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 卸载模型
|
||||||
|
kernel.model.remove(currentText);
|
||||||
|
console.log(`模型 ${currentText} 已卸载`);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@ type LoadResult = {
|
|||||||
* 模型管理类- 负责加载、缓存和管理3D模型
|
* 模型管理类- 负责加载、缓存和管理3D模型
|
||||||
*/
|
*/
|
||||||
export class AppModel extends Monobehiver {
|
export class AppModel extends Monobehiver {
|
||||||
private modelDic: Dictionary<AbstractMesh[]>;
|
private modelDic: Dictionary<AbstractMesh>;
|
||||||
private loadedMeshes: AbstractMesh[];
|
private loadedMeshes: AbstractMesh[];
|
||||||
private skeletonManager: any;
|
private skeletonManager: any;
|
||||||
private outfitManager: any;
|
private outfitManager: any;
|
||||||
@ -28,7 +28,7 @@ export class AppModel extends Monobehiver {
|
|||||||
|
|
||||||
constructor(mainApp: any) {
|
constructor(mainApp: any) {
|
||||||
super(mainApp);
|
super(mainApp);
|
||||||
this.modelDic = new Dictionary<AbstractMesh[]>();
|
this.modelDic = new Dictionary<AbstractMesh>();
|
||||||
this.loadedMeshes = [];
|
this.loadedMeshes = [];
|
||||||
this.skeletonManager = null;
|
this.skeletonManager = null;
|
||||||
this.outfitManager = null;
|
this.outfitManager = null;
|
||||||
@ -96,16 +96,14 @@ export class AppModel extends Monobehiver {
|
|||||||
*/
|
*/
|
||||||
async loadSingleModel(modelUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<LoadResult> {
|
async loadSingleModel(modelUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<LoadResult> {
|
||||||
try {
|
try {
|
||||||
const cached = this.getCachedMeshes(modelUrl);
|
|
||||||
if (cached) return { success: true, meshes: cached };
|
|
||||||
|
|
||||||
const scene: Scene | null = this.mainApp.appScene.object;
|
const scene: Scene | null = this.mainApp.appScene.object;
|
||||||
if (!scene) return { success: false, error: '场景未初始化' };
|
if (!scene) return { success: false, error: '场景未初始化' };
|
||||||
|
|
||||||
const result = await ImportMeshAsync(modelUrl, scene, { onProgress });
|
const result = await ImportMeshAsync(modelUrl, scene, { onProgress });
|
||||||
if (!result?.meshes?.length) return { success: false, error: '未找到网格' };
|
if (!result?.meshes?.length) return { success: false, error: '未找到网格' };
|
||||||
|
|
||||||
this.modelDic.Set(modelUrl, result.meshes);
|
// 存储根网格(通常是第一个网格)
|
||||||
|
const rootMesh = result.meshes[0];
|
||||||
this.loadedMeshes.push(...result.meshes);
|
this.loadedMeshes.push(...result.meshes);
|
||||||
return { success: true, meshes: result.meshes, skeletons: result.skeletons };
|
return { success: true, meshes: result.meshes, skeletons: result.skeletons };
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
@ -131,12 +129,12 @@ export class AppModel extends Monobehiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 获取缓存的网格 */
|
/** 获取缓存的网格 */
|
||||||
getCachedMeshes(url: string): AbstractMesh[] | undefined {
|
getCachedMeshes(url: string): AbstractMesh | undefined {
|
||||||
return this.modelDic.Get(url);
|
return this.modelDic.Get(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** 清理所有资源 */
|
/** 清理所有资源 */
|
||||||
clean(): void {
|
clean(): void {
|
||||||
@ -151,9 +149,19 @@ export class AppModel extends Monobehiver {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加模型到场景
|
* 添加模型到场景
|
||||||
|
* @param modelName 模型名称(用于后续引用)
|
||||||
* @param modelUrl 模型URL路径
|
* @param modelUrl 模型URL路径
|
||||||
*/
|
*/
|
||||||
async addModel(modelUrl: string): Promise<LoadResult> {
|
async add(modelName: string, modelUrl: string): Promise<LoadResult> {
|
||||||
|
// 检查是否已经存在该模型
|
||||||
|
const existingMesh = this.modelDic.Get(modelName);
|
||||||
|
if (existingMesh && !existingMesh.isDisposed()) {
|
||||||
|
console.log(`模型 ${modelName} 已存在,直接显示`);
|
||||||
|
existingMesh.setEnabled(true);
|
||||||
|
existingMesh.getChildMeshes().forEach(child => child.setEnabled(true));
|
||||||
|
return { success: true, meshes: [existingMesh, ...existingMesh.getChildMeshes()] };
|
||||||
|
}
|
||||||
|
|
||||||
const handleProgress = (event: ISceneLoaderProgressEvent): void => {
|
const handleProgress = (event: ISceneLoaderProgressEvent): void => {
|
||||||
const progress = event.lengthComputable && event.total > 0
|
const progress = event.lengthComputable && event.total > 0
|
||||||
? Math.min(1, event.loaded / event.total)
|
? Math.min(1, event.loaded / event.total)
|
||||||
@ -175,7 +183,10 @@ export class AppModel extends Monobehiver {
|
|||||||
|
|
||||||
const result = await this.loadSingleModel(modelUrl, handleProgress);
|
const result = await this.loadSingleModel(modelUrl, handleProgress);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success && result.meshes) {
|
||||||
|
// 使用modelName作为key存储根网格
|
||||||
|
const rootMesh = result.meshes[0];
|
||||||
|
this.modelDic.Set(modelName, rootMesh);
|
||||||
EventBridge.modelLoaded({ urls: [modelUrl] });
|
EventBridge.modelLoaded({ urls: [modelUrl] });
|
||||||
} else {
|
} else {
|
||||||
EventBridge.modelLoadError({ url: modelUrl, error: result.error });
|
EventBridge.modelLoadError({ url: modelUrl, error: result.error });
|
||||||
@ -191,35 +202,27 @@ export class AppModel extends Monobehiver {
|
|||||||
*/
|
*/
|
||||||
async replaceModel(modelName: string, newModelUrl: string): Promise<LoadResult> {
|
async replaceModel(modelName: string, newModelUrl: string): Promise<LoadResult> {
|
||||||
// 先销毁旧模型
|
// 先销毁旧模型
|
||||||
this.destroyModel(modelName);
|
this.remove(modelName);
|
||||||
|
|
||||||
// 加载新模型
|
// 加载新模型
|
||||||
return await this.addModel(newModelUrl);
|
return await this.add(modelName, newModelUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 销毁指定模型
|
* 销毁指定模型
|
||||||
* @param modelName 模型名称
|
* @param modelName 模型名称
|
||||||
*/
|
*/
|
||||||
destroyModel(modelName: string): void {
|
remove(modelName: string): void {
|
||||||
// 遍历模型字典,查找匹配的模型
|
const mesh = this.modelDic.Get(modelName);
|
||||||
const keys = this.modelDic.Keys();
|
if (mesh) {
|
||||||
for (const key of keys) {
|
// 隐藏网格而不是销毁,以便后续可以重新显示
|
||||||
if (key.includes(modelName)) {
|
mesh.setEnabled(false);
|
||||||
const meshes = this.modelDic.Get(key);
|
mesh.getChildMeshes().forEach(child => child.setEnabled(false));
|
||||||
if (meshes) {
|
|
||||||
// 销毁所有网格
|
console.log(`Model hidden: ${modelName}`);
|
||||||
meshes.forEach(mesh => mesh?.dispose());
|
} else {
|
||||||
// 从字典中移除
|
console.warn(`Model not found: ${modelName}`);
|
||||||
this.modelDic.Remove(key);
|
|
||||||
// 从加载的网格列表中移除
|
|
||||||
this.loadedMeshes = this.loadedMeshes.filter(mesh => !meshes.includes(mesh));
|
|
||||||
console.log(`Model destroyed: ${modelName}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
console.warn(`Model not found: ${modelName}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,15 +17,15 @@ export class KernelAdapter {
|
|||||||
* 添加模型到场景
|
* 添加模型到场景
|
||||||
* @param modelUrl 模型URL路径
|
* @param modelUrl 模型URL路径
|
||||||
*/
|
*/
|
||||||
add: async (modelUrl: string): Promise<void> => {
|
add: async (name:string,modelUrl: string): Promise<void> => {
|
||||||
await this.mainApp.appModel.addModel(modelUrl);
|
await this.mainApp.appModel.add(name,modelUrl);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 销毁指定模型
|
* 销毁指定模型
|
||||||
* @param modelName 模型名称
|
* @param modelName 模型名称
|
||||||
*/
|
*/
|
||||||
destroy: (modelName: string): void => {
|
remove: (modelName: string): void => {
|
||||||
this.mainApp.appModel.destroyModel(modelName);
|
this.mainApp.appModel.remove(modelName);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 替换模型
|
* 替换模型
|
||||||
@ -45,6 +45,14 @@ export class KernelAdapter {
|
|||||||
*/
|
*/
|
||||||
apply: (options: { target: string; attribute: string,value:number|string }): void => {
|
apply: (options: { target: string; attribute: string,value:number|string }): void => {
|
||||||
this.mainApp.gameManager.applyMaterial(options.target, options.attribute,options.value);
|
this.mainApp.gameManager.applyMaterial(options.target, options.attribute,options.value);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 更换材质颜色
|
||||||
|
* @param materialName 材质名称
|
||||||
|
* @param hexColor 16进制颜色值,例如 "#FF0000"
|
||||||
|
*/
|
||||||
|
color: (materialName: string, hexColor: string): void => {
|
||||||
|
this.mainApp.gameManager.applyMaterial(materialName, 'baseColor', hexColor);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user