feat(label): add right select
This commit is contained in:
@@ -318,6 +318,229 @@ const hidePaperContextMenu = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const PAPER_OBJECT_TYPES = ["rectangle", "polygon", "brush", "point"] as const
|
||||
const PAPER_CONTEXT_HIT_TYPES = [
|
||||
...PAPER_OBJECT_TYPES,
|
||||
"circle",
|
||||
"mask",
|
||||
"pathBuff",
|
||||
"pathCircle",
|
||||
] as const
|
||||
|
||||
const isPaperObjectType = (type: unknown) =>
|
||||
typeof type === "string" &&
|
||||
PAPER_OBJECT_TYPES.includes(type as (typeof PAPER_OBJECT_TYPES)[number])
|
||||
|
||||
const isPaperContextHitType = (type: unknown) =>
|
||||
typeof type === "string" &&
|
||||
PAPER_CONTEXT_HIT_TYPES.includes(
|
||||
type as (typeof PAPER_CONTEXT_HIT_TYPES)[number]
|
||||
)
|
||||
|
||||
const getPaperCursorByMode = (
|
||||
mode: PaperState["mode"] = usePaperStore.getState().mode
|
||||
) => {
|
||||
if (
|
||||
["polygon", "rectangle", "brush", "point", "support"].includes(mode || "")
|
||||
) {
|
||||
return "crosshair"
|
||||
}
|
||||
return "default"
|
||||
}
|
||||
|
||||
const syncPaperCursorByMode = (
|
||||
mode: PaperState["mode"] = usePaperStore.getState().mode
|
||||
) => {
|
||||
if (usePaperStore.getState().el) {
|
||||
usePaperStore.getState().el!.style.cursor = getPaperCursorByMode(mode)
|
||||
}
|
||||
}
|
||||
|
||||
const clearPaperSelectedObjects = () => {
|
||||
const group = usePaperStore.getState().group
|
||||
if (!group) return
|
||||
|
||||
group
|
||||
.getItems({
|
||||
match: (item: paper.Item) => !!item.data?.selected,
|
||||
})
|
||||
.forEach((item) => {
|
||||
item.data.selected = false
|
||||
})
|
||||
|
||||
usePaperSupportStore.getState().clearAll()
|
||||
|
||||
const activeImage = useBottomToolsStore.getState().activeImage
|
||||
const selectedIds = [
|
||||
...(useObjectStore.getState().selectedPath[activeImage] || []),
|
||||
]
|
||||
|
||||
selectedIds.forEach((id) => {
|
||||
usePaperStore
|
||||
.getState()
|
||||
.getItemsById(id)
|
||||
.forEach((item) => {
|
||||
if (
|
||||
(item instanceof paper.Path || item instanceof paper.CompoundPath) &&
|
||||
["rectangle", "polygon"].includes(item.data?.type || "")
|
||||
) {
|
||||
item.fillColor = item.data?.blankColor || item.fillColor || null
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
selectedIds.forEach((id) => {
|
||||
useObjectStore.getState().updateSelectedPath(activeImage, "DELETE", id)
|
||||
})
|
||||
}
|
||||
|
||||
const applyPaperSelectedPath = (item: paper.Path | paper.CompoundPath) => {
|
||||
if (item.data.type === "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 (item.data.type === "brush") {
|
||||
item.data.selected = true
|
||||
if (item instanceof paper.Path) {
|
||||
usePaperSupportStore.getState().handleMask(item)
|
||||
usePaperSupportStore.getState().handleBufferPaths(item)
|
||||
usePaperSupportStore.getState().handleCircles(item)
|
||||
}
|
||||
} else if (item.data.type === "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 (item.data.type === "polygon") {
|
||||
item.data.selected = true
|
||||
if (!(item instanceof paper.Path) || !item.data?.isHollowPolygon) {
|
||||
item.fillColor = item.data.fillColor || item.fillColor || null
|
||||
}
|
||||
}
|
||||
|
||||
item.bringToFront()
|
||||
}
|
||||
|
||||
const getPaperSelectionPath = (
|
||||
id: number,
|
||||
localPoint: paper.Point,
|
||||
preferredItem?: paper.Item | null
|
||||
) => {
|
||||
if (
|
||||
preferredItem instanceof paper.Path &&
|
||||
isPaperObjectType(preferredItem.data?.type)
|
||||
) {
|
||||
return preferredItem
|
||||
}
|
||||
|
||||
const objectPaths = usePaperStore
|
||||
.getState()
|
||||
.getItemsById(id)
|
||||
.filter(
|
||||
(item): item is paper.Path =>
|
||||
item instanceof paper.Path && isPaperObjectType(item.data?.type)
|
||||
)
|
||||
|
||||
if (!objectPaths.length) return null
|
||||
if (objectPaths.length === 1) return objectPaths[0]
|
||||
|
||||
let nearestPath = objectPaths[0]
|
||||
for (let index = 1; index < objectPaths.length; index += 1) {
|
||||
const item = objectPaths[index]
|
||||
if (
|
||||
item.getNearestPoint(localPoint).getDistance(localPoint) <
|
||||
nearestPath.getNearestPoint(localPoint).getDistance(localPoint)
|
||||
) {
|
||||
nearestPath = item
|
||||
}
|
||||
}
|
||||
|
||||
return nearestPath
|
||||
}
|
||||
|
||||
const trySelectPaperObjectByPoint = (clickPoint: paper.Point) => {
|
||||
const group = usePaperStore.getState().group
|
||||
if (!group) return false
|
||||
|
||||
const hitResult = group.hitTest(clickPoint, {
|
||||
segments: true,
|
||||
stroke: true,
|
||||
curves: true,
|
||||
fill: true,
|
||||
guides: false,
|
||||
tolerance: usePaperStore.getState().paperScope
|
||||
? 8 / useTopToolsStore.getState().scale
|
||||
: 0,
|
||||
match: (hit: paper.HitResult) =>
|
||||
!!hit.item.data?.id && isPaperContextHitType(hit.item.data?.type),
|
||||
})
|
||||
|
||||
const id = hitResult?.item?.data?.id
|
||||
if (!id) return false
|
||||
|
||||
clearPaperSelectedObjects()
|
||||
|
||||
const localPoint = group.globalToLocal(clickPoint)
|
||||
const selectedPath = getPaperSelectionPath(id, localPoint, hitResult?.item)
|
||||
const operationId = (
|
||||
selectedPath?.data?.operationId ||
|
||||
usePaperStore.getState().getItemById(id)?.data?.operationId ||
|
||||
hitResult?.item?.data?.operationId ||
|
||||
""
|
||||
).toString()
|
||||
|
||||
usePaperStore
|
||||
.getState()
|
||||
.getItemsById(id)
|
||||
.forEach((item) => {
|
||||
if (!(item instanceof paper.Path || item instanceof paper.CompoundPath))
|
||||
return
|
||||
if (!isPaperObjectType(item.data?.type)) return
|
||||
|
||||
if (item.data.type === "polygon") {
|
||||
applyPaperSelectedPath(item)
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
item instanceof paper.CompoundPath ||
|
||||
(selectedPath && item === selectedPath)
|
||||
) {
|
||||
applyPaperSelectedPath(item)
|
||||
}
|
||||
})
|
||||
|
||||
const activeImage = useBottomToolsStore.getState().activeImage
|
||||
useObjectStore.getState().updateSelectedPath(activeImage, "ADD", id)
|
||||
|
||||
const category = useTopToolsStore
|
||||
.getState()
|
||||
.objectOperations.find(
|
||||
(item) => item.category_id.toString() === operationId
|
||||
)
|
||||
const { top, left } = getShowContextMenuPosition(
|
||||
clickPoint,
|
||||
(category || {}) as Project.LabelSchemaList,
|
||||
5,
|
||||
5
|
||||
)
|
||||
|
||||
useOtherToolsStore.getState().setShowContextMenu({
|
||||
showContextMenu: true,
|
||||
position: { top, left },
|
||||
imageId:
|
||||
selectedPath?.data?.imageId ||
|
||||
hitResult?.item?.data?.imageId ||
|
||||
activeImage,
|
||||
operationId,
|
||||
id,
|
||||
})
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
let isMiddleMousePanning = false
|
||||
let hoveredBufferPathInfo: {
|
||||
id: number
|
||||
@@ -3530,8 +3753,14 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
if (startMiddleMousePan(e.event)) return
|
||||
if (e.event.button === 2) {
|
||||
e.event.preventDefault()
|
||||
hidePaperContextMenu()
|
||||
undoPolygonPoint()
|
||||
if (polygon || points.length) {
|
||||
hidePaperContextMenu()
|
||||
undoPolygonPoint()
|
||||
return
|
||||
}
|
||||
if (!trySelectPaperObjectByPoint(e.point)) {
|
||||
hidePaperContextMenu()
|
||||
}
|
||||
return
|
||||
}
|
||||
if (e.event.button !== 0) return
|
||||
@@ -4113,8 +4342,18 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
let rect: paper.Path.Rectangle | null
|
||||
let rectangleTool = paperRectangleTool
|
||||
|
||||
rectangleTool.onMouseDown = (e: { event: MouseEvent }) => {
|
||||
rectangleTool.onMouseDown = (e: {
|
||||
event: MouseEvent
|
||||
point: paper.Point
|
||||
}) => {
|
||||
if (startMiddleMousePan(e.event)) return
|
||||
if (e.event.button === 2) {
|
||||
e.event.preventDefault()
|
||||
if (!trySelectPaperObjectByPoint(e.point)) {
|
||||
hidePaperContextMenu()
|
||||
}
|
||||
return
|
||||
}
|
||||
if (e.event && e.event.button !== 2)
|
||||
useOtherToolsStore.getState().setShowContextMenu({
|
||||
showContextMenu: false,
|
||||
@@ -4463,8 +4702,14 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
if (startMiddleMousePan(e.event)) return
|
||||
if (e.event.button === 2) {
|
||||
e.event.preventDefault()
|
||||
hidePaperContextMenu()
|
||||
undoBrushPoint()
|
||||
if (myPath || points.length) {
|
||||
hidePaperContextMenu()
|
||||
undoBrushPoint()
|
||||
return
|
||||
}
|
||||
if (!trySelectPaperObjectByPoint(e.point)) {
|
||||
hidePaperContextMenu()
|
||||
}
|
||||
return
|
||||
}
|
||||
if (e.event.button !== 0) return
|
||||
@@ -4934,8 +5179,14 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
if (startMiddleMousePan(e.event)) return
|
||||
if (e.event.button === 2) {
|
||||
e.event.preventDefault()
|
||||
hidePaperContextMenu()
|
||||
undoPoint()
|
||||
if (myPath || points.length) {
|
||||
hidePaperContextMenu()
|
||||
undoPoint()
|
||||
return
|
||||
}
|
||||
if (!trySelectPaperObjectByPoint(e.point)) {
|
||||
hidePaperContextMenu()
|
||||
}
|
||||
return
|
||||
}
|
||||
if (e.event.button !== 0) return
|
||||
@@ -5426,7 +5677,10 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
clearHoveredBufferPathHighlight()
|
||||
circle.strokeWidth = 4
|
||||
circle.fillColor = new paper.Color("#FFF")
|
||||
if (usePaperStore.getState().el) {
|
||||
if (
|
||||
usePaperStore.getState().mode === "pan" &&
|
||||
usePaperStore.getState().el
|
||||
) {
|
||||
usePaperStore.getState().el!.style.cursor = "move"
|
||||
}
|
||||
}
|
||||
@@ -5436,9 +5690,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
}
|
||||
circle.strokeWidth = 2
|
||||
circle.fillColor = color
|
||||
if (usePaperStore.getState().el) {
|
||||
usePaperStore.getState().el!.style.cursor = "default"
|
||||
}
|
||||
syncPaperCursorByMode()
|
||||
}
|
||||
return circle
|
||||
},
|
||||
@@ -5485,7 +5737,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
!hoveredPathCircleInfo?.item.parent &&
|
||||
!hoveredBufferPathInfo
|
||||
) {
|
||||
usePaperStore.getState().el!.style.cursor = "default"
|
||||
syncPaperCursorByMode()
|
||||
}
|
||||
}
|
||||
const scheduleClear = () => {
|
||||
@@ -5564,45 +5816,31 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
switch (modeParam) {
|
||||
case "pan":
|
||||
usePaperStore.getState().panTool?.activate()
|
||||
if (usePaperStore.getState().el) {
|
||||
usePaperStore.getState().el!.style.cursor = "default"
|
||||
}
|
||||
syncPaperCursorByMode(modeParam)
|
||||
break
|
||||
case "polygon":
|
||||
usePaperStore.getState().polygonTool?.activate()
|
||||
if (usePaperStore.getState().el) {
|
||||
usePaperStore.getState().el!.style.cursor = "crosshair"
|
||||
}
|
||||
syncPaperCursorByMode(modeParam)
|
||||
break
|
||||
case "rectangle":
|
||||
usePaperStore.getState().rectangleTool?.activate()
|
||||
if (usePaperStore.getState().el) {
|
||||
usePaperStore.getState().el!.style.cursor = "crosshair"
|
||||
}
|
||||
syncPaperCursorByMode(modeParam)
|
||||
break
|
||||
case "brush":
|
||||
usePaperStore.getState().brushTool?.activate()
|
||||
if (usePaperStore.getState().el) {
|
||||
usePaperStore.getState().el!.style.cursor = "crosshair"
|
||||
}
|
||||
syncPaperCursorByMode(modeParam)
|
||||
break
|
||||
case "point":
|
||||
usePaperStore.getState().pointTool?.activate()
|
||||
if (usePaperStore.getState().el) {
|
||||
usePaperStore.getState().el!.style.cursor = "crosshair"
|
||||
}
|
||||
syncPaperCursorByMode(modeParam)
|
||||
break
|
||||
case "support":
|
||||
usePaperStore.getState().supportTool?.activate()
|
||||
if (usePaperStore.getState().el) {
|
||||
usePaperStore.getState().el!.style.cursor = "crosshair"
|
||||
}
|
||||
syncPaperCursorByMode(modeParam)
|
||||
break
|
||||
default:
|
||||
usePaperStore.getState().viewTool?.activate()
|
||||
if (usePaperStore.getState().el) {
|
||||
usePaperStore.getState().el!.style.cursor = "default"
|
||||
}
|
||||
syncPaperCursorByMode(modeParam)
|
||||
break
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user