diff --git a/frontend/javascripts/oxalis/model/actions/skeletontracing_actions.js b/frontend/javascripts/oxalis/model/actions/skeletontracing_actions.js index 8c7184e028..71e05756f2 100644 --- a/frontend/javascripts/oxalis/model/actions/skeletontracing_actions.js +++ b/frontend/javascripts/oxalis/model/actions/skeletontracing_actions.js @@ -74,6 +74,11 @@ type CreateBranchPointAction = { timestamp: number, }; type DeleteBranchPointAction = { type: "DELETE_BRANCHPOINT" }; +type DeleteBranchpointByIdAction = { + type: "DELETE_BRANCHPOINT_BY_ID", + nodeId: number, + treeId: number, +}; type ToggleTreeAction = { type: "TOGGLE_TREE", treeId: ?number, timestamp: number }; type SetTreeVisibilityAction = { type: "SET_TREE_VISIBILITY", @@ -146,6 +151,7 @@ export type SkeletonTracingAction = | SetNodePositionAction | CreateBranchPointAction | DeleteBranchPointAction + | DeleteBranchpointByIdAction | RequestDeleteBranchPointAction | CreateTreeAction | AddTreesAndGroupsAction @@ -186,6 +192,7 @@ export const SkeletonTracingSaveRelevantActions = [ "SET_NODE_RADIUS", "SET_NODE_POSITION", "CREATE_BRANCHPOINT", + "DELETE_BRANCHPOINT_BY_ID", "DELETE_BRANCHPOINT", "CREATE_TREE", "ADD_TREES_AND_GROUPS", @@ -314,6 +321,15 @@ export const deleteBranchPointAction = (): DeleteBranchPointAction => ({ type: "DELETE_BRANCHPOINT", }); +export const deleteBranchpointByIdAction = ( + nodeId: number, + treeId: number, +): DeleteBranchpointByIdAction => ({ + type: "DELETE_BRANCHPOINT_BY_ID", + nodeId, + treeId, +}); + export const requestDeleteBranchPointAction = (): RequestDeleteBranchPointAction => ({ type: "REQUEST_DELETE_BRANCHPOINT", }); diff --git a/frontend/javascripts/oxalis/model/reducers/skeletontracing_reducer.js b/frontend/javascripts/oxalis/model/reducers/skeletontracing_reducer.js index cb9ac489d0..39317b2fbe 100644 --- a/frontend/javascripts/oxalis/model/reducers/skeletontracing_reducer.js +++ b/frontend/javascripts/oxalis/model/reducers/skeletontracing_reducer.js @@ -609,6 +609,27 @@ function SkeletonTracingReducer(state: OxalisState, action: Action): OxalisState .getOrElse(state); } + case "DELETE_BRANCHPOINT_BY_ID": { + const { nodeId, treeId } = action; + return getTree(skeletonTracing, treeId) + .map(tree => + update(state, { + tracing: { + skeleton: { + trees: { + [treeId]: { + branchPoints: { + $set: tree.branchPoints.filter(bp => bp.nodeId !== nodeId), + }, + }, + }, + }, + }, + }), + ) + .getOrElse(state); + } + case "CREATE_TREE": { const { timestamp } = action; return createTree(state, timestamp) diff --git a/frontend/javascripts/oxalis/view/context_menu.js b/frontend/javascripts/oxalis/view/context_menu.js index 17f0b103a9..880e211c25 100644 --- a/frontend/javascripts/oxalis/view/context_menu.js +++ b/frontend/javascripts/oxalis/view/context_menu.js @@ -30,6 +30,8 @@ import { setActiveNodeAction, createTreeAction, setTreeVisibilityAction, + createBranchPointAction, + deleteBranchpointByIdAction, } from "oxalis/model/actions/skeletontracing_actions"; import { hasAgglomerateMapping, @@ -88,6 +90,8 @@ type DispatchProps = {| addNewBoundingBox: Vector3 => void, deleteBoundingBox: number => void, setActiveCell: (number, somePosition?: Vector3) => void, + createBranchPoint: (number, number) => void, + deleteBranchpointById: (number, number) => void, |}; type StateProps = {| @@ -242,6 +246,8 @@ function NodeContextMenuOptions({ deleteEdge, mergeTrees, deleteNode, + createBranchPoint, + deleteBranchpointById, setActiveNode, hideTree, useLegacyBindings, @@ -252,6 +258,7 @@ function NodeContextMenuOptions({ const { activeTreeId, trees, activeNodeId } = skeletonTracing; const clickedTree = findTreeByNodeId(trees, clickedNodeId).get(); const areInSameTree = activeTreeId === clickedTree.treeId; + const isBranchpoint = clickedTree.branchPoints.find(bp => bp.nodeId === clickedNodeId) != null; const isTheSameNode = activeNodeId === clickedNodeId; let areNodesConnected = false; if (areInSameTree && !isTheSameNode && activeNodeId != null) { @@ -295,6 +302,27 @@ function NodeContextMenuOptions({ > Delete this Node {activeNodeId === clickedNodeId ? shortcutBuilder(["Del"]) : null} + {isBranchpoint ? ( +