fuseMode.ts 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. import { SDK, SceneModel, ModelAttrRange } from "../sdk";
  2. import { toRaw, watch, reactive, ref, watchEffect } from "vue";
  3. import { custom, getResource, getResources } from "@/env";
  4. import {
  5. diffArrayChange,
  6. shallowWatchArray,
  7. arrayChildEffectScope,
  8. showLoad,
  9. hideLoad,
  10. deepIsRevise,
  11. round,
  12. } from "@/utils";
  13. import {
  14. dynamicAddedModelIds,
  15. fuseModels,
  16. getFuseModelShowVariable,
  17. SceneType,
  18. SceneStatus,
  19. FuseModel,
  20. FuseModels,
  21. taggings,
  22. taggingPositions,
  23. } from "@/store";
  24. import { currentLayout, RoutesName } from "@/router";
  25. import { unsetFactory } from "@/utils/unset";
  26. import { getTaggingPosNode, taggingGroup } from "./tagging";
  27. const us = unsetFactory()
  28. // -----------------模型关联--------------------
  29. export const modelRange: ModelAttrRange = {
  30. opacityRange: { min: 0, max: 100, step: 0.1 },
  31. bottomRange: { min: -30, max: 70, step: 0.1 },
  32. scaleRange: { min: 0.1, max: 200, step: 0.1 },
  33. };
  34. export const sceneModelMap = reactive(new Map<FuseModel, SceneModel>());
  35. export const getSceneModel = (model?: FuseModel | null) =>
  36. model && sceneModelMap.get(toRaw(model));
  37. export const getFuseModel = (model?: SceneModel | null) => {
  38. if (!model) return null;
  39. for (const [k, v] of sceneModelMap.entries()) {
  40. if (toRaw(v) === toRaw(model)) {
  41. return k;
  42. }
  43. }
  44. };
  45. const setModels = (sdk: SDK, models: FuseModels, oldModels: FuseModels) => {
  46. const { added, deleted } = diffArrayChange(models, oldModels);
  47. for (const item of added) {
  48. if (getSceneModel(item)) {
  49. continue;
  50. }
  51. if (item.status !== SceneStatus.SUCCESS) {
  52. item.error = true;
  53. item.loaded = true;
  54. continue;
  55. }
  56. const itemRaw = toRaw(item);
  57. let sceneModel: SceneModel;
  58. try {
  59. console.error('addMode', itemRaw)
  60. sceneModel = sdk.addModel({
  61. ...itemRaw,
  62. ...modelRange,
  63. mode: RoutesName.signModel === currentLayout.value! ? "single" : "many",
  64. isDynamicAdded: dynamicAddedModelIds.value.some(
  65. (id) => itemRaw.id === id
  66. ),
  67. type: [SceneType.SWSS, SceneType.SWYDSS].includes(item.type)
  68. ? "laser"
  69. : item.modelType,
  70. url: [SceneType.SWSS, SceneType.SWYDSS].includes(item.type)
  71. ? item.url
  72. : item.url && item.url.map(getResources),
  73. fromType: item.type,
  74. });
  75. } catch (e) {
  76. console.error("模型加载失败", e);
  77. item.error = true;
  78. return;
  79. }
  80. sceneModelMap.set(itemRaw, sceneModel);
  81. let changeId: NodeJS.Timeout;
  82. sceneModel.bus.on("transformChanged", (transform) => {
  83. clearTimeout(changeId);
  84. changeId = setTimeout(() => {
  85. transform = { ...transform };
  86. if (transform.rotation) {
  87. transform.rotation = {
  88. x: round(transform.rotation.x, 5),
  89. y: round(transform.rotation.y, 5),
  90. z: round(transform.rotation.z, 5),
  91. };
  92. }
  93. if (transform.position) {
  94. transform.position = {
  95. x: round(transform.position.x, 5),
  96. y: round(transform.position.y, 5),
  97. z: round(transform.position.z, 5),
  98. };
  99. }
  100. delete transform.bottom;
  101. // if (transform.bottom) {
  102. // transform.bottom = round(transform.bottom, 2)
  103. // }
  104. if (transform.scale) {
  105. transform.scale = round(transform.scale, 2);
  106. taggingPositions.value.forEach(position => {
  107. getTaggingPosNode(position)?.bus.emit('scaleChanged', true)
  108. })
  109. }
  110. const updateKeys = Object.keys(transform);
  111. const update: any = {};
  112. for (const key of updateKeys) {
  113. update[key] = (item as any)[key];
  114. }
  115. if (deepIsRevise(update, transform)) {
  116. console.error('change', item)
  117. us.unSet(() => Object.assign(item, transform));
  118. }
  119. }, 16);
  120. });
  121. sceneModel.bus.on("changeSelect", (select) => {
  122. us.unSet(() => {
  123. // if (custom.showMode === "fuse") {
  124. if (custom.currentModel === item && !select) {
  125. custom.currentModel = null;
  126. } else if (custom.currentModel !== item && select) {
  127. custom.currentModel = item;
  128. }
  129. // }
  130. });
  131. });
  132. showLoad();
  133. sceneModel.bus.on("loadDone", () => {
  134. item.loaded = true;
  135. hideLoad();
  136. });
  137. sceneModel.bus.on("loadError", () => {
  138. item.error = true;
  139. item.show = false;
  140. custom.showModelsMap.delete(item);
  141. hideLoad();
  142. });
  143. sceneModel.bus.on("loadProgress", (progress) => (item.progress = progress));
  144. }
  145. for (const item of deleted) {
  146. console.error("销毁", item);
  147. getSceneModel(item)?.destroy();
  148. sceneModelMap.delete(item);
  149. }
  150. };
  151. export const activeModel = (status: {
  152. showMode: "fuse" | "pano";
  153. active?: FuseModel;
  154. fore?: boolean
  155. }) => {
  156. const oldStatus = {
  157. showMode: custom.showMode,
  158. active: custom.currentModel,
  159. };
  160. if (
  161. toRaw(status.active) === toRaw(oldStatus.active) &&
  162. status.showMode === oldStatus.showMode
  163. ) {
  164. return;
  165. }
  166. const model = status.active && getSceneModel(status.active)!;
  167. const oldModel = oldStatus.active && getSceneModel(oldStatus.active)!;
  168. if (oldModel) {
  169. oldModel.changeSelect(false);
  170. }
  171. if (model && status.active === oldStatus.active) {
  172. if (status.showMode === "pano") {
  173. if (model) {
  174. console.error('--->', model)
  175. model.changeSelect(false)
  176. model.flyInPano();
  177. }
  178. } else {
  179. if (model) {
  180. model.flyOutPano();
  181. custom.currentModel === status.active && model.changeSelect(true)
  182. }
  183. }
  184. } else {
  185. if (oldStatus.showMode !== status.showMode) {
  186. if (oldStatus.showMode === "pano") {
  187. if (oldModel) {
  188. console.error('---> a', oldModel)
  189. oldModel.flyOutPano();
  190. custom.currentModel === oldStatus.active && oldModel.changeSelect(true)
  191. }
  192. }
  193. }
  194. if (status.showMode === "pano") {
  195. if (model) {
  196. console.error('---> b', oldModel)
  197. model.changeSelect(false)
  198. model.flyInPano();
  199. }
  200. } else {
  201. console.log("select");
  202. }
  203. }
  204. setTimeout(() => {
  205. if (status.showMode !== "pano" && model) {
  206. if (oldStatus.showMode !== 'pano' || status.fore) {
  207. model && model.changeSelect(true);
  208. }
  209. }
  210. }, 35);
  211. custom.currentModel = status.active!;
  212. custom.showMode = status.showMode;
  213. };
  214. export const associationModels = (sdk: SDK) => {
  215. sdk.sceneBus.on("modeChange", (data) => {
  216. if (data.active || data.model) {
  217. activeModel({ active: getFuseModel(data.active || data.model)!, showMode: data.mode })
  218. }
  219. custom.showMode = data.mode;
  220. console.error('modeChange', data, (data.active || data.model))
  221. if ((data.active || data.model) && data.mode === 'pano') {
  222. (data.active || data.model).changeSelect(false)
  223. }
  224. });
  225. sdk.sceneBus.on("panoModelChange", (data) => {
  226. custom.showMode = "pano";
  227. custom.currentModel = getFuseModel(data)!;
  228. data.changeSelect(false)
  229. // activeModel({ active: getFuseModel(data)!, showMode: 'pano' })
  230. });
  231. const getModels = () =>
  232. fuseModels.value.filter(
  233. (model) => getSceneModel(model) || getFuseModelShowVariable(model).value
  234. );
  235. shallowWatchArray(getModels, (models, oldModels) => {
  236. setModels(sdk, models, oldModels);
  237. });
  238. arrayChildEffectScope(getModels, (item) => {
  239. const stopLoadedWatch = watch(
  240. () => item.loaded,
  241. (loaded) => {
  242. if (loaded) {
  243. const modelShow = getFuseModelShowVariable(item);
  244. watch(
  245. () => item.bottom,
  246. () => us.isUnSet || getSceneModel(item)?.changeBottom(item.bottom)
  247. // { immediate: true }
  248. );
  249. watch(
  250. () => item.opacity,
  251. () => us.isUnSet || getSceneModel(item)?.changeOpacity(item.opacity)
  252. // { immediate: true }
  253. );
  254. watch(
  255. () => item.scale,
  256. () => {
  257. us.isUnSet || getSceneModel(item)?.changeScale(item.scale)
  258. }
  259. // { immediate: true }
  260. );
  261. watch(
  262. () => item.position,
  263. () => {
  264. if (!us.isUnSet) {
  265. console.log('position', item.raw.modelTitle, toRaw(item.position))
  266. getSceneModel(item)?.changePosition(item.position);
  267. }
  268. }
  269. // { immediate: true }
  270. );
  271. watch(
  272. () => item.rotation,
  273. () => {
  274. if (!us.isUnSet) {
  275. console.log('rotation', item.raw.modelTitle, toRaw(item.rotation))
  276. getSceneModel(item)?.changeRotation(toRaw(item.rotation));
  277. }
  278. }
  279. // { immediate: true }
  280. );
  281. watch(
  282. () => modelShow.value,
  283. () => {
  284. const sceneModel = getSceneModel(item);
  285. if (!us.isUnSet && sceneModel) {
  286. sceneModel.changeSelect(false);
  287. sceneModel.changeShow(modelShow.value);
  288. }
  289. },
  290. { immediate: true }
  291. );
  292. stopLoadedWatch();
  293. }
  294. }
  295. // { immediate: true }
  296. );
  297. });
  298. };
  299. export const getSupportPano = (model: FuseModel) => {
  300. const supportPano = ref(false);
  301. const show = getFuseModelShowVariable(model);
  302. watchEffect(() => {
  303. if (!show.value) {
  304. supportPano.value = false;
  305. return;
  306. }
  307. const sceneModel = getSceneModel(model);
  308. const support = sceneModel?.supportPano();
  309. supportPano.value = !!support;
  310. sceneModel?.bus.on("loadDone", () => {
  311. supportPano.value = sceneModel?.supportPano();
  312. });
  313. });
  314. return supportPano
  315. }