import { watchEffect, nextTick } from 'vue' import { fuseModelsLoaded, SceneType } from '@/store' import { fuseModel } from './' import { initialSDK, initialed as fuseInitialed, sdk as fuseSDK } from '@/sdk' import { asyncTimeout } from '@/utils' import type { ModelType } from './' export async function modelSDKFactory ( type: ModelType, dom: HTMLDivElement | HTMLIFrameElement ): Promise { console.log(type, dom) if (type === fuseModel) { if (!fuseInitialed) { await initialSDK({ layout: dom }) } return exposeFactory(fuseModel) } else { const iframe = dom as HTMLIFrameElement const win = await new Promise((resolve, reject) => { const loadedHandler = () => { resolve(iframe.contentWindow) cleanup() } const errorHandler = (err: any) => { reject(err) cleanup() } const cleanup = () => { iframe.removeEventListener('load', loadedHandler) iframe.removeEventListener('error', errorHandler) } iframe.addEventListener('load', loadedHandler) iframe.addEventListener('error', errorHandler) }) if (!win) { throw new Error('场景加载失败') } return await exposeFactory(type, win) } } const findObjectAttr = (data: T, key: K): Promise => { return new Promise(resolve => { const query = () => { if (key in data) { resolve(data[key]) } else { setTimeout(query, 6) } } query() }) } const fuseLoaded = new Promise(resolve => { const stop = watchEffect(() => { if (fuseModelsLoaded.value) { resolve() nextTick(() => stop()) } }) }) export interface ModelExpose { getView: () => Promise<{ image: Blob, flyData: string }> setView: (flyData: string) => void } export async function exposeFactory(type: ModelType, win?: any): Promise { const sceneType = type === fuseModel ? fuseModel : type.type const platforms: {[key in any]: {getSDK: () => Promise, expose: ModelExpose}} = { [fuseModel]: { getSDK: async () => { await fuseLoaded return fuseSDK }, expose: { async getView() { const dataURL = await sdk.screenshot(260, 160) const res = await fetch(dataURL) const image = await res.blob() const pose = sdk.getPose() return { image, flyData: JSON.stringify(pose) } }, async setView(flyData: string) { const pose = JSON.parse(flyData) sdk.comeTo({ dur: 300, ...pose }) } } }, [SceneType.SWKK]: { getSDK: async () => { const sdk = await findObjectAttr(win , '__sdk') if (!sdk.Scene.loaded) { await new Promise(reoslve => sdk.Scene.on('loaded', reoslve)) } return sdk }, expose: { async getView() { const pose = sdk.Camera.getPose() const images = await sdk.Camera.screenshot( [{ width: 260, height: 160, name: '2k' }], true ) return { image: images[0].data, flyData: JSON.stringify(pose) } }, async setView(flyData: string) { const pose = JSON.parse(flyData) sdk.Camera.setPose({ dur: 300, ...pose }) } } }, [SceneType.SWSS]: { getSDK: async () => { await findObjectAttr(win, 'laserLoaded') return await findObjectAttr(win, '__sdk') }, expose: { async getView() { const dataURL = await sdk.scene.screenshot(260, 160) const res = await fetch(dataURL) const image = await res.blob() const pose = await sdk.scene.getPose() const mode = sdk.customMap.mode return { image, flyData: JSON.stringify({ pose, mode }) } }, async setView(flyData: string) { const { pose, mode } = JSON.parse(flyData) sdk.customMap.mode = mode sdk.scene.setPose(pose, 300) } } } } platforms[SceneType.SWSSMX] = platforms[SceneType.SWKJ] = platforms[SceneType.SWKK] platforms[SceneType.SWMX] = { getSDK: async () => findObjectAttr(win , '__sdk'), expose: platforms[fuseModel].expose } if (!(sceneType in platforms)) { throw new Error('不支持该类型场景!') } const sdk: any = await Promise.race([ asyncTimeout(10000) .then(() => Promise.reject(new Error('加载超时'))), platforms[sceneType].getSDK() ]) return platforms[sceneType].expose }