CVAT-3D Milestone2 (#2645)
* CVAT-3D Updated the Mime Types with Bin Support, added dependency of open3D * CVAT-3D Added additional column as Dimension for engine_task table and created a relatedfiles table for PCD to Image mapping. * Added Support for 3D file Upload in BIN and PCD. * Added Dimension attribute defaulting to 2D for importer and exporter. * Added props passing for dimension attribute, filtering of import, Migration Scripts and Dimension attribute for MpegChunk Writers * Modified code as per review comments * Updated Unit test cases for 3D task creation * Refactored Dimension Enum in UI and backend code * Resolving conflicts * Updated Unit Test Case * Refactored TaskDimension to DimensionType, Simplified usage of Dimension accross classes * Removing manually created test files * Removing old pcd mime-type mapping * Added test files generated by synthetic data using open3d * Merged with develop branch latest changes * Added libraries required for open3d * Added files * Added synthethic pcd,bin and img test files * Modified test file name * Trigger travis ci * Modified test case to ignore 3D preview images * Trigger notification * Deleting DS Store files * Modified test cases as per review comments * Checking pre-commit hook * Fixed Lint issues - precommit hook verification * Added changes for CVAT-3D Milestone2 changes - Frame Navigation, photo context hide and show * Modified changes * Added canvas3D for 3D Perspective * Added missing files * Added code to get image context for 3D view * Codacy check for stylesheet * Modified frame navigantion for 3D View * Modified style for context-image * Trigger notification * Added Support for 3D file Upload in BIN and PCD. * Added props passing for dimension attribute, filtering of import, Migration Scripts and Dimension attribute for MpegChunk Writers * Modified code as per review comments * Refactored Dimension Enum in UI and backend code * Merged with develop branch latest changes * Added files * Added changes for CVAT-3D Milestone2 changes - Frame Navigation, photo context hide and show * Modified changes * Added canvas3D for 3D Perspective * Added missing files * Added code to get image context for 3D view * Codacy check for stylesheet * Modified frame navigantion for 3D View * Modified style for context-image * Changed cvat-data lint issues * Modified to use opencv as per review comments * Removed unwanted imports * Fixed css and added usage of hooks * Merged Develop branch code * Removed unused data structures * Removed unused data structures * Refactored unused data structures * Added three js dependency in cvat ui package-lock.json * Merged develop branch code and refactored code * Fixed snyk issue * Modified Camera Icon in photo-context * Update icons.tsx * Remove unused svg file * Modified changelog file Co-authored-by: cdp <cdp123>main
parent
71e2ddbb59
commit
5c67846c20
@ -0,0 +1 @@
|
||||
webpack.config.js
|
||||
@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
module.exports = {
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser',
|
||||
ecmaVersion: 6,
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'import'],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'airbnb-typescript/base',
|
||||
'plugin:import/errors',
|
||||
'plugin:import/warnings',
|
||||
'plugin:import/typescript',
|
||||
],
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 0,
|
||||
'@typescript-eslint/indent': ['warn', 4],
|
||||
'no-plusplus': 0,
|
||||
'no-restricted-syntax': [
|
||||
0,
|
||||
{
|
||||
selector: 'ForOfStatement',
|
||||
},
|
||||
],
|
||||
'max-len': ['error', { code: 120 }],
|
||||
'no-continue': 0,
|
||||
'func-names': 0,
|
||||
'no-console': 0, // this rule deprecates console.log, console.warn etc. because 'it is not good in production code'
|
||||
'lines-between-class-members': 0,
|
||||
'import/prefer-default-export': 0, // works incorrect with interfaces
|
||||
'newline-per-chained-call': 0, // makes code uglier
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: {
|
||||
extensions: ['.ts', '.js', '.json'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -0,0 +1 @@
|
||||
dist
|
||||
@ -0,0 +1,50 @@
|
||||
# Module CVAT-CANVAS-3D
|
||||
|
||||
## Description
|
||||
|
||||
The CVAT module written in TypeScript language.
|
||||
It presents a canvas to viewing, drawing and editing of 3D annotations.
|
||||
|
||||
## Versioning
|
||||
|
||||
If you make changes in this package, please do following:
|
||||
|
||||
- After not important changes (typos, backward compatible bug fixes, refactoring) do: `npm version patch`
|
||||
- After changing API (backward compatible new features) do: `npm version minor`
|
||||
- After changing API (changes that break backward compatibility) do: `npm version major`
|
||||
|
||||
## Commands
|
||||
|
||||
- Building of the module from sources in the `dist` directory:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npm run build -- --mode=development # without a minification
|
||||
```
|
||||
|
||||
### API Methods
|
||||
|
||||
```ts
|
||||
interface Canvas3d {
|
||||
html(): HTMLDivElement;
|
||||
setup(frameData: any): void;
|
||||
fitCanvas(): void;
|
||||
mode(): Mode;
|
||||
isAbleToChangeFrame(): boolean;
|
||||
render(): void;
|
||||
}
|
||||
```
|
||||
|
||||
### WEB
|
||||
|
||||
```js
|
||||
// Create an instance of a canvas
|
||||
const canvas = new window.canvas.Canvas3d();
|
||||
|
||||
console.log('Version ', window.canvas.CanvasVersion);
|
||||
console.log('Current mode is ', window.canvas.mode());
|
||||
|
||||
// Put canvas to a html container
|
||||
htmlContainer.appendChild(canvas.html());
|
||||
canvas.fitCanvas();
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "cvat-canvas3d",
|
||||
"version": "0.0.1",
|
||||
"description": "Part of Computer Vision Annotation Tool which presents its canvas3D library",
|
||||
"main": "src/canvas3d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc && webpack --config ./webpack.config.js",
|
||||
"server": "nodemon --watch config --exec 'webpack-dev-server --config ./webpack.config.js --mode=development --open'"
|
||||
},
|
||||
"author": "Intel",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.5.5",
|
||||
"@babel/core": "^7.5.5",
|
||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.11.0",
|
||||
"@babel/preset-env": "^7.5.5",
|
||||
"@babel/preset-typescript": "^7.3.3",
|
||||
"@types/node": "^12.6.8",
|
||||
"@typescript-eslint/eslint-plugin": "^1.13.0",
|
||||
"@typescript-eslint/parser": "^1.13.0",
|
||||
"babel-loader": "^8.0.6",
|
||||
"css-loader": "^3.4.2",
|
||||
"dts-bundle-webpack": "^1.0.2",
|
||||
"eslint": "^6.1.0",
|
||||
"eslint-config-airbnb-typescript": "^4.0.1",
|
||||
"eslint-config-typescript-recommended": "^1.4.17",
|
||||
"eslint-plugin-import": "^2.18.2",
|
||||
"node-sass": "^4.14.1",
|
||||
"nodemon": "^1.19.4",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
"sass-loader": "^8.0.2",
|
||||
"style-loader": "^1.0.0",
|
||||
"typescript": "^3.5.3",
|
||||
"webpack": "^4.44.2",
|
||||
"webpack-cli": "^3.3.6",
|
||||
"webpack-dev-server": "^3.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"three": "^0.125.0"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
module.exports = {
|
||||
parser: false,
|
||||
plugins: {
|
||||
'postcss-preset-env': {
|
||||
browsers: '> 2.5%', // https://github.com/browserslist/browserslist
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import pjson from '../../package.json';
|
||||
import { Canvas3dController, Canvas3dControllerImpl } from './canvas3dController';
|
||||
import { Canvas3dModel, Canvas3dModelImpl, Mode } from './canvas3dModel';
|
||||
import { Canvas3dView, Canvas3dViewImpl } from './canvas3dView';
|
||||
import { Master } from './master';
|
||||
|
||||
const Canvas3dVersion = pjson.version;
|
||||
|
||||
interface Canvas3d {
|
||||
html(): any;
|
||||
setup(frameData: any): void;
|
||||
isAbleToChangeFrame(): boolean;
|
||||
fitCanvas(): void;
|
||||
mode(): Mode;
|
||||
render(): void;
|
||||
}
|
||||
|
||||
class Canvas3dImpl implements Canvas3d {
|
||||
private model: Canvas3dModel & Master;
|
||||
private controller: Canvas3dController;
|
||||
private view: Canvas3dView;
|
||||
|
||||
public constructor() {
|
||||
this.model = new Canvas3dModelImpl();
|
||||
this.controller = new Canvas3dControllerImpl(this.model);
|
||||
this.view = new Canvas3dViewImpl(this.model, this.controller);
|
||||
}
|
||||
|
||||
public html(): any {
|
||||
return this.view.html();
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
this.view.render();
|
||||
}
|
||||
|
||||
public setup(frameData: any): void {
|
||||
this.model.setup(frameData);
|
||||
}
|
||||
|
||||
public mode(): Mode {
|
||||
return this.model.mode;
|
||||
}
|
||||
|
||||
public isAbleToChangeFrame(): boolean {
|
||||
return this.model.isAbleToChangeFrame();
|
||||
}
|
||||
|
||||
public fitCanvas(): void {
|
||||
this.model.fitCanvas(this.view.html().clientWidth, this.view.html().clientHeight);
|
||||
}
|
||||
}
|
||||
|
||||
export { Canvas3dImpl as Canvas3d, Canvas3dVersion };
|
||||
@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Canvas3dModel, Mode } from './canvas3dModel';
|
||||
|
||||
export interface Canvas3dController {
|
||||
mode: Mode;
|
||||
}
|
||||
|
||||
export class Canvas3dControllerImpl implements Canvas3dController {
|
||||
private model: Canvas3dModel;
|
||||
|
||||
public constructor(model: Canvas3dModel) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public set mode(value: Mode) {
|
||||
this.model.mode = value;
|
||||
}
|
||||
|
||||
public get mode(): Mode {
|
||||
return this.model.mode;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,153 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { MasterImpl } from './master';
|
||||
|
||||
export interface Size {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface Image {
|
||||
renderWidth: number;
|
||||
renderHeight: number;
|
||||
imageData: ImageData | CanvasImageSource;
|
||||
}
|
||||
|
||||
export interface DrawData {
|
||||
enabled: boolean;
|
||||
initialState?: any;
|
||||
redraw?: number;
|
||||
}
|
||||
|
||||
export enum FrameZoom {
|
||||
MIN = 0.1,
|
||||
MAX = 10,
|
||||
}
|
||||
|
||||
export enum UpdateReasons {
|
||||
IMAGE_CHANGED = 'image_changed',
|
||||
OBJECTS_UPDATED = 'objects_updated',
|
||||
FITTED_CANVAS = 'fitted_canvas',
|
||||
DRAW = 'draw',
|
||||
SELECT = 'select',
|
||||
CANCEL = 'cancel',
|
||||
DATA_FAILED = 'data_failed',
|
||||
}
|
||||
|
||||
export enum Mode {
|
||||
IDLE = 'idle',
|
||||
DRAG = 'drag',
|
||||
RESIZE = 'resize',
|
||||
DRAW = 'draw',
|
||||
EDIT = 'edit',
|
||||
INTERACT = 'interact',
|
||||
}
|
||||
|
||||
export interface Canvas3dModel {
|
||||
mode: Mode;
|
||||
|
||||
setup(frameData: any): void;
|
||||
|
||||
isAbleToChangeFrame(): boolean;
|
||||
|
||||
fitCanvas(width: number, height: number): void;
|
||||
}
|
||||
|
||||
export class Canvas3dModelImpl extends MasterImpl implements Canvas3dModel {
|
||||
private data: {
|
||||
canvasSize: Size;
|
||||
image: Image | null;
|
||||
imageID: number | null;
|
||||
imageOffset: number;
|
||||
imageSize: Size;
|
||||
drawData: DrawData;
|
||||
mode: Mode;
|
||||
exception: Error | null;
|
||||
};
|
||||
|
||||
public constructor() {
|
||||
super();
|
||||
this.data = {
|
||||
canvasSize: {
|
||||
height: 0,
|
||||
width: 0,
|
||||
},
|
||||
image: null,
|
||||
imageID: null,
|
||||
imageOffset: 0,
|
||||
imageSize: {
|
||||
height: 0,
|
||||
width: 0,
|
||||
},
|
||||
drawData: {
|
||||
enabled: false,
|
||||
initialState: null,
|
||||
},
|
||||
mode: Mode.IDLE,
|
||||
exception: null,
|
||||
};
|
||||
}
|
||||
|
||||
public setup(frameData: any): void {
|
||||
if (this.data.imageID !== frameData.number) {
|
||||
if ([Mode.EDIT, Mode.DRAG, Mode.RESIZE].includes(this.data.mode)) {
|
||||
throw Error(`Canvas is busy. Action: ${this.data.mode}`);
|
||||
}
|
||||
}
|
||||
|
||||
this.data.imageID = frameData.number;
|
||||
frameData
|
||||
.data((): void => {
|
||||
this.data.image = null;
|
||||
this.notify(UpdateReasons.IMAGE_CHANGED);
|
||||
})
|
||||
.then((data: Image): void => {
|
||||
if (frameData.number !== this.data.imageID) {
|
||||
// already another image
|
||||
return;
|
||||
}
|
||||
|
||||
this.data.imageSize = {
|
||||
height: frameData.height as number,
|
||||
width: frameData.width as number,
|
||||
};
|
||||
|
||||
this.data.image = data;
|
||||
this.notify(UpdateReasons.IMAGE_CHANGED);
|
||||
})
|
||||
.catch((exception: any): void => {
|
||||
this.data.exception = exception;
|
||||
this.notify(UpdateReasons.DATA_FAILED);
|
||||
throw exception;
|
||||
});
|
||||
}
|
||||
|
||||
public set mode(value: Mode) {
|
||||
this.data.mode = value;
|
||||
}
|
||||
|
||||
public get mode(): Mode {
|
||||
return this.data.mode;
|
||||
}
|
||||
|
||||
public isAbleToChangeFrame(): boolean {
|
||||
const isUnable = [Mode.DRAG, Mode.EDIT, Mode.RESIZE, Mode.INTERACT].includes(this.data.mode)
|
||||
|| (this.data.mode === Mode.DRAW && typeof this.data.drawData.redraw === 'number');
|
||||
|
||||
return !isUnable;
|
||||
}
|
||||
|
||||
public fitCanvas(width: number, height: number): void {
|
||||
this.data.canvasSize.height = height;
|
||||
this.data.canvasSize.width = width;
|
||||
|
||||
this.data.imageOffset = Math.floor(
|
||||
Math.max(this.data.canvasSize.height / FrameZoom.MIN, this.data.canvasSize.width / FrameZoom.MIN),
|
||||
);
|
||||
|
||||
this.notify(UpdateReasons.FITTED_CANVAS);
|
||||
this.notify(UpdateReasons.OBJECTS_UPDATED);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import * as THREE from 'three';
|
||||
import { PCDLoader } from 'three/examples/jsm/loaders/PCDLoader';
|
||||
import { Canvas3dController } from './canvas3dController';
|
||||
import { Listener, Master } from './master';
|
||||
|
||||
import { Canvas3dModel, UpdateReasons, Mode } from './canvas3dModel';
|
||||
|
||||
export interface Canvas3dView {
|
||||
html(): HTMLDivElement;
|
||||
render(): void;
|
||||
}
|
||||
|
||||
export class Canvas3dViewImpl implements Canvas3dView, Listener {
|
||||
private controller: Canvas3dController;
|
||||
private renderer: any;
|
||||
private scene: any;
|
||||
private camera: any;
|
||||
|
||||
private set mode(value: Mode) {
|
||||
this.controller.mode = value;
|
||||
}
|
||||
|
||||
private get mode(): Mode {
|
||||
return this.controller.mode;
|
||||
}
|
||||
|
||||
public constructor(model: Canvas3dModel & Master, controller: Canvas3dController) {
|
||||
this.controller = controller;
|
||||
|
||||
this.mode = Mode.IDLE;
|
||||
|
||||
this.scene = new THREE.Scene();
|
||||
this.scene.background = new THREE.Color(0x000000);
|
||||
|
||||
// setting up the camera and adding it in the scene
|
||||
this.camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 500);
|
||||
this.camera.position.set(-15, 0, 4);
|
||||
this.camera.up.set(0, 0, 1);
|
||||
this.camera.lookAt(0, 0, 0);
|
||||
this.scene.add(this.camera);
|
||||
|
||||
this.renderer = new THREE.WebGLRenderer({ antialias: true });
|
||||
this.renderer.setPixelRatio(window.devicePixelRatio);
|
||||
this.renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
|
||||
model.subscribe(this);
|
||||
}
|
||||
|
||||
public notify(model: Canvas3dModel & Master, reason: UpdateReasons): void {
|
||||
if (reason === UpdateReasons.IMAGE_CHANGED) {
|
||||
const loader = new PCDLoader();
|
||||
this.clearScene();
|
||||
const objectURL = URL.createObjectURL(model.data.image.imageData);
|
||||
loader.load(objectURL, this.addScene.bind(this));
|
||||
URL.revokeObjectURL(objectURL);
|
||||
const event: CustomEvent = new CustomEvent('canvas.setup');
|
||||
this.renderer.domElement.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
private clearScene(): void {
|
||||
for (let i = this.scene.children.length - 1; i >= 0; i--) {
|
||||
this.scene.remove(this.scene.children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private addScene(points: any): void {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
points.material.size = 0.03;
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
points.material.color = new THREE.Color(0x0000ff);
|
||||
this.scene.add(points);
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
this.renderer.render(this.scene, this.camera);
|
||||
}
|
||||
|
||||
public html(): any {
|
||||
return this.renderer.domElement;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
const BASE_GRID_WIDTH = 2;
|
||||
|
||||
export default {
|
||||
BASE_GRID_WIDTH,
|
||||
};
|
||||
@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
export interface Master {
|
||||
subscribe(listener: Listener): void;
|
||||
unsubscribe(listener: Listener): void;
|
||||
unsubscribeAll(): void;
|
||||
notify(reason: string): void;
|
||||
}
|
||||
|
||||
export interface Listener {
|
||||
notify(master: Master, reason: string): void;
|
||||
}
|
||||
|
||||
export class MasterImpl implements Master {
|
||||
private listeners: Listener[];
|
||||
|
||||
public constructor() {
|
||||
this.listeners = [];
|
||||
}
|
||||
|
||||
public subscribe(listener: Listener): void {
|
||||
this.listeners.push(listener);
|
||||
}
|
||||
|
||||
public unsubscribe(listener: Listener): void {
|
||||
for (let i = 0; i < this.listeners.length; i++) {
|
||||
if (this.listeners[i] === listener) {
|
||||
this.listeners.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public unsubscribeAll(): void {
|
||||
this.listeners = [];
|
||||
}
|
||||
|
||||
public notify(reason: string): void {
|
||||
for (const listener of this.listeners) {
|
||||
listener.notify(this, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"emitDeclarationOnly": true,
|
||||
"module": "es6",
|
||||
"target": "es6",
|
||||
"noImplicitAny": true,
|
||||
"preserveConstEnums": true,
|
||||
"declaration": true,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node",
|
||||
"declarationDir": "dist/declaration",
|
||||
"paths": {
|
||||
"cvat-canvas.node": ["dist/cvat-canvas3d.node"]
|
||||
}
|
||||
},
|
||||
"include": ["src/typescript/*.ts"]
|
||||
}
|
||||
@ -0,0 +1,138 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const path = require('path');
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const DtsBundleWebpack = require('dts-bundle-webpack');
|
||||
|
||||
const nodeConfig = {
|
||||
target: 'node',
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
entry: './src/typescript/canvas3d.ts',
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'cvat-canvas3d.node.js',
|
||||
library: 'canvas3d',
|
||||
libraryTarget: 'commonjs',
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js', '.json'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
plugins: [
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
'@babel/plugin-proposal-optional-chaining',
|
||||
],
|
||||
presets: [['@babel/preset-env'], ['@babel/typescript']],
|
||||
sourceType: 'unambiguous',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(css|scss)$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
'style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 2,
|
||||
},
|
||||
},
|
||||
'postcss-loader',
|
||||
'sass-loader',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new DtsBundleWebpack({
|
||||
name: 'cvat-canvas3d.node',
|
||||
main: 'dist/declaration/src/typescript/canvas3d.d.ts',
|
||||
out: '../cvat-canvas3d.node.d.ts',
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
const webConfig = {
|
||||
target: 'web',
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
entry: {
|
||||
'cvat-canvas3d': './src/typescript/canvas3d.ts',
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: '[name].[contenthash].js',
|
||||
library: 'canvas3d',
|
||||
libraryTarget: 'window',
|
||||
},
|
||||
devServer: {
|
||||
contentBase: path.join(__dirname, 'dist'),
|
||||
compress: false,
|
||||
inline: true,
|
||||
port: 3000,
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js', '.json'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
plugins: ['@babel/plugin-proposal-class-properties'],
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: '> 2.5%', // https://github.com/browserslist/browserslist
|
||||
},
|
||||
],
|
||||
['@babel/typescript'],
|
||||
],
|
||||
sourceType: 'unambiguous',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
'style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 2,
|
||||
},
|
||||
},
|
||||
'postcss-loader',
|
||||
'sass-loader',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new DtsBundleWebpack({
|
||||
name: 'cvat-canvas3d',
|
||||
main: 'dist/declaration/src/typescript/canvas3d.d.ts',
|
||||
out: '../cvat-canvas3d.d.ts',
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = [webConfig, nodeConfig];
|
||||
@ -0,0 +1,109 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import React, { ReactElement, useEffect, useRef } from 'react';
|
||||
import { GlobalHotKeys } from 'react-hotkeys';
|
||||
import Layout from 'antd/lib/layout/layout';
|
||||
|
||||
import { Workspace } from 'reducers/interfaces';
|
||||
import { Canvas3d } from 'cvat-canvas3d-wrapper';
|
||||
import ContextImage from '../standard3D-workspace/context-image/context-image';
|
||||
|
||||
interface Props {
|
||||
canvasInstance: Canvas3d;
|
||||
jobInstance: any;
|
||||
frameData: any;
|
||||
curZLayer: number;
|
||||
contextImageHide: boolean;
|
||||
loaded: boolean;
|
||||
data: string;
|
||||
annotations: any[];
|
||||
onSetupCanvas: () => void;
|
||||
getContextImage(): void;
|
||||
workspace: Workspace;
|
||||
animateID: any;
|
||||
automaticBordering: boolean;
|
||||
showObjectsTextAlways: boolean;
|
||||
}
|
||||
|
||||
const CanvasWrapperComponent = (props: Props): ReactElement => {
|
||||
const animateId = useRef(0);
|
||||
const cvatCanvasContainerRef = useRef();
|
||||
|
||||
const {
|
||||
frameData, contextImageHide, getContextImage, loaded, data, annotations, curZLayer,
|
||||
} = props;
|
||||
|
||||
const fitCanvas = (): void => {
|
||||
const { canvasInstance } = props;
|
||||
canvasInstance.fitCanvas();
|
||||
};
|
||||
|
||||
const onCanvasSetup = (): void => {
|
||||
const { onSetupCanvas } = props;
|
||||
onSetupCanvas();
|
||||
};
|
||||
|
||||
const animateCanvas = (): void => {
|
||||
const { canvasInstance } = props;
|
||||
|
||||
canvasInstance.render();
|
||||
animateId.current = requestAnimationFrame(animateCanvas);
|
||||
};
|
||||
|
||||
const updateCanvas = (): void => {
|
||||
const { canvasInstance } = props;
|
||||
|
||||
if (frameData !== null) {
|
||||
canvasInstance.setup(frameData);
|
||||
}
|
||||
};
|
||||
|
||||
const initialSetup = (): void => {
|
||||
const { canvasInstance } = props;
|
||||
|
||||
// Size
|
||||
window.addEventListener('resize', fitCanvas);
|
||||
fitCanvas();
|
||||
|
||||
// Events
|
||||
canvasInstance.html().addEventListener('canvas.setup', onCanvasSetup);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const { canvasInstance } = props;
|
||||
|
||||
cvatCanvasContainerRef.current.appendChild(canvasInstance.html());
|
||||
|
||||
initialSetup();
|
||||
updateCanvas();
|
||||
animateCanvas();
|
||||
|
||||
return () => {
|
||||
canvasInstance.html().removeEventListener('canvas.setup', onCanvasSetup);
|
||||
window.removeEventListener('resize', fitCanvas);
|
||||
cancelAnimationFrame(animateId.current);
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
updateCanvas();
|
||||
}, [frameData, annotations, curZLayer]);
|
||||
|
||||
return (
|
||||
<Layout.Content style={{ position: 'relative' }}>
|
||||
<GlobalHotKeys />
|
||||
<ContextImage
|
||||
frame={frameData}
|
||||
contextImageHide={contextImageHide}
|
||||
getContextImage={getContextImage}
|
||||
loaded={loaded}
|
||||
data={data}
|
||||
/>
|
||||
<div ref={cvatCanvasContainerRef} className='cvat-canvas-container cvat-canvas-container-overflow' />
|
||||
</Layout.Content>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(CanvasWrapperComponent);
|
||||
@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
interface Props {
|
||||
frame: number;
|
||||
contextImageHide: boolean;
|
||||
loaded: boolean;
|
||||
data: string;
|
||||
getContextImage(): void;
|
||||
}
|
||||
|
||||
export default function ContextImage(props: Props): JSX.Element {
|
||||
const {
|
||||
contextImageHide, loaded, data, getContextImage,
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
if (!contextImageHide && !loaded) {
|
||||
getContextImage();
|
||||
}
|
||||
}, [contextImageHide, loaded]);
|
||||
|
||||
if (!contextImageHide && data !== '') {
|
||||
return (
|
||||
<div className='cvat-contextImage'>
|
||||
<img src={data} alt='Context not available' className='cvat-contextImage-show' />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import React from 'react';
|
||||
import { GlobalHotKeys } from 'react-hotkeys';
|
||||
import Layout from 'antd/lib/layout';
|
||||
|
||||
import { ActiveControl } from 'reducers/interfaces';
|
||||
import { Canvas3d as Canvas } from 'cvat-canvas3d-wrapper';
|
||||
|
||||
import CursorControl from './cursor-control';
|
||||
import MoveControl from './move-control';
|
||||
|
||||
import DrawCuboidControl from './draw-cuboid-control';
|
||||
|
||||
import PhotoContextControl from './photo-context';
|
||||
|
||||
interface Props {
|
||||
canvasInstance: Canvas;
|
||||
activeControl: ActiveControl;
|
||||
normalizedKeyMap: Record<string, string>;
|
||||
contextImageHide: boolean;
|
||||
hideShowContextImage: (hidden: boolean) => void;
|
||||
}
|
||||
|
||||
export default function ControlsSideBarComponent(props: Props): JSX.Element {
|
||||
const {
|
||||
canvasInstance, activeControl, normalizedKeyMap, contextImageHide, hideShowContextImage,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Layout.Sider className='cvat-canvas-controls-sidebar' theme='light' width={44}>
|
||||
<GlobalHotKeys />
|
||||
|
||||
<MoveControl canvasInstance={canvasInstance} activeControl={activeControl} />
|
||||
|
||||
<CursorControl
|
||||
cursorShortkey={normalizedKeyMap.CANCEL}
|
||||
canvasInstance={canvasInstance}
|
||||
activeControl={activeControl}
|
||||
/>
|
||||
|
||||
<DrawCuboidControl
|
||||
canvasInstance={canvasInstance}
|
||||
isDrawing={activeControl === ActiveControl.DRAW_CUBOID}
|
||||
/>
|
||||
<PhotoContextControl
|
||||
canvasInstance={canvasInstance}
|
||||
activeControl={activeControl}
|
||||
contextImageHide={contextImageHide}
|
||||
hideShowContextImage={hideShowContextImage}
|
||||
/>
|
||||
</Layout.Sider>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import React from 'react';
|
||||
import Icon from '@ant-design/icons';
|
||||
import Tooltip from 'antd/lib/tooltip';
|
||||
|
||||
import { CursorIcon } from 'icons';
|
||||
import { ActiveControl } from 'reducers/interfaces';
|
||||
import { Canvas3d as Canvas } from 'cvat-canvas3d-wrapper';
|
||||
|
||||
interface Props {
|
||||
canvasInstance: Canvas;
|
||||
cursorShortkey: string;
|
||||
activeControl: ActiveControl;
|
||||
}
|
||||
|
||||
function CursorControl(props: Props): JSX.Element {
|
||||
const { activeControl, cursorShortkey } = props;
|
||||
|
||||
return (
|
||||
<Tooltip title={`Cursor ${cursorShortkey}`} placement='right' mouseLeaveDelay={0}>
|
||||
<Icon
|
||||
component={CursorIcon}
|
||||
className={[
|
||||
'cvat-cursor-control',
|
||||
activeControl === ActiveControl.CURSOR ? 'cvat-active-canvas-control ' : null,
|
||||
]}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(CursorControl);
|
||||
@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import React from 'react';
|
||||
import Popover from 'antd/lib/popover';
|
||||
import Icon from '@ant-design/icons';
|
||||
|
||||
import { Canvas3d as Canvas } from 'cvat-canvas3d-wrapper';
|
||||
import { ShapeType } from 'reducers/interfaces';
|
||||
|
||||
import { CubeIcon } from 'icons';
|
||||
|
||||
import DrawShapePopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover';
|
||||
|
||||
interface Props {
|
||||
canvasInstance: Canvas;
|
||||
isDrawing: boolean;
|
||||
}
|
||||
|
||||
function DrawPolygonControl(props: Props): JSX.Element {
|
||||
const { canvasInstance, isDrawing } = props;
|
||||
|
||||
const dynamcPopoverPros = isDrawing ?
|
||||
{
|
||||
overlayStyle: {
|
||||
display: 'none',
|
||||
},
|
||||
} :
|
||||
{};
|
||||
|
||||
const dynamicIconProps = isDrawing ?
|
||||
{
|
||||
className: 'cvat-draw-cuboid-control cvat-active-canvas-control',
|
||||
onClick: (): void => {
|
||||
canvasInstance.draw({ enabled: false });
|
||||
},
|
||||
} :
|
||||
{
|
||||
className: 'cvat-draw-cuboid-control',
|
||||
};
|
||||
|
||||
return (
|
||||
<Popover
|
||||
{...dynamcPopoverPros}
|
||||
overlayClassName='cvat-draw-shape-popover'
|
||||
placement='right'
|
||||
content={<DrawShapePopoverContainer shapeType={ShapeType.CUBOID} />}
|
||||
>
|
||||
<Icon {...dynamicIconProps} component={CubeIcon} />
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(DrawPolygonControl);
|
||||
@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import React from 'react';
|
||||
import Icon from '@ant-design/icons';
|
||||
import Tooltip from 'antd/lib/tooltip';
|
||||
|
||||
import { MoveIcon } from 'icons';
|
||||
import { ActiveControl } from 'reducers/interfaces';
|
||||
import { Canvas3d as Canvas } from 'cvat-canvas3d-wrapper';
|
||||
|
||||
interface Props {
|
||||
canvasInstance: Canvas;
|
||||
activeControl: ActiveControl;
|
||||
}
|
||||
|
||||
function MoveControl(props: Props): JSX.Element {
|
||||
const { activeControl } = props;
|
||||
|
||||
return (
|
||||
<Tooltip title='Move the image' placement='right' mouseLeaveDelay={0}>
|
||||
<Icon
|
||||
component={MoveIcon}
|
||||
className={[
|
||||
'cvat-move-control',
|
||||
activeControl === ActiveControl.DRAG_CANVAS ? ' cvat-active-canvas-control' : null,
|
||||
]}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(MoveControl);
|
||||
@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import CameraIcon from '@ant-design/icons/CameraOutlined';
|
||||
import Tooltip from 'antd/lib/tooltip';
|
||||
import { Canvas3d as Canvas } from 'cvat-canvas3d-wrapper';
|
||||
import React from 'react';
|
||||
import { ActiveControl } from 'reducers/interfaces';
|
||||
|
||||
interface Props {
|
||||
canvasInstance: Canvas;
|
||||
activeControl: ActiveControl;
|
||||
hideShowContextImage: (hidden: boolean) => void;
|
||||
contextImageHide: boolean;
|
||||
}
|
||||
|
||||
function PhotoContextControl(props: Props): JSX.Element {
|
||||
const { activeControl, contextImageHide, hideShowContextImage } = props;
|
||||
|
||||
return (
|
||||
<Tooltip title='Photo context show/hide' placement='right' mouseLeaveDelay={0}>
|
||||
<CameraIcon
|
||||
className={`cvat-move-control
|
||||
cvat-control-side-bar-icon-size ${
|
||||
activeControl === ActiveControl.PHOTO_CONTEXT ? 'cvat-active-canvas-control' : ''
|
||||
}`}
|
||||
onClick={(): void => {
|
||||
hideShowContextImage(!contextImageHide);
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(PhotoContextControl);
|
||||
@ -0,0 +1,19 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import './styles.scss';
|
||||
import React from 'react';
|
||||
import Layout from 'antd/lib/layout';
|
||||
|
||||
import CanvasWrapperContainer from 'containers/annotation-page/canvas/canvas-wrapper3D';
|
||||
import ControlsSideBarContainer from 'containers/annotation-page/standard3D-workspace/controls-side-bar/controls-side-bar';
|
||||
|
||||
export default function StandardWorkspace3DComponent(): JSX.Element {
|
||||
return (
|
||||
<Layout hasSider className='cvat-standard-workspace'>
|
||||
<ControlsSideBarContainer />
|
||||
<CanvasWrapperContainer />
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,173 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@import 'base.scss';
|
||||
|
||||
.cvat-standard-workspace.ant-layout {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cvat-contextImage {
|
||||
width: $grid-unit-size * 32;
|
||||
position: absolute;
|
||||
background: $border-color-3;
|
||||
top: $grid-unit-size;
|
||||
right: $grid-unit-size;
|
||||
max-height: $grid-unit-size * 16;
|
||||
z-index: 100;
|
||||
border-radius: $grid-unit-size;
|
||||
border: 1px solid $border-color-3;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: $grid-unit-size/2;
|
||||
}
|
||||
|
||||
.cvat-contextImage-show {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.cvat-contextImage-loading {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cvat-objects-sidebar-filter-input {
|
||||
width: calc(100% - 35px);
|
||||
}
|
||||
|
||||
.cvat-objects-sidebar-sider {
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: auto;
|
||||
background-color: $background-color-2;
|
||||
border-left: 1px solid $border-color-1;
|
||||
border-bottom: 1px solid $border-color-1;
|
||||
border-radius: $grid-unit-size/2 0 0 $grid-unit-size/2;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.cvat-objects-sidebar {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cvat-rotate-canvas-controls-right > svg {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.cvat-canvas-controls-sidebar {
|
||||
background-color: $background-color-2;
|
||||
border-right: 1px solid $border-color-1;
|
||||
|
||||
> div {
|
||||
> i {
|
||||
border-radius: 3.3px;
|
||||
transform: scale(0.65);
|
||||
padding: $grid-unit-size/4;
|
||||
|
||||
&:hover {
|
||||
background: $header-color;
|
||||
transform: scale(0.75);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.65);
|
||||
}
|
||||
|
||||
> svg {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cvat-active-canvas-control {
|
||||
background: $header-color;
|
||||
transform: scale(0.75);
|
||||
}
|
||||
|
||||
.cvat-rotate-canvas-controls-left,
|
||||
.cvat-rotate-canvas-controls-right {
|
||||
transform: scale(0.65);
|
||||
border-radius: $grid-unit-size/2;
|
||||
|
||||
&:hover {
|
||||
transform: scale(0.75);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.65);
|
||||
}
|
||||
}
|
||||
|
||||
.cvat-rotate-canvas-controls > .ant-popover-content > .ant-popover-inner > div > .ant-popover-inner-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.cvat-draw-shape-popover,
|
||||
.cvat-tools-control-popover {
|
||||
> .ant-popover-content > .ant-popover-inner > div > .ant-popover-inner-content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.cvat-tools-track-button,
|
||||
.cvat-tools-interact-button {
|
||||
width: 100%;
|
||||
margin-top: $grid-unit-size;
|
||||
}
|
||||
|
||||
.cvat-draw-shape-popover-points-selector {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cvat-tools-control-popover-content {
|
||||
width: fit-content;
|
||||
padding: $grid-unit-size;
|
||||
border-radius: $grid-unit-size/2;
|
||||
background: $background-color-2;
|
||||
}
|
||||
|
||||
.cvat-draw-shape-popover-content {
|
||||
padding: $grid-unit-size;
|
||||
border-radius: $grid-unit-size/2;
|
||||
background: $background-color-2;
|
||||
width: 270px;
|
||||
|
||||
> div {
|
||||
margin-top: $grid-unit-size/2;
|
||||
}
|
||||
|
||||
> div:nth-child(3) > div > div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
> div:last-child {
|
||||
span {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
|
||||
&:nth-child(1) {
|
||||
border-radius: $grid-unit-size/2 0 0 $grid-unit-size/2;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
border-radius: 0 $grid-unit-size/2 $grid-unit-size/2 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cvat-canvas-container-overflow {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cvat-control-side-bar-icon-size {
|
||||
font-size: $grid-unit-size * 5;
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import CanvasWrapperComponent from 'components/annotation-page/canvas/canvas-wrapper3D';
|
||||
import { confirmCanvasReady, getContextImage } from 'actions/annotation-actions';
|
||||
|
||||
import { CombinedState } from 'reducers/interfaces';
|
||||
|
||||
import { Canvas3d } from 'cvat-canvas3d-wrapper';
|
||||
|
||||
interface StateToProps {
|
||||
canvasInstance: Canvas3d;
|
||||
jobInstance: any;
|
||||
frameData: any;
|
||||
curZLayer: number;
|
||||
contextImageHide: boolean;
|
||||
loaded: boolean;
|
||||
data: string;
|
||||
annotations: any[];
|
||||
}
|
||||
|
||||
interface DispatchToProps {
|
||||
onSetupCanvas(): void;
|
||||
getContextImage(): void;
|
||||
}
|
||||
|
||||
function mapStateToProps(state: CombinedState): StateToProps {
|
||||
const {
|
||||
annotation: {
|
||||
canvas: { instance: canvasInstance },
|
||||
job: { instance: jobInstance },
|
||||
player: {
|
||||
frame: { data: frameData },
|
||||
contextImage: { hidden: contextImageHide, data, loaded },
|
||||
},
|
||||
annotations: {
|
||||
states: annotations,
|
||||
zLayer: { cur: curZLayer },
|
||||
},
|
||||
},
|
||||
} = state;
|
||||
|
||||
return {
|
||||
canvasInstance,
|
||||
jobInstance,
|
||||
frameData,
|
||||
curZLayer,
|
||||
contextImageHide,
|
||||
loaded,
|
||||
data,
|
||||
annotations,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch: any): DispatchToProps {
|
||||
return {
|
||||
onSetupCanvas(): void {
|
||||
dispatch(confirmCanvasReady());
|
||||
},
|
||||
getContextImage(): void {
|
||||
dispatch(getContextImage());
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(CanvasWrapperComponent);
|
||||
@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { ExtendedKeyMapOptions } from 'react-hotkeys';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { Canvas } from 'cvat-canvas-wrapper';
|
||||
import { hideShowContextImage } from 'actions/annotation-actions';
|
||||
import ControlsSideBarComponent from 'components/annotation-page/standard3D-workspace/controls-side-bar/controls-side-bar';
|
||||
import { ActiveControl, CombinedState } from 'reducers/interfaces';
|
||||
|
||||
interface StateToProps {
|
||||
canvasInstance: Canvas;
|
||||
activeControl: ActiveControl;
|
||||
keyMap: Record<string, ExtendedKeyMapOptions>;
|
||||
normalizedKeyMap: Record<string, string>;
|
||||
contextImageHide: boolean;
|
||||
loaded: boolean;
|
||||
}
|
||||
|
||||
interface DispatchToProps {
|
||||
hideShowContextImage(hidden: boolean): void;
|
||||
}
|
||||
|
||||
function mapStateToProps(state: CombinedState): StateToProps {
|
||||
const {
|
||||
annotation: {
|
||||
canvas: { instance: canvasInstance, activeControl },
|
||||
player: {
|
||||
contextImage: { hidden: contextImageHide, loaded },
|
||||
},
|
||||
},
|
||||
shortcuts: { keyMap, normalizedKeyMap },
|
||||
} = state;
|
||||
|
||||
return {
|
||||
canvasInstance,
|
||||
activeControl,
|
||||
normalizedKeyMap,
|
||||
keyMap,
|
||||
contextImageHide,
|
||||
loaded,
|
||||
};
|
||||
}
|
||||
|
||||
function dispatchToProps(dispatch: any): DispatchToProps {
|
||||
return {
|
||||
hideShowContextImage(hidden: boolean): void {
|
||||
dispatch(hideShowContextImage(hidden));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, dispatchToProps)(ControlsSideBarComponent);
|
||||
@ -0,0 +1,7 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Canvas3d, Canvas3dVersion } from 'cvat-canvas3d/src/typescript/canvas3d';
|
||||
|
||||
export { Canvas3d, Canvas3dVersion };
|
||||
Loading…
Reference in New Issue