Skip to content

Commit

Permalink
feat: Optionally remove the event mouse functions from the 360 images (
Browse files Browse the repository at this point in the history
…#4801)

* Initial commit

* Update reveal.api.md

* Update Cognite3DViewer.ts

* Update reveal.api.md

* Update Image360Facade.ts
  • Loading branch information
nilscognite authored Oct 15, 2024
1 parent e7beded commit af8e73e
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 59 deletions.
6 changes: 4 additions & 2 deletions viewer/packages/360-images/src/Image360Facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ export class Image360Facade<T> {
this.getCollectionContainingEntity(entity).setSelectedVisibility(visible);
}

hideAllHoverIcons(): void {
this._image360Collections.forEach(collection => collection.setSelectedVisibility(false));
hideAllHoverIcons(): boolean {
return this._image360Collections.reduce((changed, collection) => {
return collection.setSelectedVisibility(false) || changed;
}, false);
}

set allIconCullingScheme(scheme: IconCullingScheme) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,12 @@ export class DefaultImage360Collection implements Image360Collection {
this.image360Entities.forEach(entity => (entity.icon.selected = selected));
}

public setSelectedVisibility(visible: boolean): void {
public setSelectedVisibility(visible: boolean): boolean {
if (this._icons.hoverSpriteVisibility == visible) {
return false;
}
this._icons.hoverSpriteVisibility = visible;
return true;
}

public setCullingScheme(scheme: IconCullingScheme): void {
Expand Down
5 changes: 3 additions & 2 deletions viewer/packages/3d-overlays/src/Overlay3DIcon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,9 @@ export class Overlay3DIcon<ContentType = DefaultOverlay3DContentType> implements
}

updateHoverSpriteScale(): void {
if (!this._hoverSprite) return;

if (!this._hoverSprite) {
return;
}
this._hoverSprite.scale.set(this._adaptiveScale * 2, this._adaptiveScale * 2, 1);
}

Expand Down
100 changes: 54 additions & 46 deletions viewer/packages/api/src/api-helpers/Image360ApiHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export class Image360ApiHelper {
private _transitionInProgress: boolean = false;
private readonly _raycaster = new Raycaster();
private _needsRedraw: boolean = false;
private readonly _hasEventListeners: boolean;
private readonly _inputHandler?: InputHandler;

private readonly _interactionState: {
currentImage360Hovered?: Image360Entity;
Expand All @@ -58,13 +60,6 @@ export class Image360ApiHelper {
lastMousePosition?: { offsetX: number; offsetY: number };
};

private readonly _eventHandlers: {
setHoverIconEventHandler: (event: MouseEvent) => void;
enter360Image: (event: PointerEvent) => Promise<void>;
exit360ImageOnEscapeKey: (event: KeyboardEvent) => void;
updateHoverStateOnRender: () => void;
};

private readonly _debouncePreLoad = debounce(
entity => {
this._image360Facade.preload(entity, this.findRevisionIdToEnter(entity)).catch(() => {});
Expand All @@ -80,15 +75,32 @@ export class Image360ApiHelper {
private readonly _onBeforeSceneRenderedEvent: EventTrigger<BeforeSceneRenderedDelegate>;
private _cachedCameraManager: CameraManager | undefined;

private readonly exit360ImageOnEscapeKey = (event: KeyboardEvent) => this.exit360ImageOnEscape(event);
public readonly setHoverIconEventHandler = (event: MouseEvent): void =>
this.setHoverIconOnIntersect(event.offsetX, event.offsetY);

public readonly enter360ImageHandler = (event: PointerEventData): Promise<boolean> =>
this.enter360ImageOnIntersect(event);

private readonly updateHoverStateOnRenderHandler = () => {
const lastOffset = this._interactionState.lastMousePosition;
if (lastOffset === undefined) {
return;
}
this.setHoverIconOnIntersect(lastOffset.offsetX, lastOffset.offsetY);
};

constructor(
cogniteClient: CogniteClient,
sceneHandler: SceneHandler,
domElement: HTMLElement,
activeCameraManager: ProxyCameraManager,
inputHandler: InputHandler,
onBeforeSceneRendered: EventTrigger<BeforeSceneRenderedDelegate>,
hasEventListeners?: boolean,
iconsOptions?: IconsOptions
) {
this._hasEventListeners = hasEventListeners ?? true;
const image360EventDescriptorProvider = new Cdf360EventDescriptorProvider(cogniteClient);
const image360DataModelsDescriptorProvider = new Cdf360DataModelsDescriptorProvider(cogniteClient);
const combinedDescriptorProvider = new Cdf360CombinedDescriptorProvider(
Expand Down Expand Up @@ -119,30 +131,12 @@ export class Image360ApiHelper {
this._stationaryCameraManager = new StationaryCameraManager(domElement, activeCameraManager.getCamera().clone());
this._cachedCameraManager = activeCameraManager.innerCameraManager;
}
const setHoverIconEventHandler = (event: MouseEvent) => this.setHoverIconOnIntersect(event.offsetX, event.offsetY);
domElement.addEventListener('mousemove', setHoverIconEventHandler);

const enter360Image = (event: PointerEventData) => this.enter360ImageOnIntersect(event);
inputHandler.on('click', enter360Image);

const exit360ImageOnEscapeKey = (event: KeyboardEvent) => this.exit360ImageOnEscape(event);

const updateHoverStateOnRender = () => {
const lastOffset = this._interactionState.lastMousePosition;
if (lastOffset === undefined) {
return;
}
this.setHoverIconOnIntersect(lastOffset.offsetX, lastOffset.offsetY);
};

onBeforeSceneRendered.subscribe(updateHoverStateOnRender);

this._eventHandlers = {
setHoverIconEventHandler,
enter360Image,
exit360ImageOnEscapeKey,
updateHoverStateOnRender
};
if (this._hasEventListeners) {
domElement.addEventListener('mousemove', this.setHoverIconEventHandler);
this._inputHandler = inputHandler;
this._inputHandler.on('click', this.enter360ImageHandler);
}
onBeforeSceneRendered.subscribe(this.updateHoverStateOnRenderHandler);
}

get needsRedraw(): boolean {
Expand Down Expand Up @@ -240,9 +234,16 @@ export class Image360ApiHelper {
}

public async enter360Image(image360Entity: Image360Entity, revision?: Image360RevisionEntity): Promise<void> {
await this.enter360ImageInternal(image360Entity, revision);
}

public async enter360ImageInternal(
image360Entity: Image360Entity,
revision?: Image360RevisionEntity
): Promise<boolean> {
const revisionToEnter = revision ?? this.findRevisionIdToEnter(image360Entity);
if (revisionToEnter === this._interactionState.revisionSelectedForEntry) {
return;
return false;
}
this._interactionState.revisionSelectedForEntry = revisionToEnter;
try {
Expand All @@ -251,10 +252,10 @@ export class Image360ApiHelper {
if (this._interactionState.revisionSelectedForEntry === revisionToEnter) {
this._interactionState.revisionSelectedForEntry = undefined;
}
return;
return false;
}
if (this._interactionState.revisionSelectedForEntry !== revisionToEnter) {
return;
return false;
}
const lastEntered360ImageEntity = this._interactionState.currentImage360Entered;
this._interactionState.currentImage360Entered = image360Entity;
Expand Down Expand Up @@ -304,10 +305,11 @@ export class Image360ApiHelper {
}
this._transitionInProgress = false;
}
this._domElement.addEventListener('keydown', this._eventHandlers.exit360ImageOnEscapeKey);
this._domElement.addEventListener('keydown', this.exit360ImageOnEscapeKey);
this.applyFullResolutionTextures(revisionToEnter);

imageCollection.events.image360Entered.fire(image360Entity, revisionToEnter);
return true;
}

private async applyFullResolutionTextures(revision: Image360RevisionEntity) {
Expand Down Expand Up @@ -471,7 +473,7 @@ export class Image360ApiHelper {
this._activeCameraManager.setActiveCameraManager(this._cachedCameraManager);
setCameraTarget1MeterInFrontOfCamera(this._activeCameraManager, position, rotation);
}
this._domElement.removeEventListener('keydown', this._eventHandlers.exit360ImageOnEscapeKey);
this._domElement.removeEventListener('keydown', this.exit360ImageOnEscapeKey);

function setCameraTarget1MeterInFrontOfCamera(manager: CameraManager, position: Vector3, rotation: Quaternion) {
manager.setCameraState({
Expand All @@ -482,9 +484,14 @@ export class Image360ApiHelper {
}

public dispose(): void {
this._onBeforeSceneRenderedEvent.unsubscribe(this._eventHandlers.updateHoverStateOnRender);
this._domElement.removeEventListener('mousemove', this._eventHandlers.setHoverIconEventHandler);
this._domElement.removeEventListener('keydown', this._eventHandlers.exit360ImageOnEscapeKey);
this._onBeforeSceneRenderedEvent.unsubscribe(this.updateHoverStateOnRenderHandler);
if (this._hasEventListeners) {
this._domElement.removeEventListener('mousemove', this.setHoverIconEventHandler);
if (this._inputHandler != undefined) {
this._inputHandler.off('click', this.enter360ImageHandler);
}
}
this._domElement.removeEventListener('keydown', this.exit360ImageOnEscapeKey);

if (this._stationaryCameraManager && this._cachedCameraManager) {
if (this._activeCameraManager.innerCameraManager === this._stationaryCameraManager) {
Expand All @@ -500,15 +507,15 @@ export class Image360ApiHelper {
return targetDate ? image360Entity.getRevisionClosestToDate(targetDate) : image360Entity.getMostRecentRevision();
}

private enter360ImageOnIntersect(event: PointerEventData): Promise<void> {
private enter360ImageOnIntersect(event: PointerEventData): Promise<boolean> {
if (this._transitionInProgress) {
return Promise.resolve();
return Promise.resolve(false);
}
const entity = this.intersect360ImageIcons(event.offsetX, event.offsetY);
if (entity === undefined) {
return Promise.resolve();
return Promise.resolve(false);
}
return this.enter360Image(entity);
return this.enter360ImageInternal(entity);
}

public intersect360ImageIcons(offsetX: number, offsetY: number): Image360Entity | undefined {
Expand Down Expand Up @@ -554,7 +561,6 @@ export class Image360ApiHelper {

if (entity === this._interactionState.currentImage360Hovered) {
entity?.icon.updateHoverSpriteScale();

return;
}

Expand All @@ -563,9 +569,11 @@ export class Image360ApiHelper {
entity.icon.selected = true;
this._debouncePreLoad(entity);
} else {
this._image360Facade.hideAllHoverIcons();
if (!this._image360Facade.hideAllHoverIcons()) {
this._interactionState.currentImage360Hovered = undefined;
return;
}
}

this._needsRedraw = true;
this._interactionState.currentImage360Hovered = entity;
}
Expand Down
30 changes: 29 additions & 1 deletion viewer/packages/api/src/public/migration/Cognite3DViewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export class Cognite3DViewer {
private readonly spinner: Spinner;

/**
* Enbles us to ensure models are added in the order their load is initialized.
* Enable us to ensure models are added in the order their load is initialized.
*/
private readonly _addModelSequencer: AsyncSequencer = new AsyncSequencer();

Expand Down Expand Up @@ -350,6 +350,7 @@ export class Cognite3DViewer {
this._activeCameraManager,
this._mouseHandler,
this._events.beforeSceneRendered,
options.hasEventListeners,
{
platformMaxPointsSize: getMaxPointSize(this._renderer)
}
Expand Down Expand Up @@ -1664,6 +1665,33 @@ export class Cognite3DViewer {
return intersection;
}

/**
* Event function to click on 360 images.
* @param event The event type.
* @returns True if the event was handled, false otherwise.
* @beta
*/
public async onClick360Images(event: PointerEvent): Promise<boolean> {
if (this._image360ApiHelper === undefined) {
return false;
}
return this._image360ApiHelper.enter360ImageHandler({ offsetX: event.offsetX, offsetY: event.offsetY });
}

/**
* Event function to to move the mouse.
* @param event The event type.
* @returns True if the event was handled, false otherwise.
* @beta
*/
public onHover360Images(event: PointerEvent): boolean {
if (this._image360ApiHelper === undefined) {
return false;
}
this._image360ApiHelper.setHoverIconEventHandler(event);
return true;
}

private isIntersecting360Icon(vector: THREE.Vector2): boolean {
if (this._image360ApiHelper === undefined) {
return false;
Expand Down
2 changes: 1 addition & 1 deletion viewer/packages/api/src/public/migration/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ export interface Cognite3DViewerOptions {
useFlexibleCameraManager?: boolean;

/**
* Add event listerers around, default is having event listeners.
* Add event listeners around, default is having event listeners.
* @beta
*/
hasEventListeners?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class FlexibleCameraManager extends PointerEvents implements IFlexibleCam
private _isEnableClickAndDoubleClick = true;
private _nearAndFarNeedsUpdate = false;
private readonly _raycastCallback: RaycastCallback;
private readonly _haveEventListeners: boolean;
private readonly _hasEventListeners: boolean;

private readonly cameraManagerHelper = new CameraManagerHelper();

Expand All @@ -61,15 +61,15 @@ export class FlexibleCameraManager extends PointerEvents implements IFlexibleCam
raycastCallback: RaycastCallback,
camera?: PerspectiveCamera,
scene?: Scene,
haveEventListeners?: boolean
hasEventListeners?: boolean
) {
super();
this._haveEventListeners = haveEventListeners ?? true;
this._hasEventListeners = hasEventListeners ?? true;
this._controls = new FlexibleControls(camera, domElement, new FlexibleControlsOptions());
this._controls.getPickedPointByPixelCoordinates = this.getPickedPointByPixelCoordinates;
this._raycastCallback = raycastCallback;

if (this._haveEventListeners) {
if (this._hasEventListeners) {
this._pointerEventsTarget = new PointerEventsTarget(domElement, this);
this.addEventListeners();
}
Expand Down Expand Up @@ -393,15 +393,15 @@ export class FlexibleCameraManager extends PointerEvents implements IFlexibleCam
//================================================

private addEventListeners() {
if (!this._haveEventListeners) {
if (!this._hasEventListeners) {
return;
}
this._pointerEventsTarget?.addEventListeners();
this._controls.addEventListeners();
}

private removeEventListeners(): void {
if (!this._haveEventListeners) {
if (!this._hasEventListeners) {
return;
}
this._pointerEventsTarget?.removeEventListeners();
Expand Down
4 changes: 4 additions & 0 deletions viewer/reveal.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,10 @@ export class Cognite3DViewer {
on(event: 'cameraStop', callback: CameraStopDelegate): void;
on(event: 'beforeSceneRendered', callback: BeforeSceneRenderedDelegate): void;
on(event: 'sceneRendered', callback: SceneRenderedDelegate): void;
// @beta
onClick360Images(event: PointerEvent): Promise<boolean>;
// @beta
onHover360Images(event: PointerEvent): boolean;
get pointCloudBudget(): PointCloudBudget;
set pointCloudBudget(budget: PointCloudBudget);
// @deprecated
Expand Down

0 comments on commit af8e73e

Please sign in to comment.