import { SDK, SceneModel, ModelAttrRange } from "../sdk"; import { toRaw, watch, reactive, ref } from "vue"; import { custom, getResource } from "@/env"; import { diffArrayChange, shallowWatchArray, arrayChildEffectScope, showLoad, hideLoad, deepIsRevise, round, } from "@/utils"; import { dynamicAddedModelIds, fuseModels, getFuseModelShowVariable, SceneType, SceneStatus, FuseModel, FuseModels, } from "@/store"; import { currentLayout, RoutesName } from "@/router"; import { isUnSet, unSet } from "@/utils/unset"; // -----------------模型关联-------------------- export const modelRange: ModelAttrRange = { opacityRange: { min: 0, max: 100, step: 0.1 }, bottomRange: { min: -30, max: 70, step: 0.1 }, scaleRange: { min: 0.1, max: 200, step: 0.1 }, }; export const sceneModelMap = reactive(new Map()); export const getSceneModel = (model?: FuseModel | null) => model && sceneModelMap.get(toRaw(model)); export const getFuseModel = (model?: SceneModel | null) => { if (!model) return null; for (const [k, v] of sceneModelMap.entries()) { if (toRaw(v) === toRaw(model)) { return k; } } }; const setModels = (sdk: SDK, models: FuseModels, oldModels: FuseModels) => { const { added, deleted } = diffArrayChange(models, oldModels); for (const item of added) { if (getSceneModel(item)) { continue; } if (item.status !== SceneStatus.SUCCESS) { item.error = true; item.loaded = true; continue; } const itemRaw = toRaw(item); let sceneModel: SceneModel; try { sceneModel = sdk.addModel({ ...itemRaw, ...modelRange, mode: RoutesName.signModel === currentLayout.value! ? "single" : "many", isDynamicAdded: dynamicAddedModelIds.value.some( (id) => itemRaw.id === id ), type: [SceneType.SWSS, SceneType.SWYDSS].includes(item.type) ? "laser" : item.modelType, url: [SceneType.SWSS, SceneType.SWYDSS].includes(item.type) ? item.url : item.url && item.url.map(getResource), fromType: item.type, }); } catch (e) { console.error("模型加载失败", e); item.error = true; return; } sceneModelMap.set(itemRaw, sceneModel); let changeId: NodeJS.Timeout; sceneModel.bus.on("transformChanged", (transform) => { clearTimeout(changeId); changeId = setTimeout(() => { transform = { ...transform }; if (transform.rotation) { transform.rotation = { x: round(transform.rotation.x, 5), y: round(transform.rotation.y, 5), z: round(transform.rotation.z, 5), }; } if (transform.position) { transform.position = { x: round(transform.position.x, 5), y: round(transform.position.y, 5), z: round(transform.position.z, 5), }; } delete transform.bottom; // if (transform.bottom) { // transform.bottom = round(transform.bottom, 2) // } if (transform.scale) { transform.scale = round(transform.scale, 2); } const updateKeys = Object.keys(transform); const update: any = {}; for (const key of updateKeys) { update[key] = (item as any)[key]; } if (deepIsRevise(update, transform)) { console.error('change', item) unSet(() => Object.assign(item, transform)); } }, 16); }); sceneModel.bus.on("changeSelect", (select) => { unSet(() => { // if (custom.showMode === "fuse") { if (custom.currentModel === item && !select) { custom.currentModel = null; } else if (custom.currentModel !== item && select) { custom.currentModel = item; } // } }); }); showLoad(); sceneModel.bus.on("loadDone", () => { item.loaded = true; hideLoad(); }); sceneModel.bus.on("loadError", () => { item.error = true; item.show = false; custom.showModelsMap.delete(item); hideLoad(); }); sceneModel.bus.on("loadProgress", (progress) => (item.progress = progress)); } for (const item of deleted) { console.error("销毁", item); getSceneModel(item)?.destroy(); sceneModelMap.delete(item); } }; export const activeModel = (status: { showMode: "fuse" | "pano"; active?: FuseModel; fore?: boolean }) => { const oldStatus = { showMode: custom.showMode, active: custom.currentModel, }; if ( toRaw(status.active) === toRaw(oldStatus.active) && status.showMode === oldStatus.showMode ) { return; } const model = status.active && getSceneModel(status.active)!; const oldModel = oldStatus.active && getSceneModel(oldStatus.active)!; if (oldModel) { oldModel.changeSelect(false); } if (model && status.active === oldStatus.active) { if (status.showMode === "pano") { if (model) { model.changeSelect(false) model.flyInPano(); } } else { if (model) { model.flyOutPano(); custom.currentModel === status.active && model.changeSelect(true) } } } else { if (oldStatus.showMode !== status.showMode) { if (oldStatus.showMode === "pano") { if (oldModel) { oldModel.flyOutPano(); custom.currentModel === oldStatus.active && oldModel.changeSelect(true) } } } if (status.showMode === "pano") { if (model) { model.changeSelect(false) model.flyInPano(); } } else { console.log("select"); } } setTimeout(() => { if (status.showMode !== "pano" && model) { if (oldStatus.showMode !== 'pano' || status.fore) { model && model.changeSelect(true); } } }, 35); custom.currentModel = status.active!; custom.showMode = status.showMode; }; export const associationModels = (sdk: SDK) => { sdk.sceneBus.on("modeChange", (data) => { custom.showMode = data.mode; if (data.active) { custom.currentModel = getFuseModel(data.active)!; } console.log('modeChange', data, custom.showMode) }); sdk.sceneBus.on("panoModelChange", (data) => { custom.showMode = "pano"; custom.currentModel = getFuseModel(data)!; }); const getModels = () => fuseModels.value.filter( (model) => getSceneModel(model) || getFuseModelShowVariable(model).value ); shallowWatchArray(getModels, (models, oldModels) => { setModels(sdk, models, oldModels); }); arrayChildEffectScope(getModels, (item) => { const stopLoadedWatch = watch( () => item.loaded, (loaded) => { if (loaded) { const modelShow = getFuseModelShowVariable(item); watch( () => item.bottom, () => isUnSet || getSceneModel(item)?.changeBottom(item.bottom) // { immediate: true } ); watch( () => item.opacity, () => isUnSet || getSceneModel(item)?.changeOpacity(item.opacity) // { immediate: true } ); watch( () => item.scale, () => isUnSet || getSceneModel(item)?.changeScale(item.scale) // { immediate: true } ); watch( () => item.position, () => { if (!isUnSet) { console.log('position', item.raw.modelTitle, toRaw(item.position)) getSceneModel(item)?.changePosition(item.position); } } // { immediate: true } ); watch( () => item.rotation, () => { if (!isUnSet) { console.log('rotation', item.raw.modelTitle, toRaw(item.rotation)) getSceneModel(item)?.changeRotation(toRaw(item.rotation)); } } // { immediate: true } ); watch( () => modelShow.value, () => { const sceneModel = getSceneModel(item); if (!isUnSet && sceneModel) { sceneModel.changeSelect(false); sceneModel.changeShow(modelShow.value); } }, { immediate: true } ); stopLoadedWatch(); } } // { immediate: true } ); }); };