import { sdk } from './sdk' import { models, isEdit, sysBus, getModelShowVariable, ModelType, backupModels } from '@/store' import { toRaw, watchEffect, ref, watch, createApp } from 'vue' import { viewModeStack, custom, getResource, showRightCtrlPanoStack } from '@/env' import { diffArrayChange, shallowWatchArray, arrayChildEffectScope, togetherCallback, showLoad, hideLoad } from '@/utils' import SDKApp from './index.vue' import Components from 'bill/index' import { Model } from '@/store' import type { SDK, SceneModel, SceneGuidePath, ModelAttrRange } from '.' export const modelRange: ModelAttrRange = { opacityRange: { min: 0, max: 100, step: 0.1 }, bottomRange: { min: -30, max: 70, step: 0.1 }, scaleRange: { min: 0, max: 200, step: 0.1 } } const sceneModelMap = new WeakMap() export const getSceneModel = (model: Model | null) => model && sceneModelMap.get(toRaw(model)) const associationModels = (sdk: SDK) => { const getModels = () => models.value shallowWatchArray(getModels, (models, oldModels) => { const { added, deleted } = diffArrayChange(models, oldModels) for (const item of added) { if (getSceneModel(item)) { continue; } const itemRaw = toRaw(item) console.log('加载模型', { ...itemRaw, ...modelRange, url: getResource(item.url) }) const sceneModel = sdk.addModel({ ...itemRaw, ...modelRange, // type: ModelType.SWMX, url: getResource(item.url) }) sceneModelMap.set(itemRaw, sceneModel) sceneModel.bus.on('transformChanged', transform => { Object.assign(item, transform) }) sceneModel.bus.on('changeSelect', select => { 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 backupModels() 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) { getSceneModel(item)?.destroy() } }) arrayChildEffectScope(getModels, item => { const stopLoadedWatch = watch( () => item.loaded, (loaded) => { if (loaded) { const modelShow = getModelShowVariable(item) watchEffect(() => { getSceneModel(item)?.changeBottom(item.bottom) }) watchEffect(() => getSceneModel(item)?.changeOpacity(item.opacity)) watchEffect(() => getSceneModel(item)?.changeScale(item.scale)) watchEffect(() => { console.error(getSceneModel(item), 'changeshow', modelShow.value) getSceneModel(item)?.changeShow(modelShow.value) }) stopLoadedWatch() } } ) }) } const fullView = async (fn: () => void) => { const pop = togetherCallback([ viewModeStack.push(ref('full')), showRightCtrlPanoStack.push(ref(false)) ]) await document.documentElement.requestFullscreen() const driving = () => document.fullscreenElement || fn() document.addEventListener('fullscreenchange', driving) document.addEventListener('fullscreenerror', fn) return () => { pop() document.fullscreenElement && document.exitFullscreen() document.removeEventListener('fullscreenchange', driving) document.removeEventListener('fullscreenerror', fn) } } export const isScenePlayIng = ref(false) export const playSceneGuide = async (paths: SceneGuidePath[], changeIndexCallback?: (index: number) => void) => { if (isScenePlayIng.value) { throw new Error('导览正在播放') } isScenePlayIng.value = true const sceneGuide = sdk.enterSceneGuide(paths) changeIndexCallback && sceneGuide.bus.on('changePoint', changeIndexCallback) const quitHandler = () => (isScenePlayIng.value = false) const clearHandler = isEdit.value ? null : await fullView(quitHandler) if (!clearHandler) { sysBus.on('leave', quitHandler, { last: true }) sysBus.on('save', quitHandler, { last: true }) } sceneGuide.play() const reces = [ new Promise(resolve => sceneGuide.bus.on('playComplete', resolve)), new Promise(resolve => { const stop = watch(isScenePlayIng, () => { if (!isScenePlayIng.value) { resolve() sceneGuide.pause() stop() } }) }), ] await Promise.race(reces) isScenePlayIng.value = false if (clearHandler) { clearHandler() } else { sysBus.off('leave', quitHandler) sysBus.off('save', quitHandler) } sceneGuide.clear() sceneGuide.bus.off('changePoint') } export const pauseSceneGuide = () => isScenePlayIng.value = false export const setupAssociation = (mountEl: HTMLDivElement) => { associationModels(sdk) const sdkApp = createApp(SDKApp) sdkApp.mount(mountEl) sdkApp.use(Components) }