bill 4 mesi fa
parent
commit
6202794422

+ 13 - 9
src/components/actions-merge/index.vue

@@ -41,17 +41,9 @@ const clickHandler = (select: ActionsItem) => {
 };
 
 watch(
-  () => props.current,
-  () => {
-    if (!props.current && selected.value) {
-      clickHandler(selected.value);
-    }
-  }
-);
-
-watch(
   selected,
   (_n, _o, onCleanup) => {
+    console.error("click", selected.value?.action);
     if (selected.value?.action) {
       const cleanup = selected.value.action();
       cleanup && onCleanup(cleanup);
@@ -59,6 +51,18 @@ watch(
   },
   { flush: "sync" }
 );
+watch(
+  () => props.current,
+  () => {
+    if (!props.current && selected.value) {
+      clickHandler(selected.value);
+    }
+  }
+);
+
+if (props.current) {
+  clickHandler(props.current);
+}
 
 onBeforeUnmount(() => {
   selected.value = null;

+ 2 - 0
src/env/index.ts

@@ -10,6 +10,7 @@ export const showRightPanoStack = stackFactory(ref<boolean>(true));
 export const showLeftPanoStack = stackFactory(ref<boolean>(false));
 export const moundLeftPanoStack = stackFactory(ref<boolean>(true));
 export const showLeftCtrlPanoStack = stackFactory(ref<boolean>(true));
+export const showAMsStack = stackFactory(ref<boolean>(false));
 export const showModeStack = stackFactory(ref<"pano" | "fuse">("fuse"));
 export const showRightCtrlPanoStack = stackFactory(ref<boolean>(true));
 export const showBottomBarStack = stackFactory(ref<boolean>(false), true);
@@ -55,6 +56,7 @@ export const custom = flatStacksValue({
   showBottomBar: showBottomBarStack,
   bottomBarHeight: bottomBarHeightStack,
   showHeadBar: showHeadBarStack,
+  showAMs: showAMsStack,
   currentView: currentViewStack,
   showMode: showModeStack,
   showSearch: showSearchStack,

+ 7 - 2
src/layout/edit/scene-select.vue

@@ -80,7 +80,7 @@ import {
 } from "ant-design-vue";
 import { computed, nextTick, ref, watch, watchEffect } from "vue";
 import { scenes, save, SceneTypeDesc } from "@/store";
-import { asyncTimeout, createLoadPack } from "@/utils";
+import { asyncTimeout, createLoadPack, diffArrayChange } from "@/utils";
 import {
   fuseModels,
   createFuseModels,
@@ -92,6 +92,8 @@ import {
 import { SceneType, uploadMaterialToModel, type Scene } from "@/api";
 import { getSceneModel } from "@/sdk";
 import { selectMaterials } from "@/components/materials/quisk";
+import { custom } from "@/env";
+import { actionItems, currentItem } from "@/views/merge";
 
 type Key = Scene["modelId"];
 
@@ -173,7 +175,7 @@ const addModelHandler = createLoadPack(async (modelIds: number[]) => {
   const models = modelIds.map((modelId) => createFuseModels({ modelId }));
   const addPromises = models.map(addFuseModel);
 
-  await Promise.all(addPromises);
+  const addModels = await Promise.all(addPromises);
   await new Promise<void>((resolve) => {
     nextTick(() => {
       const stop = watchEffect(() => {
@@ -193,6 +195,9 @@ const addModelHandler = createLoadPack(async (modelIds: number[]) => {
   });
   await asyncTimeout(100);
   await save();
+
+  custom.currentModel = addModels[addModels.length - 1]
+  currentItem.value = actionItems[0]
 });
 
 const okHandler = createLoadPack(async () => {

+ 59 - 26
src/sdk/association/animation.ts

@@ -14,7 +14,15 @@ import sdk, {
   SDK,
   sdk as _sdk,
 } from "../sdk";
-import { computed, nextTick, reactive, ref, toRaw, watch, watchEffect } from "vue";
+import {
+  computed,
+  nextTick,
+  reactive,
+  ref,
+  toRaw,
+  watch,
+  watchEffect,
+} from "vue";
 import { ams } from "@/store/animation";
 import { mergeFuns, uuid } from "@/components/drawing/hook";
 import { getPathNode } from "./path";
@@ -25,6 +33,7 @@ import { Size } from "@/components/drawing/dec";
 import router, { RoutesName } from "@/router";
 import { paths } from "@/store";
 import { Color } from "three";
+import { custom, showAMsStack } from "@/env";
 
 export let animationGroup: AnimationGroup;
 export const getAMKey = (am: AnimationModel) => am.key || am.id;
@@ -56,7 +65,7 @@ export const addAM = (data: AnimationModel): Promise<AnimationModel3D> => {
         Object.values(des.actions || {}).forEach((frame) => frame.destroy());
         Object.values(des.paths || {}).forEach((frame) => frame.destroy());
         des.am?.destroy();
-        console.error('destory', key, data)
+        console.error("destory", key, data);
         delete amMap[key];
       } else if (!amMap[key]) {
         amMap[key] = {
@@ -68,7 +77,7 @@ export const addAM = (data: AnimationModel): Promise<AnimationModel3D> => {
         const am = animationGroup.addAnimationModel(data);
         am.bus.on("loadDone", () => {
           amMap[key].am = am;
-          console.log('0.0', am)
+          console.log("0.0", am);
         });
       }
     },
@@ -268,11 +277,14 @@ export const addPath = (
     watchEffect(() =>
       amMap[key]?.paths[data.id]?.changeDuration(data.duration)
     ),
-    watch(path, (p) => {
-      const path = toRaw(p)
-      path && amMap[key]?.paths[data.id]?.changePath(path);
-
-    }, {immediate: true})
+    watch(
+      path,
+      (p) => {
+        const path = toRaw(p);
+        path && amMap[key]?.paths[data.id]?.changePath(path);
+      },
+      { immediate: true }
+    )
   );
 
   const stopWatch = watch(
@@ -331,11 +343,14 @@ export const addSubtitle = (data: AnimationModelSubtitle) => {
           }),
           watchEffect(() => {
             const theme = new Color();
-            theme.setHex(parseInt(data.background.substring(1), 16))
-            const rgb = {r: 0, g: 0, b: 0}
-            theme.getRGB(rgb)
-
-            layer.style.backgroundColor = `rgba(${round(rgb.r * 255, 2)},${round(rgb.g* 255, 2)},${round(rgb.b* 255, 2)},0.5)`
+            theme.setHex(parseInt(data.background.substring(1), 16));
+            const rgb = { r: 0, g: 0, b: 0 };
+            theme.getRGB(rgb);
+
+            layer.style.backgroundColor = `rgba(${round(
+              rgb.r * 255,
+              2
+            )},${round(rgb.g * 255, 2)},${round(rgb.b * 255, 2)},0.5)`;
           }),
           watchEffect(() => {
             layer.style.visibility =
@@ -369,7 +384,13 @@ export const addSubtitle = (data: AnimationModelSubtitle) => {
 
   const stopAttrib = mergeFuns(
     watch(
-      [currentTime, () => amMap[getAMKey(am)]?.am, size, play, () => amMap[key]?.am],
+      [
+        currentTime,
+        () => amMap[getAMKey(am)]?.am,
+        size,
+        play,
+        () => amMap[key]?.am,
+      ],
       (_a, _b, onCleanup) => {
         if (
           !play.value &&
@@ -426,7 +447,7 @@ export const endTime = computed(() => {
     ].map((item) => item.time + (item.duration || 0));
     return Math.max(...endPoints);
   });
-  console.log('amsEndTime', amsEndTime, ams.value)
+  console.log("amsEndTime", amsEndTime, ams.value);
   return (
     Math.max(...amsEndTime) +
     ((animationGroup.delayEndTime && animationGroup.delayEndTime()) || 0)
@@ -438,7 +459,7 @@ watch(play, (_a, _b, onCleanup) => {
   play.value ? animationGroup?.play() : animationGroup?.pause();
   if (!play.value) return;
   if (currentTime.value >= endTime.value) {
-    currentTime.value = 0
+    currentTime.value = 0;
   }
   onCleanup(
     watchEffect(() => {
@@ -509,10 +530,8 @@ export const associationAnimation = (sdk: SDK, el: HTMLDivElement) => {
   let cleanupMap: Record<string, () => void> = {};
   watch(
     () => {
-      // !am.frames.length && 
-      const gAms = ams.value.filter(
-        (am) => amMap[getAMKey(am)]?.am
-      );
+      // !am.frames.length &&
+      const gAms = ams.value.filter((am) => amMap[getAMKey(am)]?.am);
       return gAms;
     },
     (am3ds, oldAm3ds = []) => {
@@ -527,15 +546,15 @@ export const associationAnimation = (sdk: SDK, el: HTMLDivElement) => {
         //   time: 0,
         // });
         // am3d.globalFrame = frame;
-        const mat = am.mat || am3d.am.getModelPose()
-        am3d.am.changePosition(mat.position!)
-        am3d.am.changeRotation(mat.rotation!)
-        am3d.am.changeScale(mat.scale!)
+        const mat = am.mat || am3d.am.getModelPose();
+        am3d.am.changePosition(mat.position!);
+        am3d.am.changeRotation(mat.rotation!);
+        am3d.am.changeScale(mat.scale!);
 
         cleanupMap[getAMKey(am)] = mergeFuns(
           watchEffect(() => {
             // am.mat && frame.setMat(am.mat);
-            if  (am.mat && am3d.am) {
+            if (am.mat && am3d.am) {
               // console.log(am.mat)
               // am3d.am.changePosition(mat.position!)
               // am3d.am.changeRotation(mat.rotation!)
@@ -545,7 +564,7 @@ export const associationAnimation = (sdk: SDK, el: HTMLDivElement) => {
           }),
           () => {
             // frame.destroy();
-            am3d.am?.addFrame
+            am3d.am?.addFrame;
             am3d.globalFrame = undefined;
             delete cleanupMap[getAMKey(am)];
           }
@@ -557,4 +576,18 @@ export const associationAnimation = (sdk: SDK, el: HTMLDivElement) => {
     },
     { flush: "post", immediate: true }
   );
+
+  watch(
+    () =>
+      [Object.values(amMap).map((item) => item.am), custom.showAMs] as const,
+    ([ams, show]) => {
+      console.error(ams, 'show', show)
+      ams.forEach((am) => {
+        am?.changeShow(show);
+      });
+    }
+  );
 };
+
+
+showAMsStack.push(play)

+ 1 - 0
src/store/fuse-model.ts

@@ -168,6 +168,7 @@ export const addFuseModel = async (model: FuseModel) => {
     dynamicAddedModelIds.value.push(addModel.id);
   });
   backupFuseModels()
+  return addModel
 };
 
 export const initialFuseModels = fetchStoreItems(

+ 22 - 22
src/views/animation/index.vue

@@ -58,6 +58,7 @@ import { title } from "./type";
 import { amMap, getAMKey, currentTime, play } from "@/sdk/association/animation";
 import { sdk, AnimationModel3D } from "@/sdk";
 import {
+  showAMsStack,
   showBottomBarStack,
   showHeadBarStack,
   showLeftCtrlPanoStack,
@@ -80,6 +81,7 @@ useViewStack(() => {
     showBottomBarStack.push(ref(true)),
     showRightPanoStack.push(showRight),
     showLeftPanoStack.push(ref(true)),
+    showAMsStack.push(ref(true)),
     showHeadBarStack.push(computed(() => !play.value)),
     showLeftCtrlPanoStack.push(computed(() => !play.value)),
     showModeTabStack.push(computed(() => !play.value)),
@@ -178,24 +180,24 @@ const updateFocus = (am?: AnimationModel) => {
   focusAM.value = am;
   am && asyncOper(am, (item) => item.changeSelect(true));
 };
+watch(
+  () => [ams.value, ams.value.map((am) => amMap[getAMKey(am)]?.am)] as const,
+  ([ams, am3ds], _, onCleanup) => {
+    const cleanups = am3ds.map((am3d, ndx) => {
+      const am = ams[ndx];
+      const update = (f: boolean) => {
+        focusAM.value = f ? am : undefined;
+      };
+      am3d?.bus.on("changeSelect", update);
 
-watchEffect((onCleanup) => {
-  onCleanup(
-    mergeFuns(
-      ams.value.map((item) => {
-        return asyncOper(item, (s) =>
-          s.bus.on("changeSelect", (f) => {
-            if (f) {
-              focusAM.value = item;
-            } else if (focusAM.value === item) {
-              focusAM.value = undefined;
-            }
-          })
-        );
-      })
-    )
-  );
-});
+      return () => {
+        am3d?.bus.off("changeSelect", update);
+      };
+    });
+    onCleanup(mergeFuns(cleanups));
+  },
+  { immediate: true }
+);
 
 watch(activeAttrib, (_a, _b, onCleanup) => {
   if (!activeAttrib.value) return;
@@ -232,7 +234,7 @@ const add = <T extends Active["key"]>(
     1
   );
   if (!attr) {
-    Message.error("当前时间已存在其他" + title[key]);
+    Message.error("同一时间内请勿重复添加");
   } else {
     const item = reactive({
       id: uuid(),
@@ -262,16 +264,14 @@ const changeSelect = ({ select, unSelect }: Record<string, AnimationModel[]>) =>
     ...unSelect.map((item) =>
       asyncOper(item, (am) => {
         if (item === focusAM.value) {
-          focusAM.value = undefined;
+          updateFocus(undefined);
         }
         am.changeShow(false);
       })
     )
   );
 };
-onUnmounted(() => {
-  changeSelect({ select: ams.value, unSelect: [] });
-});
+
 const deleteAm = (am: AnimationModel) => {
   if (am === focusAM.value) {
     activeAttrib.value = undefined;

+ 1 - 1
src/views/animation/left.vue

@@ -82,7 +82,7 @@ const updateSelectAm = (item: AnimationModel, select: boolean) => {
 // if (import.meta.env.DEV) {
 activeKey.value = "animation";
 const stop = watchEffect(() => {
-  if (amMap[getAMKey(ams.value[0])].am) {
+  if (ams.value.length > 0 && amMap[getAMKey(ams.value[0])].am) {
     setTimeout(() => {
       emit("update:focus", ams.value[0]);
       stop();

+ 1 - 1
src/views/animation/right/index.vue

@@ -73,7 +73,7 @@ const setDuration = (dur: number) => {
   const cur = items[ndx];
 
   if (!checkTLItem(items, { ...cur, duration: dur }, ndx)) {
-    Message.error("当前时间已存在其他" + title[props.activeAttrib!.key]);
+    Message.error("同一时间内请勿重复添加");
   } else {
     cur.duration = dur;
   }

+ 2 - 0
src/views/guide/guide/edit-paths.vue

@@ -145,6 +145,7 @@ import {
 
 import type { Guide, GuidePaths, GuidePath } from "@/store";
 import type { CalcPathProps } from "@/sdk";
+import { showAMsStack } from "../../../env";
 
 const props = defineProps<{ data: Guide }>();
 const paths = ref<GuidePaths>(getGuidePaths(props.data));
@@ -169,6 +170,7 @@ useViewStack(() => {
     showLeftCtrlPanoStack.push(ref(false)),
     showLeftPanoStack.push(ref(false)),
     showRightCtrlPanoStack.push(ref(false)),
+    showAMsStack.push(ref(true)),
     togetherCallback(
       keys.map((key) =>
         mapping[key].push(

+ 2 - 0
src/views/guide/path/edit-path.vue

@@ -158,6 +158,7 @@
 
 <script setup lang="ts">
 import {
+  showAMsStack,
   showLeftCtrlPanoStack,
   showLeftPanoStack,
   showRightCtrlPanoStack,
@@ -274,6 +275,7 @@ watch(
 );
 
 useViewStack(() => {
+
   return togetherCallback([
     showRightPanoStack.push(ref(false)),
     showLeftCtrlPanoStack.push(ref(false)),

+ 38 - 0
src/views/merge/index.ts

@@ -0,0 +1,38 @@
+import { ActionsItem, ActionsProps } from "@/components/actions-merge/index.vue";
+import { custom } from "@/env";
+import { getSceneModel } from "@/sdk";
+import { reactive, ref } from "vue";
+
+export const currentItem = ref<ActionsItem | null>(null);
+
+export const actionItems: ActionsProps["items"] = reactive([
+  {
+    icon: "a-move",
+    text: "移动",
+    action: () => {
+      getSceneModel(custom.currentModel)?.enterMoveMode();
+      console.error('move', getSceneModel(custom.currentModel))
+      return () => getSceneModel(custom.currentModel)?.leaveTransform();
+    },
+  },
+  {
+    icon: "a-rotate",
+    text: "旋转",
+    action: () => {
+      getSceneModel(custom.currentModel)?.enterRotateMode();
+      return () => {
+        getSceneModel(custom.currentModel)?.leaveTransform();
+      };
+    },
+  },
+  {
+    icon: "a-zoom",
+    text: "缩放",
+    action: () => {
+      getSceneModel(custom.currentModel)?.enterScaleMode();
+      return () => {
+        getSceneModel(custom.currentModel)?.leaveTransform();
+      };
+    },
+  },
+]);

+ 7 - 38
src/views/merge/index.vue

@@ -71,38 +71,9 @@ import type { ActionsProps, ActionsItem } from "@/components/actions/index.vue";
 import { listener } from "@/components/drawing/hook";
 import { clickListener, getOffset } from "@/utils/event";
 import { useRMenus } from "@/components/right-menu";
+import { actionItems, currentItem } from ".";
 
 const active = useActive();
-const actionItems: ActionsProps["items"] = [
-  {
-    icon: "a-move",
-    text: "移动",
-    action: () => {
-      getSceneModel(custom.currentModel)?.enterMoveMode();
-      return () => getSceneModel(custom.currentModel)?.leaveTransform();
-    },
-  },
-  {
-    icon: "a-rotate",
-    text: "旋转",
-    action: () => {
-      getSceneModel(custom.currentModel)?.enterRotateMode();
-      return () => {
-        getSceneModel(custom.currentModel)?.leaveTransform();
-      };
-    },
-  },
-  {
-    icon: "a-zoom",
-    text: "缩放",
-    action: () => {
-      getSceneModel(custom.currentModel)?.enterScaleMode();
-      return () => {
-        getSceneModel(custom.currentModel)?.leaveTransform();
-      };
-    },
-  },
-];
 
 const othActions = reactive([
   {
@@ -127,19 +98,18 @@ const othActions = reactive([
   },
 ]);
 
-const currentItem = ref<ActionsItem | null>(null);
 watchEffect(() => {
   if (!custom.currentModel) {
     currentItem.value = null;
   }
 });
 
-watch(
-  () => custom.currentModel,
-  () => {
-    currentItem.value = null;
-  }
-);
+// watch(
+//   () => custom.currentModel,
+//   () => {
+//     currentItem.value = null;
+//   }
+// );
 
 const reset = async () => {
   if (custom.currentModel && (await Dialog.confirm("确定恢复默认?此操作无法撤销"))) {
@@ -187,7 +157,6 @@ useViewStack(() =>
   ])
 );
 useViewStack(autoSaveFuseModels);
-
 useViewStack(() => {
   const stopWatch = watchEffect(() => {
     if (custom.showMode === "pano") {

+ 0 - 4
src/views/registration/index.vue

@@ -147,16 +147,12 @@ watchEffect((onCleanup) => {
     selectOptions.value = [options[0]];
     const selects = [...selectPaths.selects.value];
     selectPaths.all.value = false;
-    ams.value.forEach((item) => amMap[getAMKey(item)]?.am?.changeShow(false));
     onCleanup(
       mergeFuns(
         () => {
           smodel.leaveTransform();
           smodel.leaveAlignment();
         },
-        () => {
-          ams.value.forEach((item) => amMap[getAMKey(item)]?.am?.changeShow(true));
-        },
         currentModelStack.push(model as any),
         // showPathStack.push(ref(undefined)),
         // showPathsStack.push(ref(false)),