From 5fc65c8e7398a5c78da16342f77a5f9f6c2e3171 Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Thu, 12 Mar 2020 18:58:36 +0300 Subject: [PATCH] PR fixed --- cvat-canvas/src/typescript/canvasView.ts | 43 +++++------ cvat-core/src/annotations-collection.js | 16 ++--- cvat-core/src/annotations-filter.js | 7 +- cvat-ui/src/actions/annotation-actions.ts | 72 ++++++++----------- .../standard-workspace/canvas-wrapper.tsx | 3 +- .../objects-side-bar/styles.scss | 1 - .../controls-side-bar/draw-shape-popover.tsx | 4 +- .../controls-side-bar/setup-tag-popover.tsx | 44 ++++++++++-- cvat-ui/src/reducers/annotation-reducer.ts | 26 +------ 9 files changed, 103 insertions(+), 113 deletions(-) diff --git a/cvat-canvas/src/typescript/canvasView.ts b/cvat-canvas/src/typescript/canvasView.ts index 8966a1da..24e9923f 100644 --- a/cvat-canvas/src/typescript/canvasView.ts +++ b/cvat-canvas/src/typescript/canvasView.ts @@ -399,11 +399,8 @@ export class CanvasViewImpl implements CanvasView, Listener { this.svgTexts[state.clientID].remove(); } - const shape = this.svgShapes[state.clientID]; - if (shape) { - shape.off('click.canvas'); - shape.remove(); - } + this.svgShapes[state.clientID].off('click.canvas'); + this.svgShapes[state.clientID].remove(); delete this.drawnStates[state.clientID]; } @@ -849,7 +846,7 @@ export class CanvasViewImpl implements CanvasView, Listener { hidden: state.hidden, lock: state.lock, shapeType: state.shapeType, - points: Array.isArray(state.points) ? [...state.points] : [], + points: [...state.points], attributes: { ...state.attributes }, zOrder: state.zOrder, pinned: state.pinned, @@ -894,7 +891,7 @@ export class CanvasViewImpl implements CanvasView, Listener { this.activate(activeElement); } - if (state.points && state.points + if (state.points .some((p: number, id: number): boolean => p !== drawnState.points[id]) ) { const translatedPoints: number[] = translate(state.points); @@ -1023,25 +1020,23 @@ export class CanvasViewImpl implements CanvasView, Listener { const drawnState = this.drawnStates[clientID]; const shape = this.svgShapes[clientID]; - if (shape) { - shape.removeClass('cvat_canvas_shape_activated'); - - if (!drawnState.pinned) { - (shape as any).off('dragstart'); - (shape as any).off('dragend'); - (shape as any).draggable(false); - } + shape.removeClass('cvat_canvas_shape_activated'); - if (drawnState.shapeType !== 'points') { - this.selectize(false, shape); - } + if (!drawnState.pinned) { + (shape as any).off('dragstart'); + (shape as any).off('dragend'); + (shape as any).draggable(false); + } - (shape as any).off('resizestart'); - (shape as any).off('resizing'); - (shape as any).off('resizedone'); - (shape as any).resize(false); + if (drawnState.shapeType !== 'points') { + this.selectize(false, shape); } + (shape as any).off('resizestart'); + (shape as any).off('resizing'); + (shape as any).off('resizedone'); + (shape as any).resize(false); + // TODO: Hide text only if it is hidden by settings const text = this.svgTexts[clientID]; if (text) { @@ -1090,10 +1085,6 @@ export class CanvasViewImpl implements CanvasView, Listener { this.activeElement = { ...activeElement }; const shape = this.svgShapes[clientID]; - if (!shape) { - return; - } - let text = this.svgTexts[clientID]; if (!text) { text = this.addText(state); diff --git a/cvat-core/src/annotations-collection.js b/cvat-core/src/annotations-collection.js index 68b78b8c..309d387d 100644 --- a/cvat-core/src/annotations-collection.js +++ b/cvat-core/src/annotations-collection.js @@ -802,7 +802,9 @@ let minimumState = null; for (const state of objectStates) { checkObjectType('object state', state, null, ObjectState); - if (state.outside || state.hidden) continue; + if (state.outside || state.hidden || state.objectType === ObjectType.TAG) { + continue; + } const object = this.objects[state.clientID]; if (typeof (object) === 'undefined') { @@ -810,13 +812,11 @@ 'The object has not been saved yet. Call annotations.put([state]) before', ); } - if (!(object instanceof Tag)) { - const distance = object.constructor.distance(state.points, x, y); - if (distance !== null && (minimumDistance === null - || distance < minimumDistance)) { - minimumDistance = distance; - minimumState = state; - } + const distance = object.constructor.distance(state.points, x, y); + if (distance !== null && (minimumDistance === null + || distance < minimumDistance)) { + minimumDistance = distance; + minimumState = state; } } diff --git a/cvat-core/src/annotations-filter.js b/cvat-core/src/annotations-filter.js index 903067bc..8a00cab2 100644 --- a/cvat-core/src/annotations-filter.js +++ b/cvat-core/src/annotations-filter.js @@ -8,7 +8,10 @@ */ const jsonpath = require('jsonpath'); -const { AttributeType } = require('./enums'); +const { + AttributeType, + ObjectType, +} = require('./enums'); const { ArgumentError } = require('./exceptions'); @@ -167,7 +170,7 @@ class AnnotationsFilter { let ybr = Number.MIN_SAFE_INTEGER; let [width, height] = [null, null]; - if (state.objectType !== 'tag') { + if (state.objectType !== ObjectType.TAG) { state.points.forEach((coord, idx) => { if (idx % 2) { // y ytl = Math.min(ytl, coord); diff --git a/cvat-ui/src/actions/annotation-actions.ts b/cvat-ui/src/actions/annotation-actions.ts index 6f901cb7..cb7f998f 100644 --- a/cvat-ui/src/actions/annotation-actions.ts +++ b/cvat-ui/src/actions/annotation-actions.ts @@ -84,10 +84,10 @@ export enum AnnotationActionTypes { COPY_SHAPE = 'COPY_SHAPE', PASTE_SHAPE = 'PASTE_SHAPE', EDIT_SHAPE = 'EDIT_SHAPE', - DRAW_SHAPE = 'DRAW_SHAPE', REPEAT_DRAW_SHAPE = 'REPEAT_DRAW_SHAPE', SHAPE_DRAWN = 'SHAPE_DRAWN', RESET_CANVAS = 'RESET_CANVAS', + REMEMBER_CREATED_OBJECT = 'REMEMBER_CREATED_OBJECT', UPDATE_ANNOTATIONS_SUCCESS = 'UPDATE_ANNOTATIONS_SUCCESS', UPDATE_ANNOTATIONS_FAILED = 'UPDATE_ANNOTATIONS_FAILED', CREATE_ANNOTATIONS_SUCCESS = 'CREATE_ANNOTATIONS_SUCCESS', @@ -844,15 +844,17 @@ ThunkAction, {}, {}, AnyAction> { }; } -export function drawShape( - shapeType: ShapeType, - labelID: number, +export function rememberObject( objectType: ObjectType, + labelID: number, + shapeType?: ShapeType, points?: number, rectDrawingMethod?: RectDrawingMethod, ): AnyAction { - let activeControl = ActiveControl.DRAW_RECTANGLE; - if (shapeType === ShapeType.POLYGON) { + let activeControl = ActiveControl.CURSOR; + if (shapeType === ShapeType.RECTANGLE) { + activeControl = ActiveControl.DRAW_RECTANGLE; + } else if (shapeType === ShapeType.POLYGON) { activeControl = ActiveControl.DRAW_POLYGON; } else if (shapeType === ShapeType.POLYLINE) { activeControl = ActiveControl.DRAW_POLYLINE; @@ -861,7 +863,7 @@ export function drawShape( } return { - type: AnnotationActionTypes.DRAW_SHAPE, + type: AnnotationActionTypes.REMEMBER_CREATED_OBJECT, payload: { shapeType, labelID, @@ -1152,10 +1154,7 @@ export function searchAnnotationsAsync( }; } -export function addTagAsync( - labelID: number, - frame: number, -): ThunkAction, {}, {}, AnyAction> { +export function pasteShapeAsync(): ThunkAction, {}, {}, AnyAction> { return async (dispatch: ActionCreator): Promise => { const { canvas: { @@ -1164,40 +1163,14 @@ export function addTagAsync( job: { instance: jobInstance, }, - } = getStore().getState().annotation; - - dispatch({ - type: AnnotationActionTypes.ADD_TAG, - payload: { - labelID, - objectType: ObjectType.TAG, - activeControl: ActiveControl.CURSOR, - }, - }); - - canvasInstance.cancel(); - const objectState = new cvat.classes.ObjectState({ - objectType: ObjectType.TAG, - label: jobInstance.task.labels - .filter((label: any) => label.id === labelID)[0], - frame, - }); - dispatch(createAnnotationsAsync(jobInstance, frame, [objectState])); - }; -} - -export function pasteShapeAsync(): ThunkAction, {}, {}, AnyAction> { - return async (dispatch: ActionCreator): Promise => { - const initialState = getStore().getState().annotation.drawing.activeInitialState; - const { - canvas: { - instance: canvasInstance, - }, player: { frame: { number: frameNumber, }, }, + drawing: { + activeInitialState: initialState, + }, } = getStore().getState().annotation; if (initialState) { @@ -1221,7 +1194,13 @@ export function pasteShapeAsync(): ThunkAction, {}, {}, AnyAction> canvasInstance.cancel(); if (initialState.objectType === ObjectType.TAG) { - dispatch(addTagAsync(initialState.label.id, frameNumber)); + const objectState = new cvat.classes.ObjectState({ + objectType: ObjectType.TAG, + label: initialState.label, + attributes: initialState.attributes, + frame: frameNumber, + }); + dispatch(createAnnotationsAsync(jobInstance, frameNumber, [objectState])); } else { canvasInstance.draw({ enabled: true, @@ -1238,6 +1217,10 @@ export function repeatDrawShapeAsync(): ThunkAction, {}, {}, AnyAc canvas: { instance: canvasInstance, }, + job: { + labels, + instance: jobInstance, + }, player: { frame: { number: frameNumber, @@ -1272,7 +1255,12 @@ export function repeatDrawShapeAsync(): ThunkAction, {}, {}, AnyAc canvasInstance.cancel(); if (activeObjectType === ObjectType.TAG) { - dispatch(addTagAsync(activeLabelID, frameNumber)); + const objectState = new cvat.classes.ObjectState({ + objectType: ObjectType.TAG, + label: labels.filter((label: any) => label.id === activeLabelID)[0], + frame: frameNumber, + }); + dispatch(createAnnotationsAsync(jobInstance, frameNumber, [objectState])); } else { canvasInstance.draw({ enabled: true, diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx index 1b5d7508..c1d7efa1 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx @@ -345,7 +345,8 @@ export default class CanvasWrapperComponent extends React.PureComponent { } = this.props; if (frameData !== null) { - canvasInstance.setup(frameData, annotations); + canvasInstance.setup(frameData, annotations + .filter((e) => e.objectType !== ObjectType.TAG)); canvasInstance.rotate(frameAngle); } } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/styles.scss b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/styles.scss index 9ffa21d8..81e6ba9c 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/styles.scss +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/styles.scss @@ -121,7 +121,6 @@ .cvat-objects-sidebar-state-item-color { width: 7px; opacity: 1; - background-color: $default-object-colorpicker-item-background-color; &:hover { opacity: 0.7; diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx index 8d418e68..868b1ddb 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx @@ -13,7 +13,7 @@ import { } from 'reducers/interfaces'; import { - drawShape, + rememberObject, } from 'actions/annotation-actions'; import { Canvas, RectDrawingMethod } from 'cvat-canvas'; import DrawShapePopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover'; @@ -47,7 +47,7 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { points?: number, rectDrawingMethod?: RectDrawingMethod, ): void { - dispatch(drawShape(shapeType, labelID, objectType, points, rectDrawingMethod)); + dispatch(rememberObject(objectType, labelID, shapeType, points, rectDrawingMethod)); }, }; } diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx index d31d1e7e..4ba675c8 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx @@ -7,26 +7,38 @@ import { connect } from 'react-redux'; import { CombinedState, + ObjectType, } from 'reducers/interfaces'; import { - addTagAsync, + createAnnotationsAsync, + rememberObject, } from 'actions/annotation-actions'; import SetupTagPopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover'; +import { Canvas } from 'cvat-canvas'; +import getCore from 'cvat-core'; + +const cvat = getCore(); interface DispatchToProps { - onAddTag(labelID: number, frame: number): void; + onAnnotationCreate(sessionInstance: any, frame: number, states: any[]): void; + onRememberObject(labelID: number): void; } interface StateToProps { + canvasInstance: Canvas; + jobInstance: any; labels: any[]; frame: number; } function mapDispatchToProps(dispatch: any): DispatchToProps { return { - onAddTag(labelID: number, frame: number): void { - dispatch(addTagAsync(labelID, frame)); + onAnnotationCreate(sessionInstance: any, frame: number, states: any[]): void { + dispatch(createAnnotationsAsync(sessionInstance, frame, states)); + }, + onRememberObject(labelID: number): void { + dispatch(rememberObject(ObjectType.TAG, labelID)); }, }; } @@ -34,7 +46,11 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { function mapStateToProps(state: CombinedState): StateToProps { const { annotation: { + canvas: { + instance: canvasInstance, + }, job: { + instance: jobInstance, labels, }, player: { @@ -46,6 +62,8 @@ function mapStateToProps(state: CombinedState): StateToProps { } = state; return { + canvasInstance, + jobInstance, labels, frame, }; @@ -76,12 +94,26 @@ class DrawShapePopoverContainer extends React.PureComponent { private onSetup(): void { const { frame, - onAddTag, + labels, + jobInstance, + canvasInstance, + onAnnotationCreate, + onRememberObject, } = this.props; const { selectedLabelID } = this.state; - onAddTag(selectedLabelID, frame); + canvasInstance.cancel(); + + onRememberObject(selectedLabelID); + + const objectState = new cvat.classes.ObjectState({ + objectType: ObjectType.TAG, + label: labels.filter((label: any) => label.id === selectedLabelID)[0], + frame, + }); + + onAnnotationCreate(jobInstance, frame, [objectState]); } public render(): JSX.Element { diff --git a/cvat-ui/src/reducers/annotation-reducer.ts b/cvat-ui/src/reducers/annotation-reducer.ts index 07298373..83b7a8c0 100644 --- a/cvat-ui/src/reducers/annotation-reducer.ts +++ b/cvat-ui/src/reducers/annotation-reducer.ts @@ -393,7 +393,7 @@ export default (state = defaultState, action: AnyAction): AnnotationState => { }, }; } - case AnnotationActionTypes.DRAW_SHAPE: { + case AnnotationActionTypes.REMEMBER_CREATED_OBJECT: { const { shapeType, labelID, @@ -437,30 +437,6 @@ export default (state = defaultState, action: AnyAction): AnnotationState => { }, }; } - case AnnotationActionTypes.ADD_TAG: { - const { - labelID, - objectType, - activeControl, - } = action.payload; - - return { - ...state, - annotations: { - ...state.annotations, - activatedStateID: null, - }, - canvas: { - ...state.canvas, - activeControl, - }, - drawing: { - ...defaultState.drawing, - activeLabelID: labelID, - activeObjectType: objectType, - }, - }; - } case AnnotationActionTypes.MERGE_OBJECTS: { const { enabled } = action.payload; const activeControl = enabled