feat(tool): eclipse
This commit is contained in:
@@ -267,6 +267,7 @@ const LabelPage = ({
|
|||||||
setShowMultiFrame,
|
setShowMultiFrame,
|
||||||
isView,
|
isView,
|
||||||
setIsView,
|
setIsView,
|
||||||
|
renderMode,
|
||||||
scale,
|
scale,
|
||||||
setScale,
|
setScale,
|
||||||
objectOperations,
|
objectOperations,
|
||||||
@@ -1307,8 +1308,8 @@ const LabelPage = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const setDrawType = useCallback(() => {
|
const setDrawType = useCallback(() => {
|
||||||
if (isView) {
|
if (isView || renderMode) {
|
||||||
setPaperMode("pan")
|
setPaperMode(null)
|
||||||
} else {
|
} else {
|
||||||
let operationSchema = getOperationSchema(activeOperation)
|
let operationSchema = getOperationSchema(activeOperation)
|
||||||
if (operationSchema) {
|
if (operationSchema) {
|
||||||
@@ -1371,6 +1372,7 @@ const LabelPage = ({
|
|||||||
editMode,
|
editMode,
|
||||||
getOperationSchema,
|
getOperationSchema,
|
||||||
isView,
|
isView,
|
||||||
|
renderMode,
|
||||||
setPaperMode,
|
setPaperMode,
|
||||||
setToolOption,
|
setToolOption,
|
||||||
])
|
])
|
||||||
@@ -2117,7 +2119,7 @@ const LabelPage = ({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isView) return
|
if (isView || renderMode) return
|
||||||
|
|
||||||
if (!e.ctrlKey && !e.metaKey && !e.altKey && lowerKey === "h") {
|
if (!e.ctrlKey && !e.metaKey && !e.altKey && lowerKey === "h") {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@@ -2426,6 +2428,7 @@ const LabelPage = ({
|
|||||||
handleContinueSelectedPolygon,
|
handleContinueSelectedPolygon,
|
||||||
handleShortcut,
|
handleShortcut,
|
||||||
isView,
|
isView,
|
||||||
|
renderMode,
|
||||||
projectDetail?.label_type,
|
projectDetail?.label_type,
|
||||||
setEditMode,
|
setEditMode,
|
||||||
setGroupScale,
|
setGroupScale,
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import { useBottomToolsStore } from "../useBottomToolsStore"
|
|||||||
import { useKeyboardStore } from "../useKeyBoardStore"
|
import { useKeyboardStore } from "../useKeyBoardStore"
|
||||||
import { useOtherToolsStore } from "../useOtherToolsStore"
|
import { useOtherToolsStore } from "../useOtherToolsStore"
|
||||||
import { clearSupportAnnotationItem, usePaperStore } from "../usePaperStore"
|
import { clearSupportAnnotationItem, usePaperStore } from "../usePaperStore"
|
||||||
|
import { usePaperSupportStore } from "../usePaperSupportStore"
|
||||||
import { renderGroupPath } from "../useRenderGroupPath"
|
import { renderGroupPath } from "../useRenderGroupPath"
|
||||||
import useRenderTag from "../useRenderTag"
|
import useRenderTag from "../useRenderTag"
|
||||||
import { useRightToolsStore } from "../useRightToolsStore"
|
import { useRightToolsStore } from "../useRightToolsStore"
|
||||||
@@ -443,6 +444,7 @@ const PaperContainer = (
|
|||||||
crosshairStatus,
|
crosshairStatus,
|
||||||
assistToolEnabled,
|
assistToolEnabled,
|
||||||
assistToolSize,
|
assistToolSize,
|
||||||
|
renderMode,
|
||||||
showTags,
|
showTags,
|
||||||
showTagsConfigs,
|
showTagsConfigs,
|
||||||
} = useTopToolsStore()
|
} = useTopToolsStore()
|
||||||
@@ -452,6 +454,8 @@ const PaperContainer = (
|
|||||||
selectedPath,
|
selectedPath,
|
||||||
updateSelectedPath,
|
updateSelectedPath,
|
||||||
} = useObjectStore()
|
} = useObjectStore()
|
||||||
|
const currentSelectedPath = selectedPath[activeImage] || []
|
||||||
|
const currentSelectedPathKey = currentSelectedPath.join(",")
|
||||||
|
|
||||||
const {
|
const {
|
||||||
showContextMenu,
|
showContextMenu,
|
||||||
@@ -511,6 +515,11 @@ const PaperContainer = (
|
|||||||
token: number
|
token: number
|
||||||
imageName: string
|
imageName: string
|
||||||
} | null>(null)
|
} | null>(null)
|
||||||
|
const renderModePanRef = useRef({
|
||||||
|
active: false,
|
||||||
|
lastX: 0,
|
||||||
|
lastY: 0,
|
||||||
|
})
|
||||||
|
|
||||||
const paperScope = useRef<paper.PaperScope>(null)
|
const paperScope = useRef<paper.PaperScope>(null)
|
||||||
useEffect(() => {
|
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 saveSupportAnnotationData = useCallback(() => {
|
||||||
const group = usePaperStore.getState().group
|
const group = usePaperStore.getState().group
|
||||||
@@ -2163,6 +2218,7 @@ const PaperContainer = (
|
|||||||
if (useBottomToolsStore.getState().activeImage !== expectedImage) return
|
if (useBottomToolsStore.getState().activeImage !== expectedImage) return
|
||||||
renderGroupPath()
|
renderGroupPath()
|
||||||
renderTag()
|
renderTag()
|
||||||
|
syncRenderModeVisuals()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2194,6 +2250,7 @@ const PaperContainer = (
|
|||||||
if (useBottomToolsStore.getState().activeImage !== expectedImage) return
|
if (useBottomToolsStore.getState().activeImage !== expectedImage) return
|
||||||
renderGroupPath()
|
renderGroupPath()
|
||||||
renderTag()
|
renderTag()
|
||||||
|
syncRenderModeVisuals()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2238,6 +2295,7 @@ const PaperContainer = (
|
|||||||
if (useBottomToolsStore.getState().activeImage !== expectedImage) return
|
if (useBottomToolsStore.getState().activeImage !== expectedImage) return
|
||||||
renderGroupPath()
|
renderGroupPath()
|
||||||
renderTag()
|
renderTag()
|
||||||
|
syncRenderModeVisuals()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof globalThis.requestAnimationFrame === "function") {
|
if (typeof globalThis.requestAnimationFrame === "function") {
|
||||||
@@ -2246,7 +2304,13 @@ const PaperContainer = (
|
|||||||
setTimeout(runBatch, 0)
|
setTimeout(runBatch, 0)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[clearRenderedAnnotationItems, objectOperations, renderPolygons, renderTag]
|
[
|
||||||
|
clearRenderedAnnotationItems,
|
||||||
|
objectOperations,
|
||||||
|
renderPolygons,
|
||||||
|
renderTag,
|
||||||
|
syncRenderModeVisuals,
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
const withPaperGroup = useCallback(
|
const withPaperGroup = useCallback(
|
||||||
@@ -2365,6 +2429,7 @@ const PaperContainer = (
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!tasks.length) {
|
if (!tasks.length) {
|
||||||
|
syncRenderModeVisuals(targetGroup)
|
||||||
resolve(true)
|
resolve(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2403,6 +2468,7 @@ const PaperContainer = (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syncRenderModeVisuals(targetGroup)
|
||||||
resolve(true)
|
resolve(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2416,10 +2482,107 @@ const PaperContainer = (
|
|||||||
isPendingFrameSwitchStale,
|
isPendingFrameSwitchStale,
|
||||||
objectOperations,
|
objectOperations,
|
||||||
renderPolygons,
|
renderPolygons,
|
||||||
|
syncRenderModeVisuals,
|
||||||
withPaperGroup,
|
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(
|
const preparePendingFrameSwitch = useCallback(
|
||||||
async (imageName: string, token: number) => {
|
async (imageName: string, token: number) => {
|
||||||
if (
|
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}
|
{contextMenu}
|
||||||
<Modal
|
<Modal
|
||||||
opened={confirmModalOpened}
|
opened={confirmModalOpened}
|
||||||
|
|||||||
@@ -180,6 +180,8 @@ const TopTools = (
|
|||||||
const {
|
const {
|
||||||
isView,
|
isView,
|
||||||
setIsView,
|
setIsView,
|
||||||
|
renderMode,
|
||||||
|
setRenderMode,
|
||||||
saveCurrentScale,
|
saveCurrentScale,
|
||||||
setSaveCurrentScale,
|
setSaveCurrentScale,
|
||||||
showMultiFrame,
|
showMultiFrame,
|
||||||
@@ -1896,10 +1898,16 @@ const TopTools = (
|
|||||||
<SquarePen style={{ width: 20, height: 20 }} />
|
<SquarePen style={{ width: 20, height: 20 }} />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
)}
|
)}
|
||||||
<Eclipse
|
<Tooltip label={renderMode ? "关闭渲染" : "开启渲染"}>
|
||||||
style={{ width: 20, height: 20, display: "none" }}
|
<ActionIcon
|
||||||
color="gray"
|
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" }} />
|
<CopySlash style={{ width: 20, height: 20, display: "none" }} />
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex
|
<Flex
|
||||||
|
|||||||
@@ -5600,6 +5600,9 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
usePaperStore.getState().viewTool?.activate()
|
usePaperStore.getState().viewTool?.activate()
|
||||||
|
if (usePaperStore.getState().el) {
|
||||||
|
usePaperStore.getState().el!.style.cursor = "default"
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ interface TopToolsState {
|
|||||||
// 标注页面是否仅查看
|
// 标注页面是否仅查看
|
||||||
isView: boolean
|
isView: boolean
|
||||||
setIsView: (val: boolean) => void
|
setIsView: (val: boolean) => void
|
||||||
|
renderMode: boolean
|
||||||
|
setRenderMode: (val: boolean) => void
|
||||||
// 绘制模式
|
// 绘制模式
|
||||||
editMode: boolean
|
editMode: boolean
|
||||||
setEditMode: (val: boolean) => void
|
setEditMode: (val: boolean) => void
|
||||||
@@ -81,6 +83,7 @@ interface TopToolsState {
|
|||||||
|
|
||||||
const initialTopToolsState = {
|
const initialTopToolsState = {
|
||||||
isView: false,
|
isView: false,
|
||||||
|
renderMode: false,
|
||||||
editMode: false,
|
editMode: false,
|
||||||
pressA: false,
|
pressA: false,
|
||||||
imageFilter: {
|
imageFilter: {
|
||||||
@@ -114,6 +117,12 @@ export const useTopToolsStore = create<TopToolsState>()(
|
|||||||
...state,
|
...state,
|
||||||
isView: val,
|
isView: val,
|
||||||
})),
|
})),
|
||||||
|
renderMode: initialTopToolsState.renderMode,
|
||||||
|
setRenderMode: (val: boolean) =>
|
||||||
|
set((state: TopToolsState) => ({
|
||||||
|
...state,
|
||||||
|
renderMode: val,
|
||||||
|
})),
|
||||||
editMode: initialTopToolsState.editMode,
|
editMode: initialTopToolsState.editMode,
|
||||||
setEditMode: (val: boolean) =>
|
setEditMode: (val: boolean) =>
|
||||||
set((state: TopToolsState) => ({
|
set((state: TopToolsState) => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user