123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- <template>
- <RightFillPano>
- <h3>{{ tagging?.title }}放置位置</h3>
- <Collapse v-model:activeKey="showId" ghost accordion expandIconPosition="end">
- <template v-for="(position, i) in positions" :key="position.id">
- <PositionSign
- v-show="!(unKeepAdding && position.id !== showId)"
- :position="position"
- :title="`位置${i + 1}`"
- @applyGlobal="(keys) => applyGlobal(position, keys)"
- @delete="deletePosition(position)"
- @show="showId = position.id"
- />
- </template>
- </Collapse>
- <Teleport to="#layout-app">
- <span
- @click="unKeepAdding ? unKeepAdding() : keepAdding()"
- class="pin-position strengthen fun-ctrl"
- >
- <ui-icon
- :style="{ color: unKeepAdding ? 'var(--color-main-normal)' : 'currentColor' }"
- type="pin1"
- size="22px"
- />
- </span>
- </Teleport>
- </RightFillPano>
- </template>
- <script lang="ts" setup>
- import PositionSign from "./sign.vue";
- import { router } from "@/router";
- import { Dialog, Message } from "bill/index";
- import { RightFillPano } from "@/layout";
- import { asyncTimeout, debounce } from "@/utils";
- import { useViewStack } from "@/hook";
- import { flyTaggingPosition as flyTaggingPositionRaw } from "@/hook/use-fly";
- import {
- computed,
- nextTick,
- onUnmounted,
- ref,
- shallowRef,
- watch,
- watchEffect,
- } from "vue";
- import { getTaggingPosNode, sdk, taggingsGroup } from "@/sdk";
- import { custom, showTaggingPositionsStack } from "@/env";
- import {
- autoSaveTaggings,
- getFuseModel,
- getFuseModelShowVariable,
- getTaggingPositions,
- taggingPositions,
- createTaggingPosition,
- getTagging,
- enterEdit,
- } from "@/store";
- import { Collapse } from "ant-design-vue";
- import type { TaggingPosition } from "@/store";
- import { clickListener } from "@/utils/event";
- import { useCameraChange } from "@/hook/use-pixel";
- const showId = ref<TaggingPosition["id"]>();
- const tagging = computed(() => getTagging(router.currentRoute.value.params.id as string));
- const positions = computed(() => tagging.value && getTaggingPositions(tagging.value));
- onUnmounted(() => unKeepAdding.value && unKeepAdding.value());
- useViewStack(autoSaveTaggings);
- useViewStack(() => {
- taggingsGroup.changeCanMove(true);
- taggingsGroup.showDelete(true);
- enterEdit(() => router.back());
- return () => {
- taggingsGroup.changeCanMove(false);
- taggingsGroup.showDelete(false);
- };
- });
- watch(showId, (id) => {
- const position = positions.value?.find((item) => item.id === id);
- if (custom.showMode === "fuse") {
- position && flyTaggingPosition(position);
- }
- });
- const [pose] = useCameraChange(() => sdk.getPose());
- watch(
- [
- showId,
- pose,
- () => {
- const pos = positions.value?.find((item) => item.id === showId.value);
- return [pos?.localPos, pos?.lineHeight];
- },
- ],
- debounce((a) => {
- const position = positions.value?.find((item) => item.id === showId.value);
- if (position) {
- position.pose = sdk.getPose({ modelId: position.modelId, isFlyToTag: true });
- console.log("set Pose", position.pose);
- }
- }, 300)
- );
- let pop: () => void;
- const flyTaggingPosition = (position: TaggingPosition) => {
- pop && pop();
- const model = getFuseModel(position.modelId);
- if (!model || !getFuseModelShowVariable(model).value) {
- return;
- }
- pop = showTaggingPositionsStack.push(ref(new WeakSet([position])));
- flyTaggingPositionRaw(position);
- };
- onUnmounted(() => pop && pop());
- const deletePosition = (position: TaggingPosition) => {
- const index = taggingPositions.value.indexOf(position);
- if (~index) {
- taggingPositions.value.splice(index, 1);
- }
- };
- const applyGlobal = async (position: TaggingPosition, keys: string | string[]) => {
- if (!(await Dialog.confirm("确定要将此属性应用到所有位置?"))) return;
- keys = Array.isArray(keys) ? keys : [keys];
- for (const current of positions.value!) {
- let val: any = current;
- let newVal: any = position;
- for (let i = 0; i < keys.length; i++) {
- if (i === keys.length - 1) {
- val[keys[i]] = newVal[keys[i]];
- } else {
- val = val[keys[i]];
- newVal = newVal[keys[i]];
- }
- }
- }
- };
- let unKeepAdding = shallowRef<() => void>();
- const keepAdding = () => {
- unKeepAdding.value && unKeepAdding.value();
- sdk.startAddSth();
- const hide = Message.show({ msg: "请在模型上单击选择标签位置", type: "warning" });
- showId.value = void 0;
- const removeListener = clickListener(sdk.layout, async (pos) => {
- await nextTick();
- await asyncTimeout();
- const position = sdk.getPositionByScreen(pos);
- if (!position) {
- Message.error("当前位置无法添加");
- } else {
- const storePosition = createTaggingPosition({
- ...position,
- normal: position.localNormal,
- taggingId: tagging.value!.id,
- });
- taggingPositions.value.push(storePosition);
- showId.value = storePosition.id;
- nextTick(() => {
- getTaggingPosNode(storePosition)!.changeCanMove(true);
- });
- }
- });
- unKeepAdding.value = () => {
- hide();
- sdk.endAddSth();
- removeListener();
- unKeepAdding.value = void 0;
- };
- };
- keepAdding();
- </script>
- <style lang="scss" scoped>
- h3 {
- font-family: Microsoft YaHei, Microsoft YaHei;
- font-weight: bold;
- font-size: 16px;
- color: #999999;
- margin-bottom: 4px;
- }
- .pin-position {
- position: absolute;
- left: 50%;
- transform: translate(-50%);
- width: 64px;
- height: 64px;
- background: rgba(27, 27, 28, 0.8);
- border-radius: 50%;
- bottom: 20px;
- z-index: 9;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- </style>
- <style lang="scss">
- .position-group .group-title {
- margin-bottom: 0;
- }
- </style>
|