Allow dragging 3D canvas in IDLE mode (#5385)

main
Boris Sekachev 3 years ago committed by GitHub
parent 00228ab7bb
commit 785edcb272
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -24,6 +24,7 @@ from online detectors & interactors) (<https://github.com/opencv/cvat/pull/4543>
### Changed ### Changed
- `api/docs`, `api/swagger`, `api/schema`, `server/about` endpoints now allow unauthorized access (<https://github.com/opencv/cvat/pull/4928>, <https://github.com/opencv/cvat/pull/4935>) - `api/docs`, `api/swagger`, `api/schema`, `server/about` endpoints now allow unauthorized access (<https://github.com/opencv/cvat/pull/4928>, <https://github.com/opencv/cvat/pull/4935>)
- 3D canvas now can be dragged in IDLE mode (<https://github.com/opencv/cvat/pull/5385>)
- Datumaro version is upgraded to 0.3 (dev) (<https://github.com/opencv/cvat/pull/4984>) - Datumaro version is upgraded to 0.3 (dev) (<https://github.com/opencv/cvat/pull/4984>)
- Allowed trailing slashes in the SDK host address (<https://github.com/opencv/cvat/pull/5057>) - Allowed trailing slashes in the SDK host address (<https://github.com/opencv/cvat/pull/5057>)
- Enabled authentication via email (<https://github.com/opencv/cvat/pull/5037>) - Enabled authentication via email (<https://github.com/opencv/cvat/pull/5037>)

@ -1,6 +1,6 @@
{ {
"name": "cvat-canvas3d", "name": "cvat-canvas3d",
"version": "0.0.1", "version": "0.0.2",
"description": "Part of Computer Vision Annotation Tool which presents its canvas3D library", "description": "Part of Computer Vision Annotation Tool which presents its canvas3D library",
"main": "src/canvas3d.ts", "main": "src/canvas3d.ts",
"scripts": { "scripts": {

@ -1,4 +1,5 @@
// Copyright (C) 2021-2022 Intel Corporation // Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -76,6 +77,7 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
private cube: CuboidModel; private cube: CuboidModel;
private highlighted: boolean; private highlighted: boolean;
private selected: CubeObject; private selected: CubeObject;
private isPerspectiveBeingDragged: boolean;
private model: Canvas3dModel & Master; private model: Canvas3dModel & Master;
private action: any; private action: any;
private globalHelpers: any; private globalHelpers: any;
@ -94,6 +96,7 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
this.speed = CONST.MOVEMENT_FACTOR; this.speed = CONST.MOVEMENT_FACTOR;
this.cube = new CuboidModel('line', '#ffffff'); this.cube = new CuboidModel('line', '#ffffff');
this.highlighted = false; this.highlighted = false;
this.isPerspectiveBeingDragged = false;
this.selected = this.cube; this.selected = this.cube;
this.model = model; this.model = model;
this.globalHelpers = { this.globalHelpers = {
@ -249,6 +252,15 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
} }
}); });
canvasPerspectiveView.addEventListener('mousedown', this.onPerspectiveDrag);
window.document.addEventListener('mouseup', () => {
this.disablePerspectiveDragging();
if (this.isPerspectiveBeingDragged && this.mode !== Mode.DRAG_CANVAS) {
// call this body only of drag was activated inside the canvas, but not globally
this.isPerspectiveBeingDragged = false;
}
});
canvasTopView.addEventListener('mousedown', this.startAction.bind(this, 'top')); canvasTopView.addEventListener('mousedown', this.startAction.bind(this, 'top'));
canvasSideView.addEventListener('mousedown', this.startAction.bind(this, 'side')); canvasSideView.addEventListener('mousedown', this.startAction.bind(this, 'side'));
canvasFrontView.addEventListener('mousedown', this.startAction.bind(this, 'front')); canvasFrontView.addEventListener('mousedown', this.startAction.bind(this, 'front'));
@ -276,8 +288,11 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
canvasPerspectiveView.addEventListener('click', (e: MouseEvent): void => { canvasPerspectiveView.addEventListener('click', (e: MouseEvent): void => {
e.preventDefault(); e.preventDefault();
if (e.detail !== 1) return; const selectionIsBlocked = ![Mode.GROUP, Mode.IDLE].includes(this.mode) ||
if (![Mode.GROUP, Mode.IDLE].includes(this.mode) || !this.views.perspective.rayCaster) return; !this.views.perspective.rayCaster ||
this.isPerspectiveBeingDragged;
if (e.detail !== 1 || selectionIsBlocked) return;
const intersects = this.views.perspective.rayCaster.renderer.intersectObjects( const intersects = this.views.perspective.rayCaster.renderer.intersectObjects(
this.views.perspective.scene.children[0].children, this.views.perspective.scene.children[0].children,
false, false,
@ -450,7 +465,6 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
viewType.controls = new CameraControls(viewType.camera, viewType.renderer.domElement); viewType.controls = new CameraControls(viewType.camera, viewType.renderer.domElement);
viewType.controls.mouseButtons.left = CameraControls.ACTION.NONE; viewType.controls.mouseButtons.left = CameraControls.ACTION.NONE;
viewType.controls.mouseButtons.right = CameraControls.ACTION.NONE; viewType.controls.mouseButtons.right = CameraControls.ACTION.NONE;
viewType.controls.mouseButtons.wheel = CameraControls.ACTION.NONE;
viewType.controls.touches.one = CameraControls.ACTION.NONE; viewType.controls.touches.one = CameraControls.ACTION.NONE;
viewType.controls.touches.two = CameraControls.ACTION.NONE; viewType.controls.touches.two = CameraControls.ACTION.NONE;
viewType.controls.touches.three = CameraControls.ACTION.NONE; viewType.controls.touches.three = CameraControls.ACTION.NONE;
@ -528,6 +542,30 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
} }
} }
private enablePerspectiveDragging(): void {
const { controls } = this.views.perspective;
controls.mouseButtons.left = CameraControls.ACTION.ROTATE;
controls.mouseButtons.right = CameraControls.ACTION.TRUCK;
controls.touches.one = CameraControls.ACTION.TOUCH_ROTATE;
controls.touches.two = CameraControls.ACTION.TOUCH_DOLLY_TRUCK;
controls.touches.three = CameraControls.ACTION.TOUCH_TRUCK;
}
private disablePerspectiveDragging(): void {
const { controls } = this.views.perspective;
controls.mouseButtons.left = CameraControls.ACTION.NONE;
controls.mouseButtons.right = CameraControls.ACTION.NONE;
controls.touches.one = CameraControls.ACTION.NONE;
controls.touches.two = CameraControls.ACTION.NONE;
controls.touches.three = CameraControls.ACTION.NONE;
}
private onPerspectiveDrag = (): void => {
if (![Mode.DRAG_CANVAS, Mode.IDLE].includes(this.mode)) return;
this.isPerspectiveBeingDragged = true;
this.enablePerspectiveDragging();
}
private startAction(view: any, event: MouseEvent): void { private startAction(view: any, event: MouseEvent): void {
if (event.detail !== 1) return; if (event.detail !== 1) return;
if (this.model.mode === Mode.DRAG_CANVAS) return; if (this.model.mode === Mode.DRAG_CANVAS) return;
@ -844,24 +882,26 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
} else if (reason === UpdateReasons.OBJECTS_UPDATED) { } else if (reason === UpdateReasons.OBJECTS_UPDATED) {
this.setupObjects(); this.setupObjects();
} else if (reason === UpdateReasons.DRAG_CANVAS) { } else if (reason === UpdateReasons.DRAG_CANVAS) {
this.isPerspectiveBeingDragged = true;
this.dispatchEvent( this.dispatchEvent(
new CustomEvent(this.model.mode === Mode.DRAG_CANVAS ? 'canvas.dragstart' : 'canvas.dragstop', { new CustomEvent('canvas.dragstart', {
bubbles: false, bubbles: false,
cancelable: true, cancelable: true,
}), }),
); );
this.model.data.activeElement.clientID = 'null'; this.model.data.activeElement.clientID = 'null';
if (this.model.mode === Mode.DRAG_CANVAS) {
const { controls } = this.views.perspective;
controls.mouseButtons.left = CameraControls.ACTION.ROTATE;
controls.mouseButtons.right = CameraControls.ACTION.TRUCK;
controls.mouseButtons.wheel = CameraControls.ACTION.DOLLY;
controls.touches.one = CameraControls.ACTION.TOUCH_ROTATE;
controls.touches.two = CameraControls.ACTION.TOUCH_DOLLY_TRUCK;
controls.touches.three = CameraControls.ACTION.TOUCH_TRUCK;
}
this.setupObjects(); this.setupObjects();
} else if (reason === UpdateReasons.CANCEL) { } else if (reason === UpdateReasons.CANCEL) {
if (this.mode === Mode.DRAG_CANVAS) {
this.isPerspectiveBeingDragged = false;
this.dispatchEvent(
new CustomEvent('canvas.dragstop', {
bubbles: false,
cancelable: true,
}),
);
}
if (this.mode === Mode.DRAW) { if (this.mode === Mode.DRAW) {
this.controller.drawData.enabled = false; this.controller.drawData.enabled = false;
this.controller.drawData.redraw = undefined; this.controller.drawData.redraw = undefined;
@ -869,16 +909,12 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
this.views[view as keyof Views].scene.children[0].remove(this.cube[view as keyof Views]); this.views[view as keyof Views].scene.children[0].remove(this.cube[view as keyof Views]);
}); });
} }
this.model.data.groupData.grouped = []; this.model.data.groupData.grouped = [];
this.setHelperVisibility(false); this.setHelperVisibility(false);
this.mode = Mode.IDLE;
this.model.mode = Mode.IDLE; this.model.mode = Mode.IDLE;
const { controls } = this.views.perspective;
controls.mouseButtons.left = CameraControls.ACTION.NONE;
controls.mouseButtons.right = CameraControls.ACTION.NONE;
controls.mouseButtons.wheel = CameraControls.ACTION.NONE;
controls.touches.one = CameraControls.ACTION.NONE;
controls.touches.two = CameraControls.ACTION.NONE;
controls.touches.three = CameraControls.ACTION.NONE;
this.dispatchEvent(new CustomEvent('canvas.canceled')); this.dispatchEvent(new CustomEvent('canvas.canceled'));
} else if (reason === UpdateReasons.FITTED_CANVAS) { } else if (reason === UpdateReasons.FITTED_CANVAS) {
this.dispatchEvent(new CustomEvent('canvas.fit')); this.dispatchEvent(new CustomEvent('canvas.fit'));
@ -991,6 +1027,10 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
points.material.size = 0.05; points.material.size = 0.05;
points.material.color.set(new THREE.Color(0xffffff)); points.material.color.set(new THREE.Color(0xffffff));
const { controls } = this.views.perspective;
controls.mouseButtons.wheel = CameraControls.ACTION.DOLLY;
const material = points.material.clone(); const material = points.material.clone();
const sphereCenter = points.geometry.boundingSphere.center; const sphereCenter = points.geometry.boundingSphere.center;
const { radius } = points.geometry.boundingSphere; const { radius } = points.geometry.boundingSphere;
@ -1175,7 +1215,7 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
this.cube.perspective.position.copy(newPoints); this.cube.perspective.position.copy(newPoints);
this.views.perspective.renderer.domElement.style.cursor = 'default'; this.views.perspective.renderer.domElement.style.cursor = 'default';
} }
} else if (this.mode === Mode.IDLE) { } else if (this.mode === Mode.IDLE && !this.isPerspectiveBeingDragged) {
const { children } = this.views.perspective.scene.children[0]; const { children } = this.views.perspective.scene.children[0];
const { renderer } = this.views.perspective.rayCaster; const { renderer } = this.views.perspective.rayCaster;
const intersects = renderer.intersectObjects(children, false); const intersects = renderer.intersectObjects(children, false);

@ -1,7 +1,10 @@
// Copyright (C) 2021-2022 Intel Corporation // Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) CVAT.ai Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
/* eslint-disable cypress/no-unnecessary-waiting */
/// <reference types="cypress" /> /// <reference types="cypress" />
import { taskName, labelName } from '../../support/const_canvas3d'; import { taskName, labelName } from '../../support/const_canvas3d';
@ -9,12 +12,10 @@ import { taskName, labelName } from '../../support/const_canvas3d';
context('Canvas 3D functionality. "Move the image" button interaction.', () => { context('Canvas 3D functionality. "Move the image" button interaction.', () => {
const caseId = '86'; const caseId = '86';
const screenshotsPath = 'cypress/screenshots/canvas3d_functionality/case_86_canvas3d_functionality_move_image_button.js'; const screenshotsPath = 'cypress/screenshots/canvas3d_functionality/case_86_canvas3d_functionality_move_image_button.js';
const cuboidCreationParams = { const cuboidCreationParams = { labelName };
labelName: labelName,
};
before(() => { before(() => {
cy.openTask(taskName) cy.openTask(taskName);
cy.openJob(); cy.openJob();
cy.wait(1000); // Waiting for the point cloud to display cy.wait(1000); // Waiting for the point cloud to display
cy.create3DCuboid(cuboidCreationParams); cy.create3DCuboid(cuboidCreationParams);

@ -1,7 +1,10 @@
// Copyright (C) 2021-2022 Intel Corporation // Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
/* eslint-disable cypress/no-unnecessary-waiting */
/// <reference types="cypress" /> /// <reference types="cypress" />
import { taskName } from '../../support/const_canvas3d'; import { taskName } from '../../support/const_canvas3d';
@ -75,9 +78,33 @@ context('Canvas 3D functionality. Basic actions.', () => {
before(() => { before(() => {
cy.openTaskJob(taskName); cy.openTaskJob(taskName);
cy.wait(2000); // Waiting for the point cloud to display
}); });
describe(`Testing case "${caseId}"`, () => { describe(`Testing case "${caseId}"`, () => {
it.skip('Check canvas can be zoomed.', () => {
// after some investigations it is clear that tests do not work for 3D
// in headless mode, need more time to investigate
const screenshotNameBefore = 'before_idle_zoom';
const screenshotNameAfter = 'after_idle_zoom';
cy.screenshot(screenshotNameBefore, {
onAfterScreenshot: () => {
cy.get('.cvat-canvas3d-perspective').should('exist').and('be.visible')
.within(() => {
cy.get('canvas').trigger('wheel', { deltaY: -500 });
cy.screenshot(screenshotNameAfter, {
onAfterScreenshot: () => {
cy.compareImagesAndCheckResult(
`${screenshotsPath}/${screenshotNameBefore}.png`,
`${screenshotsPath}/${screenshotNameAfter}.png`,
);
},
});
});
},
});
});
it('Check existing of elements.', () => { it('Check existing of elements.', () => {
cy.get('.cvat-canvas3d-perspective') cy.get('.cvat-canvas3d-perspective')
.should('exist') .should('exist')

Loading…
Cancel
Save