Files
labelimage/components/label/utils/objectVisibility.ts
2026-04-17 17:37:27 +08:00

186 lines
5.7 KiB
TypeScript

import paper from "paper"
import { useLabelStore, useObjectStore } from "../store"
import { useOtherToolsStore } from "../useOtherToolsStore"
import { usePaperStore } from "../usePaperStore"
import { usePaperSupportStore } from "../usePaperSupportStore"
import { useTopToolsStore } from "../useTopToolsStore"
const getTagVisibilityByConfig = (tagCategory?: string) => {
const { showTags, showTagsConfigs } = useTopToolsStore.getState()
if (!showTags) return false
if (tagCategory === "mask") return showTagsConfigs.includes("外框")
if (tagCategory === "point_text") return showTagsConfigs.includes("点ID")
return true
}
const resetSelectedItemVisual = (item: paper.Item) => {
if (!(item instanceof paper.Path || item instanceof paper.CompoundPath))
return
if (!["rectangle", "polygon"].includes(item.data?.type || "")) return
item.fillColor = item.data?.blankColor || item.fillColor || null
}
export const getObjectTagVisibility = (
imageId: string,
objectId: number,
tagCategory?: string
) => {
const { pathStatus } = useObjectStore.getState()
if (pathStatus[imageId + objectId]?.HIDE) return false
return getTagVisibilityByConfig(tagCategory)
}
const setSelectedItemFalse = (id: number) => {
if (!id) return
const sameIdItems = usePaperStore.getState().getItemsById(id)
sameIdItems.forEach((item) => {
if (item.data.type === "mask" || item.data.type === "text") {
item.remove()
}
resetSelectedItemVisual(item)
if (item.data.selected) item.data.selected = false
})
}
const clearHiddenObjectSelectionState = (imageId: string, objectId: number) => {
const otherToolsState = useOtherToolsStore.getState()
if (
otherToolsState.showContextMenu &&
otherToolsState.imageId === imageId &&
otherToolsState.id === objectId
) {
otherToolsState.setShowContextMenu({
showContextMenu: false,
position: {
top: 0,
left: 0,
},
imageId: "",
operationId: "",
id: 0,
})
}
}
const syncObjectItemsVisibility = (
imageId: string,
objectId: number,
hide: boolean
) => {
const sameIdItems = usePaperStore.getState().getItemsById(objectId)
if (!sameIdItems?.length) return
sameIdItems.forEach((item) => {
if (hide) {
item.visible = false
return
}
if (item.data?.type === "tag") {
item.visible = getObjectTagVisibility(
imageId,
objectId,
item.data?.tag_category
)
return
}
item.visible = true
})
}
const applySelectedItemVisual = (item: paper.Item) => {
if (!(item instanceof paper.Path || item instanceof paper.CompoundPath))
return
const itemType = item.data?.type
if (!["rectangle", "polygon", "brush", "point"].includes(itemType || ""))
return
if (itemType === "rectangle" && item instanceof paper.Path) {
item.data.selected = true
usePaperSupportStore.getState().handleBufferPaths(item)
usePaperSupportStore.getState().handleCircles(item)
item.fillColor = item.data.fillColor || item.fillColor || null
} else if (itemType === "brush") {
item.data.selected = true
if (item instanceof paper.Path) {
usePaperSupportStore.getState().handleMask(item)
usePaperSupportStore.getState().handleBufferPaths(item)
usePaperSupportStore.getState().handleCircles(item)
}
} else if (itemType === "point" && item instanceof paper.Path) {
item.data.selected = true
usePaperSupportStore.getState().handleMask(item)
usePaperSupportStore.getState().handleText(item)
usePaperSupportStore.getState().handleBufferPaths(item)
usePaperSupportStore.getState().handleCircles(item)
} else if (itemType === "polygon") {
item.data.selected = true
if (!(item instanceof paper.Path) || !item.data?.isHollowPolygon) {
item.fillColor = item.data.fillColor || item.fillColor || null
}
}
item.bringToFront()
}
export const syncSelectedObjectsVisualState = (imageId: string) => {
const group = usePaperStore.getState().group
if (!group) return
group
.getItems({
match: (item: paper.Item) => !!item.data?.selected,
})
.forEach((item) => {
resetSelectedItemVisual(item)
item.data.selected = false
})
usePaperSupportStore.getState().clearAll()
const { selectedPath, pathStatus } = useObjectStore.getState()
;(selectedPath[imageId] || []).forEach((selectedId) => {
if (pathStatus[imageId + selectedId]?.HIDE) return
usePaperStore
.getState()
.getItemsById(selectedId)
.forEach((item) => {
if (item.data?.type === "tag") return
applySelectedItemVisual(item)
})
})
}
export const toggleObjectHideByShortcut = (
imageId: string,
operationId: string,
objectId: number,
hide: boolean
) => {
const { updatePathStatus, updateOperationStatus } = useObjectStore.getState()
const storeLabel = useLabelStore.getState().label
if (hide) {
updatePathStatus(imageId + objectId, "HIDE", hide)
syncObjectItemsVisibility(imageId, objectId, hide)
setSelectedItemFalse(objectId)
clearHiddenObjectSelectionState(imageId, objectId)
syncSelectedObjectsVisualState(imageId)
const operationChildren = storeLabel.get(imageId)?.get(operationId) || []
const hasVisibleChild = operationChildren.some((child) => {
const item = usePaperStore
.getState()
.getItemById(child[0]) as paper.Item | null
return !!item?.visible
})
if (!hasVisibleChild) {
updateOperationStatus(imageId + operationId, "HIDE", hide)
}
return
}
updateOperationStatus(imageId + operationId, "HIDE", hide)
updatePathStatus(imageId + objectId, "HIDE", hide)
syncObjectItemsVisibility(imageId, objectId, hide)
syncSelectedObjectsVisualState(imageId)
}