From 6acda049a8a69ab0217c7ef73c1ffdfb9fea9c7c Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Tue, 3 Mar 2020 20:33:40 +0300 Subject: [PATCH 01/12] Added tag popover template --- .../controls-side-bar/controls-side-bar.tsx | 16 ++- .../controls-side-bar/setup-tag-control.tsx | 48 +++++++++ .../controls-side-bar/setup-tag-popover.tsx | 73 +++++++++++++ .../controls-side-bar/setup-tag-popover.tsx | 101 ++++++++++++++++++ cvat-ui/src/reducers/interfaces.ts | 1 + 5 files changed, 229 insertions(+), 10 deletions(-) create mode 100644 cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-control.tsx create mode 100644 cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx create mode 100644 cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/controls-side-bar.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/controls-side-bar.tsx index 176c384b..9483c148 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/controls-side-bar.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/controls-side-bar.tsx @@ -5,20 +5,14 @@ import React from 'react'; import { - Icon, Layout, - Tooltip, } from 'antd'; import { ActiveControl, - Rotation + Rotation, } from 'reducers/interfaces'; -import { - TagIcon, -} from 'icons'; - import { Canvas, } from 'cvat-canvas'; @@ -32,6 +26,7 @@ import DrawRectangleControl from './draw-rectangle-control'; import DrawPolygonControl from './draw-polygon-control'; import DrawPolylineControl from './draw-polyline-control'; import DrawPointsControl from './draw-points-control'; +import SetupTagControl from './setup-tag-control'; import MergeControl from './merge-control'; import GroupControl from './group-control'; import SplitControl from './split-control'; @@ -91,9 +86,10 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element { isDrawing={activeControl === ActiveControl.DRAW_POINTS} /> - - - +
diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-control.tsx new file mode 100644 index 00000000..0f711ba1 --- /dev/null +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-control.tsx @@ -0,0 +1,48 @@ +// Copyright (C) 2020 Intel Corporation +// +// SPDX-License-Identifier: MIT + +import React from 'react'; +import { + Popover, + Icon, +} from 'antd'; + +import { Canvas } from 'cvat-canvas'; +import { TagIcon } from 'icons'; + +import SetupTagPopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover'; + +interface Props { + canvasInstance: Canvas; + isDrawing: boolean; +} + +function SetupTagControl(props: Props): JSX.Element { + const { + isDrawing, + } = props; + + const dynamcPopoverPros = isDrawing ? { + overlayStyle: { + display: 'none', + }, + } : {}; + + return ( + + )} + > + + + ); +} + +export default React.memo(SetupTagControl); diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx new file mode 100644 index 00000000..810b5b5e --- /dev/null +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx @@ -0,0 +1,73 @@ +// Copyright (C) 2020 Intel Corporation +// +// SPDX-License-Identifier: MIT + +import React from 'react'; + +import { + Row, + Col, + Select, + Button, +} from 'antd'; + +import Text from 'antd/lib/typography/Text'; + +interface Props { + labels: any[]; + selectedLabeID: number; + onChangeLabel(value: string): void; + onSetup(): void; +} + +function setupTagPopover(props: Props): JSX.Element { + const { + labels, + selectedLabeID, + onChangeLabel, + onSetup, + } = props; + + return ( +
+ + + Setup tag + + + + + Label + + + + + + + + + + + + +
+ ); +} + +export default React.memo(setupTagPopover); 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 new file mode 100644 index 00000000..c6d42bf3 --- /dev/null +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx @@ -0,0 +1,101 @@ +// Copyright (C) 2020 Intel Corporation +// +// SPDX-License-Identifier: MIT + +import React from 'react'; +import { connect } from 'react-redux'; + +import { + CombinedState, +} from 'reducers/interfaces'; + +import { Canvas } from 'cvat-canvas'; +import SetupTagPopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover'; + +interface DispatchToProps { + onTagSetup(): void; +} + +interface StateToProps { + canvasInstance: Canvas; + labels: any[]; +} + +function mapDispatchToProps(dispatch: any): DispatchToProps { + return { + onTagSetup(): void { + dispatch(); + }, + }; +} + +function mapStateToProps(state: CombinedState): StateToProps { + const { + annotation: { + canvas: { + instance: canvasInstance, + }, + job: { + labels, + }, + }, + } = state; + + return { + canvasInstance, + labels, + }; +} + +type Props = StateToProps; + +interface State { + selectedLabelID: number; +} + +class DrawShapePopoverContainer extends React.PureComponent { + constructor(props: Props) { + super(props); + + const defaultLabelID = props.labels[0].id; + this.state = { + selectedLabelID: defaultLabelID, + }; + } + + private onChangeLabel = (value: string): void => { + this.setState({ + selectedLabelID: +value, + }); + }; + + private onSetup(): void { + const { canvasInstance } = this.props; + + canvasInstance.cancel(); + } + + public render(): JSX.Element { + const { + selectedLabelID, + } = this.state; + + const { + labels, + } = this.props; + + return ( + + ); + } +} + +export default connect( + mapStateToProps, + mapDispatchToProps, +)(DrawShapePopoverContainer); diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts index 644d85d5..0fab4ef5 100644 --- a/cvat-ui/src/reducers/interfaces.ts +++ b/cvat-ui/src/reducers/interfaces.ts @@ -245,6 +245,7 @@ export enum ActiveControl { DRAW_POLYGON = 'draw_polygon', DRAW_POLYLINE = 'draw_polyline', DRAW_POINTS = 'draw_points', + SETUP_TAG = 'setup_tag', MERGE = 'merge', GROUP = 'group', SPLIT = 'split', From f468c4035fe7e9ca24874ade6062a0d98723b553 Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Thu, 5 Mar 2020 13:37:53 +0300 Subject: [PATCH 02/12] Setup tag forward to the state --- cvat-ui/src/actions/annotation-actions.ts | 15 ++++++++++++ .../controls-side-bar/setup-tag-popover.tsx | 6 +++-- .../controls-side-bar/setup-tag-popover.tsx | 23 ++++++++++++++----- cvat-ui/src/reducers/annotation-reducer.ts | 23 +++++++++++++++++++ 4 files changed, 59 insertions(+), 8 deletions(-) diff --git a/cvat-ui/src/actions/annotation-actions.ts b/cvat-ui/src/actions/annotation-actions.ts index bc49fb02..b3d0eabf 100644 --- a/cvat-ui/src/actions/annotation-actions.ts +++ b/cvat-ui/src/actions/annotation-actions.ts @@ -85,6 +85,7 @@ export enum AnnotationActionTypes { EDIT_SHAPE = 'EDIT_SHAPE', DRAW_SHAPE = 'DRAW_SHAPE', SHAPE_DRAWN = 'SHAPE_DRAWN', + SETUP_TAG = 'SETUP_TAG', RESET_CANVAS = 'RESET_CANVAS', UPDATE_ANNOTATIONS_SUCCESS = 'UPDATE_ANNOTATIONS_SUCCESS', UPDATE_ANNOTATIONS_FAILED = 'UPDATE_ANNOTATIONS_FAILED', @@ -855,6 +856,20 @@ export function drawShape( }; } +export function setupTag( + labelID: number, + objectType: ObjectType, +): AnyAction { + return { + type: AnnotationActionTypes.SETUP_TAG, + payload: { + labelID, + objectType, + activeControl: ActiveControl.SETUP_TAG, + }, + }; +} + export function shapeDrawn(): AnyAction { return { type: AnnotationActionTypes.SHAPE_DRAWN, diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx index 810b5b5e..3edaa2aa 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx @@ -17,7 +17,9 @@ interface Props { labels: any[]; selectedLabeID: number; onChangeLabel(value: string): void; - onSetup(): void; + onSetup( + labelID: number, + ): void; } function setupTagPopover(props: Props): JSX.Element { @@ -61,7 +63,7 @@ function setupTagPopover(props: Props): JSX.Element { - 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 c6d42bf3..5714bc0a 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,13 +7,19 @@ import { connect } from 'react-redux'; import { CombinedState, + ObjectType, } from 'reducers/interfaces'; +import { + setupTag +} from 'actions/annotation-actions'; import { Canvas } from 'cvat-canvas'; import SetupTagPopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover'; interface DispatchToProps { - onTagSetup(): void; + onTagSetup( + labelID: number, + ): void; } interface StateToProps { @@ -23,8 +29,10 @@ interface StateToProps { function mapDispatchToProps(dispatch: any): DispatchToProps { return { - onTagSetup(): void { - dispatch(); + onTagSetup( + labelID: number, + ): void { + dispatch(setupTag(labelID, ObjectType.TAG)); }, }; } @@ -47,7 +55,7 @@ function mapStateToProps(state: CombinedState): StateToProps { }; } -type Props = StateToProps; +type Props = StateToProps & DispatchToProps; interface State { selectedLabelID: number; @@ -69,10 +77,11 @@ class DrawShapePopoverContainer extends React.PureComponent { }); }; - private onSetup(): void { - const { canvasInstance } = this.props; + private onSetup(labelID: number): void { + const { canvasInstance, onTagSetup } = this.props; canvasInstance.cancel(); + onTagSetup(labelID); } public render(): JSX.Element { @@ -84,6 +93,8 @@ class DrawShapePopoverContainer extends React.PureComponent { labels, } = this.props; + this.onSetup = this.onSetup.bind(this); + return ( { }, }; } + case AnnotationActionTypes.SETUP_TAG: { + const { + labelID, + objectType, + activeControl, + } = action.payload; + + return { + ...state, + annotations: { + ...state.annotations, + }, + canvas: { + ...state.canvas, + activeControl, + }, + drawing: { + ...defaultState.drawing, + activeLabelID: labelID, + activeObjectType: objectType, + }, + }; + } case AnnotationActionTypes.MERGE_OBJECTS: { const { enabled } = action.payload; const activeControl = enabled From 3199fbbdf9f340aa796aa15771c92d5099323f54 Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Fri, 6 Mar 2020 16:38:15 +0300 Subject: [PATCH 03/12] Added tag support in new UI (without canvas drawing) --- cvat-canvas/src/typescript/canvasView.ts | 44 +++++++++++------- cvat-core/src/annotations-collection.js | 12 +++-- cvat-ui/src/actions/annotation-actions.ts | 38 ++++++++------- .../objects-side-bar/object-item.tsx | 25 +++++++++- .../controls-side-bar/setup-tag-popover.tsx | 46 ++++++++++++++----- .../objects-side-bar/object-item.tsx | 21 +++++++++ cvat-ui/src/reducers/annotation-reducer.ts | 18 +------- cvat-ui/src/reducers/interfaces.ts | 1 - 8 files changed, 137 insertions(+), 68 deletions(-) diff --git a/cvat-canvas/src/typescript/canvasView.ts b/cvat-canvas/src/typescript/canvasView.ts index 63b26e1d..846ac454 100644 --- a/cvat-canvas/src/typescript/canvasView.ts +++ b/cvat-canvas/src/typescript/canvasView.ts @@ -399,8 +399,11 @@ export class CanvasViewImpl implements CanvasView, Listener { this.svgTexts[state.clientID].remove(); } - this.svgShapes[state.clientID].off('click.canvas'); - this.svgShapes[state.clientID].remove(); + const shape = this.svgShapes[state.clientID]; + if (shape) { + shape.off('click.canvas'); + shape.remove(); + } delete this.drawnStates[state.clientID]; } @@ -847,7 +850,7 @@ export class CanvasViewImpl implements CanvasView, Listener { hidden: state.hidden, lock: state.lock, shapeType: state.shapeType, - points: [...state.points], + points: Array.isArray(state.points) ? [...state.points] : [], attributes: { ...state.attributes }, zOrder: state.zOrder, pinned: state.pinned, @@ -892,7 +895,7 @@ export class CanvasViewImpl implements CanvasView, Listener { this.activate(activeElement); } - if (state.points + if (state.points && state.points .some((p: number, id: number): boolean => p !== drawnState.points[id]) ) { const translatedPoints: number[] = translate(state.points); @@ -1021,22 +1024,24 @@ export class CanvasViewImpl implements CanvasView, Listener { const drawnState = this.drawnStates[clientID]; const shape = this.svgShapes[clientID]; - shape.removeClass('cvat_canvas_shape_activated'); + 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); - } + if (!drawnState.pinned) { + (shape as any).off('dragstart'); + (shape as any).off('dragend'); + (shape as any).draggable(false); + } - if (drawnState.shapeType !== 'points') { - this.selectize(false, shape); - } + 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); + (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]; @@ -1085,6 +1090,11 @@ 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 759980db..0c5b35fd 100644 --- a/cvat-core/src/annotations-collection.js +++ b/cvat-core/src/annotations-collection.js @@ -810,11 +810,13 @@ 'The object has not been saved yet. Call annotations.put([state]) before', ); } - - const distance = object.constructor.distance(state.points, x, y); - if (distance !== null && (minimumDistance === null || distance < minimumDistance)) { - minimumDistance = distance; - minimumState = state; + if (!(object instanceof Tag)) { + const distance = object.constructor.distance(state.points, x, y); + if (distance !== null && (minimumDistance === null + || distance < minimumDistance)) { + minimumDistance = distance; + minimumState = state; + } } } diff --git a/cvat-ui/src/actions/annotation-actions.ts b/cvat-ui/src/actions/annotation-actions.ts index b3d0eabf..9a265752 100644 --- a/cvat-ui/src/actions/annotation-actions.ts +++ b/cvat-ui/src/actions/annotation-actions.ts @@ -85,7 +85,6 @@ export enum AnnotationActionTypes { EDIT_SHAPE = 'EDIT_SHAPE', DRAW_SHAPE = 'DRAW_SHAPE', SHAPE_DRAWN = 'SHAPE_DRAWN', - SETUP_TAG = 'SETUP_TAG', RESET_CANVAS = 'RESET_CANVAS', UPDATE_ANNOTATIONS_SUCCESS = 'UPDATE_ANNOTATIONS_SUCCESS', UPDATE_ANNOTATIONS_FAILED = 'UPDATE_ANNOTATIONS_FAILED', @@ -526,10 +525,31 @@ export function editShape(enabled: boolean): AnyAction { } export function copyShape(objectState: any): AnyAction { + const state = getStore().getState(); + + state.annotation.canvas.instance.cancel(); + if (objectState.objectType !== ObjectType.TAG) { + state.annotation.canvas.instance.draw({ + enabled: true, + initialState: objectState, + }); + } + + let activeControl = ActiveControl.CURSOR; + if (objectState.shapeType === ShapeType.RECTANGLE) { + activeControl = ActiveControl.DRAW_RECTANGLE; + } else if (objectState.shapeType === ShapeType.POINTS) { + activeControl = ActiveControl.DRAW_POINTS; + } else if (objectState.shapeType === ShapeType.POLYGON) { + activeControl = ActiveControl.DRAW_POLYGON; + } else if (objectState.shapeType === ShapeType.POLYLINE) { + activeControl = ActiveControl.DRAW_POLYLINE; + } + return { type: AnnotationActionTypes.COPY_SHAPE, payload: { - objectState, + activeControl, }, }; } @@ -856,20 +876,6 @@ export function drawShape( }; } -export function setupTag( - labelID: number, - objectType: ObjectType, -): AnyAction { - return { - type: AnnotationActionTypes.SETUP_TAG, - payload: { - labelID, - objectType, - activeControl: ActiveControl.SETUP_TAG, - }, - }; -} - export function shapeDrawn(): AnyAction { return { type: AnnotationActionTypes.SHAPE_DRAWN, diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx index 284fc613..ce0f69db 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx @@ -43,6 +43,7 @@ import { function ItemMenu( serverID: number | undefined, locked: boolean, + objectType: ObjectType, copy: (() => void), remove: (() => void), propagate: (() => void), @@ -68,13 +69,13 @@ function ItemMenu( - - @@ -109,6 +110,7 @@ interface ItemTopComponentProps { serverID: number | undefined; labelID: number; labels: any[]; + objectType: ObjectType; type: string; locked: boolean; changeLabel(labelID: string): void; @@ -126,6 +128,7 @@ function ItemTopComponent(props: ItemTopComponentProps): JSX.Element { serverID, labelID, labels, + objectType, type, locked, changeLabel, @@ -159,6 +162,7 @@ function ItemTopComponent(props: ItemTopComponentProps): JSX.Element { overlay={ItemMenu( serverID, locked, + objectType, copy, remove, propagate, @@ -302,6 +306,22 @@ function ItemButtonsComponent(props: ItemButtonsComponentProps): JSX.Element { ); } + if (objectType === ObjectType.TAG) { + return ( + + + + + { locked + ? + : } + + + + + ); + } + return ( @@ -726,6 +746,7 @@ function ObjectItemComponent(props: Props): JSX.Element { clientID={clientID} labelID={labelID} labels={labels} + objectType={objectType} type={type} locked={locked} changeLabel={changeLabel} 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 5714bc0a..03e9bff5 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 @@ -11,28 +11,28 @@ import { } from 'reducers/interfaces'; import { - setupTag + createAnnotationsAsync, } from 'actions/annotation-actions'; import { Canvas } from 'cvat-canvas'; import SetupTagPopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover'; +import getCore from 'cvat-core'; +const cvat = getCore(); interface DispatchToProps { - onTagSetup( - labelID: number, - ): void; + onCreateAnnotations(sessionInstance: any, frame: number, states: any[]): void; } interface StateToProps { canvasInstance: Canvas; + jobInstance: any; labels: any[]; + frame: number; } function mapDispatchToProps(dispatch: any): DispatchToProps { return { - onTagSetup( - labelID: number, - ): void { - dispatch(setupTag(labelID, ObjectType.TAG)); + onCreateAnnotations(sessionInstance: any, frame: number, states: any[]): void { + dispatch(createAnnotationsAsync(sessionInstance, frame, states)); }, }; } @@ -45,13 +45,21 @@ function mapStateToProps(state: CombinedState): StateToProps { }, job: { labels, + instance: jobInstance, + }, + player: { + frame: { + number: frame, + }, }, }, } = state; return { canvasInstance, + jobInstance, labels, + frame, }; } @@ -77,11 +85,27 @@ class DrawShapePopoverContainer extends React.PureComponent { }); }; - private onSetup(labelID: number): void { - const { canvasInstance, onTagSetup } = this.props; + private onSetup(): void { + const { + canvasInstance, + onCreateAnnotations, + jobInstance, + frame, + } = this.props; + + const { selectedLabelID } = this.state; canvasInstance.cancel(); - onTagSetup(labelID); + + const state = { + objectType: ObjectType.TAG, + label: jobInstance.task.labels + .filter((label: any) => label.id === selectedLabelID)[0], + frame, + + }; + const objectState = new cvat.classes.ObjectState(state); + onCreateAnnotations(jobInstance, frame, [objectState]); } public render(): JSX.Element { diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/object-item.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/object-item.tsx index 6ced5702..0723f438 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/object-item.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/object-item.tsx @@ -9,10 +9,12 @@ import { ActiveControl, CombinedState, ColorBy, + ObjectType, } from 'reducers/interfaces'; import { collapseObjectItems, changeLabelColorAsync, + createAnnotationsAsync, updateAnnotationsAsync, changeFrameAsync, removeObjectAsync, @@ -23,6 +25,9 @@ import { } from 'actions/annotation-actions'; import ObjectStateItemComponent from 'components/annotation-page/standard-workspace/objects-side-bar/object-item'; +import getCore from 'cvat-core'; + +const cvat = getCore(); interface OwnProps { clientID: number; @@ -47,6 +52,7 @@ interface StateToProps { interface DispatchToProps { changeFrame(frame: number): void; updateState(sessionInstance: any, frameNumber: number, objectState: any): void; + createAnnotations(sessionInstance: any, frameNumber: number, state: any): void collapseOrExpand(objectStates: any[], collapsed: boolean): void; activateObject: (activatedStateID: number | null) => void; removeObject: (sessionInstance: any, objectState: any) => void; @@ -123,6 +129,9 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { updateState(sessionInstance: any, frameNumber: number, state: any): void { dispatch(updateAnnotationsAsync(sessionInstance, frameNumber, [state])); }, + createAnnotations(sessionInstance: any, frameNumber: number, state: any): void { + dispatch(createAnnotationsAsync(sessionInstance, frameNumber, state)); + }, collapseOrExpand(objectStates: any[], collapsed: boolean): void { dispatch(collapseObjectItems(objectStates, collapsed)); }, @@ -215,9 +224,21 @@ class ObjectItemContainer extends React.PureComponent { const { objectState, copyShape, + jobInstance, + frameNumber, + createAnnotations, } = this.props; copyShape(objectState); + if (objectState.objectType === ObjectType.TAG) { + const state = new cvat.classes.ObjectState({ + objectType: objectState.objectType, + label: objectState.label, + frame: frameNumber, + + }); + createAnnotations(jobInstance, frameNumber, [state]); + } }; private propagate = (): void => { diff --git a/cvat-ui/src/reducers/annotation-reducer.ts b/cvat-ui/src/reducers/annotation-reducer.ts index 27697cb5..3a8776ae 100644 --- a/cvat-ui/src/reducers/annotation-reducer.ts +++ b/cvat-ui/src/reducers/annotation-reducer.ts @@ -429,6 +429,7 @@ export default (state = defaultState, action: AnyAction): AnnotationState => { ...state, annotations: { ...state.annotations, + activatedStateID: null, }, canvas: { ...state.canvas, @@ -678,24 +679,9 @@ export default (state = defaultState, action: AnyAction): AnnotationState => { } case AnnotationActionTypes.COPY_SHAPE: { const { - objectState, + activeControl, } = action.payload; - state.canvas.instance.cancel(); - state.canvas.instance.draw({ - enabled: true, - initialState: objectState, - }); - - let activeControl = ActiveControl.DRAW_RECTANGLE; - if (objectState.shapeType === ShapeType.POINTS) { - activeControl = ActiveControl.DRAW_POINTS; - } else if (objectState.shapeType === ShapeType.POLYGON) { - activeControl = ActiveControl.DRAW_POLYGON; - } else if (objectState.shapeType === ShapeType.POLYLINE) { - activeControl = ActiveControl.DRAW_POLYLINE; - } - return { ...state, canvas: { diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts index 0fab4ef5..644d85d5 100644 --- a/cvat-ui/src/reducers/interfaces.ts +++ b/cvat-ui/src/reducers/interfaces.ts @@ -245,7 +245,6 @@ export enum ActiveControl { DRAW_POLYGON = 'draw_polygon', DRAW_POLYLINE = 'draw_polyline', DRAW_POINTS = 'draw_points', - SETUP_TAG = 'setup_tag', MERGE = 'merge', GROUP = 'group', SPLIT = 'split', From 4746574ff197cd265a3b1cc904bf8a99e13ecf59 Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Fri, 6 Mar 2020 16:48:57 +0300 Subject: [PATCH 04/12] merge fix --- cvat-ui/src/reducers/annotation-reducer.ts | 24 ---------------------- 1 file changed, 24 deletions(-) diff --git a/cvat-ui/src/reducers/annotation-reducer.ts b/cvat-ui/src/reducers/annotation-reducer.ts index fb4669c8..d5de5f60 100644 --- a/cvat-ui/src/reducers/annotation-reducer.ts +++ b/cvat-ui/src/reducers/annotation-reducer.ts @@ -422,30 +422,6 @@ export default (state = defaultState, action: AnyAction): AnnotationState => { }, }; } - case AnnotationActionTypes.SETUP_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.REPEAT_DRAW_SHAPE: { const { activeControl } = action.payload; From 8602da72f16fcc4e337664479f819b2a3e397f97 Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Fri, 6 Mar 2020 17:27:36 +0300 Subject: [PATCH 05/12] Fixed copying/pasting actions --- cvat-ui/src/actions/annotation-actions.ts | 61 ++++++++++--------- cvat-ui/src/base.scss | 1 + .../objects-side-bar/object-item.tsx | 36 ++++++----- .../objects-side-bar/styles.scss | 1 + .../objects-side-bar/object-item.tsx | 12 ---- 5 files changed, 56 insertions(+), 55 deletions(-) diff --git a/cvat-ui/src/actions/annotation-actions.ts b/cvat-ui/src/actions/annotation-actions.ts index be23e67f..f0208701 100644 --- a/cvat-ui/src/actions/annotation-actions.ts +++ b/cvat-ui/src/actions/annotation-actions.ts @@ -542,31 +542,10 @@ export function editShape(enabled: boolean): AnyAction { } export function copyShape(objectState: any): AnyAction { - const state = getStore().getState(); - - state.annotation.canvas.instance.cancel(); - if (objectState.objectType !== ObjectType.TAG) { - state.annotation.canvas.instance.draw({ - enabled: true, - initialState: objectState, - }); - } - - let activeControl = ActiveControl.CURSOR; - if (objectState.shapeType === ShapeType.RECTANGLE) { - activeControl = ActiveControl.DRAW_RECTANGLE; - } else if (objectState.shapeType === ShapeType.POINTS) { - activeControl = ActiveControl.DRAW_POINTS; - } else if (objectState.shapeType === ShapeType.POLYGON) { - activeControl = ActiveControl.DRAW_POLYGON; - } else if (objectState.shapeType === ShapeType.POLYLINE) { - activeControl = ActiveControl.DRAW_POLYLINE; - } - return { type: AnnotationActionTypes.COPY_SHAPE, payload: { - activeControl, + objectState, }, }; } @@ -1175,11 +1154,25 @@ export function searchAnnotationsAsync( export function pasteShapeAsync(): ThunkAction, {}, {}, AnyAction> { return async (dispatch: ActionCreator): Promise => { const initialState = getStore().getState().annotation.drawing.activeInitialState; - const { instance: canvasInstance } = getStore().getState().annotation.canvas; + const { + canvas: { + instance: canvasInstance, + }, + job: { + instance: jobInstance, + }, + player: { + frame: { + number: frameNumber, + }, + }, + } = getStore().getState().annotation; if (initialState) { - let activeControl = ActiveControl.DRAW_RECTANGLE; - if (initialState.shapeType === ShapeType.POINTS) { + let activeControl = ActiveControl.CURSOR; + if (initialState.shapeType === ShapeType.RECTANGLE) { + activeControl = ActiveControl.DRAW_RECTANGLE; + } else if (initialState.shapeType === ShapeType.POINTS) { activeControl = ActiveControl.DRAW_POINTS; } else if (initialState.shapeType === ShapeType.POLYGON) { activeControl = ActiveControl.DRAW_POLYGON; @@ -1195,10 +1188,20 @@ export function pasteShapeAsync(): ThunkAction, {}, {}, AnyAction> }); canvasInstance.cancel(); - canvasInstance.draw({ - enabled: true, - initialState, - }); + if (initialState.objectType === ObjectType.TAG) { + const state = new cvat.classes.ObjectState({ + objectType: initialState.objectType, + label: initialState.label, + frame: frameNumber, + + }); + dispatch(createAnnotationsAsync(jobInstance, frameNumber, [state])); + } else { + canvasInstance.draw({ + enabled: true, + initialState, + }); + } } }; } diff --git a/cvat-ui/src/base.scss b/cvat-ui/src/base.scss index 6f545305..99649cf4 100644 --- a/cvat-ui/src/base.scss +++ b/cvat-ui/src/base.scss @@ -22,6 +22,7 @@ $info-icon-color: #0074D9; $objects-bar-tabs-color: #BEBEBE; $objects-bar-icons-color: #242424; // #6E6E6E $active-object-item-background-color: #D8ECFF; +$default-object-colorpicker-item-background-color: #D8D8D8; $slider-color: #1890FF; $monospaced-fonts-stack: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx index ce0f69db..fbe21a8d 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx @@ -719,21 +719,29 @@ function ObjectItemComponent(props: Props): JSX.Element { return (
- + )} + > +
+ + ) : ( +
- )} - > -
- + ) + }
{ const { objectState, copyShape, - jobInstance, - frameNumber, - createAnnotations, } = this.props; copyShape(objectState); - if (objectState.objectType === ObjectType.TAG) { - const state = new cvat.classes.ObjectState({ - objectType: objectState.objectType, - label: objectState.label, - frame: frameNumber, - - }); - createAnnotations(jobInstance, frameNumber, [state]); - } }; private propagate = (): void => { From c85ecb7bf3c9781c3262817939084cdfa0a46987 Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Fri, 6 Mar 2020 17:59:34 +0300 Subject: [PATCH 06/12] Deleted unused objects --- .../standard-workspace/objects-side-bar/object-item.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/object-item.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/object-item.tsx index 9a9382d6..d3f55c45 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/object-item.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/object-item.tsx @@ -9,7 +9,6 @@ import { ActiveControl, CombinedState, ColorBy, - ObjectType, } from 'reducers/interfaces'; import { collapseObjectItems, @@ -26,9 +25,7 @@ import { } from 'actions/annotation-actions'; import ObjectStateItemComponent from 'components/annotation-page/standard-workspace/objects-side-bar/object-item'; -import getCore from 'cvat-core'; -const cvat = getCore(); interface OwnProps { clientID: number; @@ -53,7 +50,7 @@ interface StateToProps { interface DispatchToProps { changeFrame(frame: number): void; updateState(sessionInstance: any, frameNumber: number, objectState: any): void; - createAnnotations(sessionInstance: any, frameNumber: number, state: any): void + createAnnotations(sessionInstance: any, frameNumber: number, state: any): void; collapseOrExpand(objectStates: any[], collapsed: boolean): void; activateObject: (activatedStateID: number | null) => void; removeObject: (sessionInstance: any, objectState: any) => void; From a99dd38fee470e89237485cd10291a74a228baba Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Tue, 10 Mar 2020 18:58:22 +0300 Subject: [PATCH 07/12] Fix copying and creating tags --- cvat-ui/src/actions/annotation-actions.ts | 94 ++++++++++++++----- .../controls-side-bar/setup-tag-popover.tsx | 36 ++----- .../objects-side-bar/objects-list.tsx | 4 +- cvat-ui/src/reducers/annotation-reducer.ts | 24 +++++ 4 files changed, 100 insertions(+), 58 deletions(-) diff --git a/cvat-ui/src/actions/annotation-actions.ts b/cvat-ui/src/actions/annotation-actions.ts index f0208701..6f901cb7 100644 --- a/cvat-ui/src/actions/annotation-actions.ts +++ b/cvat-ui/src/actions/annotation-actions.ts @@ -138,6 +138,7 @@ export enum AnnotationActionTypes { SWITCH_Z_LAYER = 'SWITCH_Z_LAYER', ADD_Z_LAYER = 'ADD_Z_LAYER', SEARCH_ANNOTATIONS_FAILED = 'SEARCH_ANNOTATIONS_FAILED', + ADD_TAG = 'ADD_TAG', } export function addZLayer(): AnyAction { @@ -1151,9 +1152,11 @@ export function searchAnnotationsAsync( }; } -export function pasteShapeAsync(): ThunkAction, {}, {}, AnyAction> { +export function addTagAsync( + labelID: number, + frame: number, +): ThunkAction, {}, {}, AnyAction> { return async (dispatch: ActionCreator): Promise => { - const initialState = getStore().getState().annotation.drawing.activeInitialState; const { canvas: { instance: canvasInstance, @@ -1161,6 +1164,35 @@ export function pasteShapeAsync(): ThunkAction, {}, {}, AnyAction> 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, @@ -1189,13 +1221,7 @@ export function pasteShapeAsync(): ThunkAction, {}, {}, AnyAction> canvasInstance.cancel(); if (initialState.objectType === ObjectType.TAG) { - const state = new cvat.classes.ObjectState({ - objectType: initialState.objectType, - label: initialState.label, - frame: frameNumber, - - }); - dispatch(createAnnotationsAsync(jobInstance, frameNumber, [state])); + dispatch(addTagAsync(initialState.label.id, frameNumber)); } else { canvasInstance.draw({ enabled: true, @@ -1209,20 +1235,32 @@ export function pasteShapeAsync(): ThunkAction, {}, {}, AnyAction> export function repeatDrawShapeAsync(): ThunkAction, {}, {}, AnyAction> { return async (dispatch: ActionCreator): Promise => { const { - activeShapeType, - activeNumOfPoints, - activeRectDrawingMethod, - } = getStore().getState().annotation.drawing; - - const { instance: canvasInstance } = getStore().getState().annotation.canvas; + canvas: { + instance: canvasInstance, + }, + player: { + frame: { + number: frameNumber, + }, + }, + drawing: { + activeObjectType, + activeLabelID, + activeShapeType, + activeNumOfPoints, + activeRectDrawingMethod, + }, + } = getStore().getState().annotation; - let activeControl = ActiveControl.DRAW_RECTANGLE; - if (activeShapeType === ShapeType.POLYGON) { + let activeControl = ActiveControl.CURSOR; + if (activeShapeType === ShapeType.RECTANGLE) { + activeControl = ActiveControl.DRAW_RECTANGLE; + } else if (activeShapeType === ShapeType.POINTS) { + activeControl = ActiveControl.DRAW_POINTS; + } else if (activeShapeType === ShapeType.POLYGON) { activeControl = ActiveControl.DRAW_POLYGON; } else if (activeShapeType === ShapeType.POLYLINE) { activeControl = ActiveControl.DRAW_POLYLINE; - } else if (activeShapeType === ShapeType.POINTS) { - activeControl = ActiveControl.DRAW_POINTS; } dispatch({ @@ -1233,12 +1271,16 @@ export function repeatDrawShapeAsync(): ThunkAction, {}, {}, AnyAc }); canvasInstance.cancel(); - canvasInstance.draw({ - enabled: true, - rectDrawingMethod: activeRectDrawingMethod, - numberOfPoints: activeNumOfPoints, - shapeType: activeShapeType, - crosshair: activeShapeType === ShapeType.RECTANGLE, - }); + if (activeObjectType === ObjectType.TAG) { + dispatch(addTagAsync(activeLabelID, frameNumber)); + } else { + canvasInstance.draw({ + enabled: true, + rectDrawingMethod: activeRectDrawingMethod, + numberOfPoints: activeNumOfPoints, + shapeType: activeShapeType, + crosshair: activeShapeType === ShapeType.RECTANGLE, + }); + } }; } 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 03e9bff5..d31d1e7e 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,32 +7,26 @@ import { connect } from 'react-redux'; import { CombinedState, - ObjectType, } from 'reducers/interfaces'; import { - createAnnotationsAsync, + addTagAsync, } from 'actions/annotation-actions'; -import { Canvas } from 'cvat-canvas'; import SetupTagPopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover'; -import getCore from 'cvat-core'; -const cvat = getCore(); interface DispatchToProps { - onCreateAnnotations(sessionInstance: any, frame: number, states: any[]): void; + onAddTag(labelID: number, frame: number): void; } interface StateToProps { - canvasInstance: Canvas; - jobInstance: any; labels: any[]; frame: number; } function mapDispatchToProps(dispatch: any): DispatchToProps { return { - onCreateAnnotations(sessionInstance: any, frame: number, states: any[]): void { - dispatch(createAnnotationsAsync(sessionInstance, frame, states)); + onAddTag(labelID: number, frame: number): void { + dispatch(addTagAsync(labelID, frame)); }, }; } @@ -40,12 +34,8 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { function mapStateToProps(state: CombinedState): StateToProps { const { annotation: { - canvas: { - instance: canvasInstance, - }, job: { labels, - instance: jobInstance, }, player: { frame: { @@ -56,8 +46,6 @@ function mapStateToProps(state: CombinedState): StateToProps { } = state; return { - canvasInstance, - jobInstance, labels, frame, }; @@ -87,25 +75,13 @@ class DrawShapePopoverContainer extends React.PureComponent { private onSetup(): void { const { - canvasInstance, - onCreateAnnotations, - jobInstance, frame, + onAddTag, } = this.props; const { selectedLabelID } = this.state; - canvasInstance.cancel(); - - const state = { - objectType: ObjectType.TAG, - label: jobInstance.task.labels - .filter((label: any) => label.id === selectedLabelID)[0], - frame, - - }; - const objectState = new cvat.classes.ObjectState(state); - onCreateAnnotations(jobInstance, frame, [objectState]); + onAddTag(selectedLabelID, frame); } public render(): JSX.Element { diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/objects-list.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/objects-list.tsx index 8bc18e0f..6edc95ca 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/objects-list.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/objects-list.tsx @@ -462,14 +462,14 @@ class ObjectsListContainer extends React.PureComponent { COPY_SHAPE: (event: KeyboardEvent | undefined) => { preventDefault(event); const state = activatedStated(); - if (state && state.objectType !== ObjectType.TAG) { + if (state) { copyShape(state); } }, PROPAGATE_OBJECT: (event: KeyboardEvent | undefined) => { preventDefault(event); const state = activatedStated(); - if (state && state.objectType !== ObjectType.TAG) { + if (state) { propagateObject(state); } }, diff --git a/cvat-ui/src/reducers/annotation-reducer.ts b/cvat-ui/src/reducers/annotation-reducer.ts index d5de5f60..07298373 100644 --- a/cvat-ui/src/reducers/annotation-reducer.ts +++ b/cvat-ui/src/reducers/annotation-reducer.ts @@ -437,6 +437,30 @@ 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 From 8b27dbe61327845ce8cddf733c0f557b41d4a81e Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Wed, 11 Mar 2020 14:16:55 +0300 Subject: [PATCH 08/12] Fixed tags color changing and hiding --- cvat-core/src/annotations-objects.js | 5 +++ .../objects-side-bar/object-item.tsx | 37 +++++++------------ .../objects-side-bar/objects-list.tsx | 4 +- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/cvat-core/src/annotations-objects.js b/cvat-core/src/annotations-objects.js index 65a30b56..245d8e37 100644 --- a/cvat-core/src/annotations-objects.js +++ b/cvat-core/src/annotations-objects.js @@ -1139,6 +1139,7 @@ attributes: { ...this.attributes }, label: this.label, group: this.groupObject, + color: this.color, updated: this.updated, frame, }; @@ -1171,6 +1172,10 @@ this._saveLock(data.lock); } + if (updated.color) { + this._saveColor(data.color); + } + this.updateTimestamp(updated); updated.reset(); diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx index fbe21a8d..72e2d0e6 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx @@ -719,30 +719,21 @@ function ObjectItemComponent(props: Props): JSX.Element { return (
- { - objectType !== ObjectType.TAG ? ( - - )} - > -
- - ) : ( -
- ) - } - + )} + > +
+
{ const { clientID, lock } = objectState; if (!lock) { - statesHidden = statesHidden && objectState.hidden; + if (objectState.objectType !== ObjectType.TAG) { + statesHidden = statesHidden && objectState.hidden; + } statesLocked = statesLocked && objectState.lock; } const stateCollapsed = clientID in collapsed ? collapsed[clientID] : true; From 89628fbac53cccb63206e3e86c0f519f3f7c851a Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Wed, 11 Mar 2020 14:52:45 +0300 Subject: [PATCH 09/12] Fixed filters with tags --- cvat-core/src/annotations-filter.js | 25 +++++++++-------- .../objects-side-bar/object-item.tsx | 28 +++++++++++-------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/cvat-core/src/annotations-filter.js b/cvat-core/src/annotations-filter.js index 62530167..903067bc 100644 --- a/cvat-core/src/annotations-filter.js +++ b/cvat-core/src/annotations-filter.js @@ -165,18 +165,21 @@ class AnnotationsFilter { let xbr = Number.MIN_SAFE_INTEGER; let ytl = Number.MAX_SAFE_INTEGER; let ybr = Number.MIN_SAFE_INTEGER; + let [width, height] = [null, null]; + + if (state.objectType !== 'tag') { + state.points.forEach((coord, idx) => { + if (idx % 2) { // y + ytl = Math.min(ytl, coord); + ybr = Math.max(ybr, coord); + } else { // x + xtl = Math.min(xtl, coord); + xbr = Math.max(xbr, coord); + } + }); + [width, height] = [xbr - xtl, ybr - ytl]; + } - state.points.forEach((coord, idx) => { - if (idx % 2) { // y - ytl = Math.min(ytl, coord); - ybr = Math.max(ybr, coord); - } else { // x - xtl = Math.min(xtl, coord); - xbr = Math.max(xbr, coord); - } - }); - - const [width, height] = [xbr - xtl, ybr - ytl]; const attributes = {}; Object.keys(state.attributes).reduce((acc, key) => { const attr = labelAttributes[key]; diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx index 72e2d0e6..dc7952cf 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx @@ -68,18 +68,22 @@ function ItemMenu( Propagate - - - - - - + { objectType !== ObjectType.TAG && ( + <> + + + + + + + + )}