feat(tool): eclipse
This commit is contained in:
@@ -267,6 +267,7 @@ const LabelPage = ({
|
||||
setShowMultiFrame,
|
||||
isView,
|
||||
setIsView,
|
||||
renderMode,
|
||||
scale,
|
||||
setScale,
|
||||
objectOperations,
|
||||
@@ -1307,8 +1308,8 @@ const LabelPage = ({
|
||||
)
|
||||
|
||||
const setDrawType = useCallback(() => {
|
||||
if (isView) {
|
||||
setPaperMode("pan")
|
||||
if (isView || renderMode) {
|
||||
setPaperMode(null)
|
||||
} else {
|
||||
let operationSchema = getOperationSchema(activeOperation)
|
||||
if (operationSchema) {
|
||||
@@ -1371,6 +1372,7 @@ const LabelPage = ({
|
||||
editMode,
|
||||
getOperationSchema,
|
||||
isView,
|
||||
renderMode,
|
||||
setPaperMode,
|
||||
setToolOption,
|
||||
])
|
||||
@@ -2117,7 +2119,7 @@ const LabelPage = ({
|
||||
return
|
||||
}
|
||||
|
||||
if (isView) return
|
||||
if (isView || renderMode) return
|
||||
|
||||
if (!e.ctrlKey && !e.metaKey && !e.altKey && lowerKey === "h") {
|
||||
e.preventDefault()
|
||||
@@ -2426,6 +2428,7 @@ const LabelPage = ({
|
||||
handleContinueSelectedPolygon,
|
||||
handleShortcut,
|
||||
isView,
|
||||
renderMode,
|
||||
projectDetail?.label_type,
|
||||
setEditMode,
|
||||
setGroupScale,
|
||||
|
||||
@@ -51,6 +51,7 @@ import { useBottomToolsStore } from "../useBottomToolsStore"
|
||||
import { useKeyboardStore } from "../useKeyBoardStore"
|
||||
import { useOtherToolsStore } from "../useOtherToolsStore"
|
||||
import { clearSupportAnnotationItem, usePaperStore } from "../usePaperStore"
|
||||
import { usePaperSupportStore } from "../usePaperSupportStore"
|
||||
import { renderGroupPath } from "../useRenderGroupPath"
|
||||
import useRenderTag from "../useRenderTag"
|
||||
import { useRightToolsStore } from "../useRightToolsStore"
|
||||
@@ -443,6 +444,7 @@ const PaperContainer = (
|
||||
crosshairStatus,
|
||||
assistToolEnabled,
|
||||
assistToolSize,
|
||||
renderMode,
|
||||
showTags,
|
||||
showTagsConfigs,
|
||||
} = useTopToolsStore()
|
||||
@@ -452,6 +454,8 @@ const PaperContainer = (
|
||||
selectedPath,
|
||||
updateSelectedPath,
|
||||
} = useObjectStore()
|
||||
const currentSelectedPath = selectedPath[activeImage] || []
|
||||
const currentSelectedPathKey = currentSelectedPath.join(",")
|
||||
|
||||
const {
|
||||
showContextMenu,
|
||||
@@ -511,6 +515,11 @@ const PaperContainer = (
|
||||
token: number
|
||||
imageName: string
|
||||
} | null>(null)
|
||||
const renderModePanRef = useRef({
|
||||
active: false,
|
||||
lastX: 0,
|
||||
lastY: 0,
|
||||
})
|
||||
|
||||
const paperScope = useRef<paper.PaperScope>(null)
|
||||
useEffect(() => {
|
||||
@@ -1812,6 +1821,52 @@ const PaperContainer = (
|
||||
]
|
||||
)
|
||||
|
||||
const syncRenderModeVisuals = useCallback(
|
||||
(targetGroup?: paper.Group | null) => {
|
||||
const group = targetGroup ?? usePaperStore.getState().group
|
||||
if (!group) return
|
||||
|
||||
group.children.forEach((item) => {
|
||||
const itemData = item.data || {}
|
||||
const itemType = itemData.type
|
||||
|
||||
if (
|
||||
itemData.name === "pic" ||
|
||||
itemData.id === "support" ||
|
||||
!itemData.fillColor ||
|
||||
!itemData.blankColor ||
|
||||
[
|
||||
"mask",
|
||||
"text",
|
||||
"tag",
|
||||
"groupPath",
|
||||
"pathCircle",
|
||||
"pathBuff",
|
||||
"circle",
|
||||
].includes(itemType)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const nextFillState = renderMode || itemData.selected ? "fill" : "blank"
|
||||
if (itemData.renderModeFillState === nextFillState) {
|
||||
return
|
||||
}
|
||||
itemData.renderModeFillState = nextFillState
|
||||
|
||||
const nextFillColor =
|
||||
renderMode || itemData.selected
|
||||
? itemData.fillColor
|
||||
: itemData.blankColor
|
||||
const pathItem = item as paper.PathItem
|
||||
pathItem.fillColor = nextFillColor
|
||||
? new paper.Color(nextFillColor)
|
||||
: null
|
||||
})
|
||||
},
|
||||
[renderMode]
|
||||
)
|
||||
|
||||
// 生成辅助标注结果数据并绘制
|
||||
const saveSupportAnnotationData = useCallback(() => {
|
||||
const group = usePaperStore.getState().group
|
||||
@@ -2163,6 +2218,7 @@ const PaperContainer = (
|
||||
if (useBottomToolsStore.getState().activeImage !== expectedImage) return
|
||||
renderGroupPath()
|
||||
renderTag()
|
||||
syncRenderModeVisuals()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2194,6 +2250,7 @@ const PaperContainer = (
|
||||
if (useBottomToolsStore.getState().activeImage !== expectedImage) return
|
||||
renderGroupPath()
|
||||
renderTag()
|
||||
syncRenderModeVisuals()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2238,6 +2295,7 @@ const PaperContainer = (
|
||||
if (useBottomToolsStore.getState().activeImage !== expectedImage) return
|
||||
renderGroupPath()
|
||||
renderTag()
|
||||
syncRenderModeVisuals()
|
||||
}
|
||||
|
||||
if (typeof globalThis.requestAnimationFrame === "function") {
|
||||
@@ -2246,7 +2304,13 @@ const PaperContainer = (
|
||||
setTimeout(runBatch, 0)
|
||||
}
|
||||
},
|
||||
[clearRenderedAnnotationItems, objectOperations, renderPolygons, renderTag]
|
||||
[
|
||||
clearRenderedAnnotationItems,
|
||||
objectOperations,
|
||||
renderPolygons,
|
||||
renderTag,
|
||||
syncRenderModeVisuals,
|
||||
]
|
||||
)
|
||||
|
||||
const withPaperGroup = useCallback(
|
||||
@@ -2365,6 +2429,7 @@ const PaperContainer = (
|
||||
})
|
||||
|
||||
if (!tasks.length) {
|
||||
syncRenderModeVisuals(targetGroup)
|
||||
resolve(true)
|
||||
return
|
||||
}
|
||||
@@ -2403,6 +2468,7 @@ const PaperContainer = (
|
||||
return
|
||||
}
|
||||
|
||||
syncRenderModeVisuals(targetGroup)
|
||||
resolve(true)
|
||||
}
|
||||
|
||||
@@ -2416,10 +2482,107 @@ const PaperContainer = (
|
||||
isPendingFrameSwitchStale,
|
||||
objectOperations,
|
||||
renderPolygons,
|
||||
syncRenderModeVisuals,
|
||||
withPaperGroup,
|
||||
]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!setup || loadingData) return
|
||||
|
||||
const group = usePaperStore.getState().group
|
||||
if (!group) return
|
||||
|
||||
syncRenderModeVisuals(group)
|
||||
|
||||
if (renderMode) {
|
||||
usePaperSupportStore.getState().clearAll()
|
||||
useOtherToolsStore.getState().setShowContextMenu({
|
||||
showContextMenu: false,
|
||||
position: { top: 0, left: 0 },
|
||||
imageId: "",
|
||||
operationId: "",
|
||||
id: 0,
|
||||
})
|
||||
}
|
||||
}, [
|
||||
activeImage,
|
||||
activeImageLabel,
|
||||
currentSelectedPathKey,
|
||||
loadingData,
|
||||
renderMode,
|
||||
setup,
|
||||
syncRenderModeVisuals,
|
||||
])
|
||||
|
||||
const stopRenderModePan = useCallback(() => {
|
||||
renderModePanRef.current.active = false
|
||||
}, [])
|
||||
|
||||
const handleRenderModeOverlayMouseDown = useCallback(
|
||||
(event: React.MouseEvent<HTMLDivElement>) => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
useOtherToolsStore.getState().setShowContextMenu({
|
||||
showContextMenu: false,
|
||||
position: { top: 0, left: 0 },
|
||||
imageId: "",
|
||||
operationId: "",
|
||||
id: 0,
|
||||
})
|
||||
|
||||
if (event.button !== 1) return
|
||||
|
||||
renderModePanRef.current = {
|
||||
active: true,
|
||||
lastX: event.clientX,
|
||||
lastY: event.clientY,
|
||||
}
|
||||
},
|
||||
[]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!renderMode) {
|
||||
stopRenderModePan()
|
||||
return
|
||||
}
|
||||
|
||||
const handleMouseMove = (event: MouseEvent) => {
|
||||
const currentPan = renderModePanRef.current
|
||||
if (!currentPan.active) return
|
||||
|
||||
event.preventDefault()
|
||||
const group = usePaperStore.getState().group
|
||||
if (!group) return
|
||||
|
||||
const deltaX = event.clientX - currentPan.lastX
|
||||
const deltaY = event.clientY - currentPan.lastY
|
||||
if (!deltaX && !deltaY) return
|
||||
|
||||
group.position = group.position.add(new paper.Point(deltaX, deltaY))
|
||||
renderModePanRef.current.lastX = event.clientX
|
||||
renderModePanRef.current.lastY = event.clientY
|
||||
}
|
||||
|
||||
const handleMouseUp = (event: MouseEvent) => {
|
||||
if (event.button === 1) {
|
||||
event.preventDefault()
|
||||
}
|
||||
stopRenderModePan()
|
||||
}
|
||||
|
||||
window.addEventListener("mousemove", handleMouseMove, { passive: false })
|
||||
window.addEventListener("mouseup", handleMouseUp, { passive: false })
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("mousemove", handleMouseMove)
|
||||
window.removeEventListener("mouseup", handleMouseUp)
|
||||
stopRenderModePan()
|
||||
}
|
||||
}, [renderMode, stopRenderModePan])
|
||||
|
||||
const preparePendingFrameSwitch = useCallback(
|
||||
async (imageName: string, token: number) => {
|
||||
if (
|
||||
@@ -4024,6 +4187,22 @@ const PaperContainer = (
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{renderMode && (
|
||||
<Box
|
||||
aria-hidden
|
||||
onContextMenu={(event) => {
|
||||
event.preventDefault()
|
||||
}}
|
||||
onMouseDown={handleRenderModeOverlayMouseDown}
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 0,
|
||||
zIndex: 47,
|
||||
background: "rgba(128, 128, 128, 0.24)",
|
||||
pointerEvents: "auto",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{contextMenu}
|
||||
<Modal
|
||||
opened={confirmModalOpened}
|
||||
|
||||
@@ -180,6 +180,8 @@ const TopTools = (
|
||||
const {
|
||||
isView,
|
||||
setIsView,
|
||||
renderMode,
|
||||
setRenderMode,
|
||||
saveCurrentScale,
|
||||
setSaveCurrentScale,
|
||||
showMultiFrame,
|
||||
@@ -1896,10 +1898,16 @@ const TopTools = (
|
||||
<SquarePen style={{ width: 20, height: 20 }} />
|
||||
</ActionIcon>
|
||||
)}
|
||||
<Eclipse
|
||||
style={{ width: 20, height: 20, display: "none" }}
|
||||
color="gray"
|
||||
/>
|
||||
<Tooltip label={renderMode ? "关闭渲染" : "开启渲染"}>
|
||||
<ActionIcon
|
||||
variant="transparent"
|
||||
c={renderMode ? "var(--mantine-color-text)" : "gray"}
|
||||
onClick={() => {
|
||||
setRenderMode(!renderMode)
|
||||
}}>
|
||||
<Eclipse style={{ width: 20, height: 20 }} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
<CopySlash style={{ width: 20, height: 20, display: "none" }} />
|
||||
</Flex>
|
||||
<Flex
|
||||
|
||||
@@ -5600,6 +5600,9 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
break
|
||||
default:
|
||||
usePaperStore.getState().viewTool?.activate()
|
||||
if (usePaperStore.getState().el) {
|
||||
usePaperStore.getState().el!.style.cursor = "default"
|
||||
}
|
||||
break
|
||||
}
|
||||
},
|
||||
|
||||
@@ -10,6 +10,8 @@ interface TopToolsState {
|
||||
// 标注页面是否仅查看
|
||||
isView: boolean
|
||||
setIsView: (val: boolean) => void
|
||||
renderMode: boolean
|
||||
setRenderMode: (val: boolean) => void
|
||||
// 绘制模式
|
||||
editMode: boolean
|
||||
setEditMode: (val: boolean) => void
|
||||
@@ -81,6 +83,7 @@ interface TopToolsState {
|
||||
|
||||
const initialTopToolsState = {
|
||||
isView: false,
|
||||
renderMode: false,
|
||||
editMode: false,
|
||||
pressA: false,
|
||||
imageFilter: {
|
||||
@@ -114,6 +117,12 @@ export const useTopToolsStore = create<TopToolsState>()(
|
||||
...state,
|
||||
isView: val,
|
||||
})),
|
||||
renderMode: initialTopToolsState.renderMode,
|
||||
setRenderMode: (val: boolean) =>
|
||||
set((state: TopToolsState) => ({
|
||||
...state,
|
||||
renderMode: val,
|
||||
})),
|
||||
editMode: initialTopToolsState.editMode,
|
||||
setEditMode: (val: boolean) =>
|
||||
set((state: TopToolsState) => ({
|
||||
|
||||
Reference in New Issue
Block a user