import { createInstance, executePayload, registerOnPayloadHandler, } from '@3cr/sdk-browser'; import { unref } from 'vue'; import { DataOverlaysActions, FileManagementActions, FrontEndInterfaces, InteractivityActions, LayoutActions, NavigationCubeActions, PresetsActions, ScanMovementActions, ScanOrientationActions, SlidersActions, ViewSelectionActions, FrontEndPayload, InteractivityState, MarkupsActions, McadActions, ObjectBoolean, ObjectColour, ObjectInvert, ObjectVisibility, NavigationCubeTransform, ColourData, MovementData, RotationValue, FlipValue, InvertTransformData, DataOverlayData, ViewToggleData, GraphicType, ColourPresetData, GreyscalePresetData, LoadFileData, LocalLoadDataset, LoadSessionState, ObjectInfo, ObjectId, ObjectPosition, ObjectSize, ObjectIcon, ObjectSize2D, ParentPayload, UnparentPayload, } from '@3cr/types-ts'; import { ActionCallback, InterfaceCallback, Viewer3crPayload, Viewer3crService, ViewerPayload, } from '@3cr/viewer-types-ts'; import { currentColourPreset, transactionStarted } from '@/models/scanState'; import { EventHandlers } from '@/models/eventHandlers'; import { CustomLayout } from '@3cr/viewer-types-ts/types/viewer-3cr-service'; type ObjectDimensionalVisibility = { Version: string; Id: string; Visibility2d: boolean; Visibility3d: boolean; }; export class Viewer3crServiceImpl implements Viewer3crService { private interfaceCallbacks = new EventHandlers(); private actionCallbacks = new EventHandlers(); async register(canvas: HTMLCanvasElement): Promise { await registerOnPayloadHandler(this.onPayload.bind(this)); await createInstance(canvas); } addInterfaceHandler(iface: string, callback: InterfaceCallback): void { this.interfaceCallbacks.add(iface, callback); } removeInterfaceHandler(iface: string, callback: InterfaceCallback): void { this.interfaceCallbacks.remove(iface, callback); } addActionHandler(action: string, callback: ActionCallback): void { this.actionCallbacks.add(action, callback); } removeActionHandler(action: string, callback: ActionCallback): void { this.actionCallbacks.remove(action, callback); } /** * DO-03: Set 2D annotation visibility. * @param payload The object visibility payload. */ async setAnnotation2dVisibility( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.data_overlay, DataOverlaysActions.do03, payload, ); } /** * DO-04: Set 2D annotation icon size. * @param payload The annotation 2D size payload. */ async setAnnotation2dSize( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.data_overlay, DataOverlaysActions.do04, payload, ); } /** * DO-05: Set 2D annotation colour. * @param payload The annotation 2D colour payload. */ async setAnnotation2dColour( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.data_overlay, DataOverlaysActions.do05, payload, ); } /** * DO-06: Set annotation icon. * @param payload The annotation icon payload. */ async setAnnotationIcon( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.data_overlay, DataOverlaysActions.do06, payload, ); } /** * DO-08: Set 3D annotation size. * @param payload The annotation 3D size payload. */ async setAnnotation3dSize( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.data_overlay, DataOverlaysActions.do08, payload, ); } /** * DO-09: Set 3D annotation colour. * @param payload The annotation 3D colour payload. */ async setAnnotation3dColour( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.data_overlay, DataOverlaysActions.do09, payload, ); } /** * DO-11: Set 3D annotation visibility. * @param payload The object visibility payload. */ async setAnnotation3dVisibility( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.data_overlay, DataOverlaysActions.do11, payload, ); } /** * FM-01: Load scan. * @param payload The load scan payload. */ async loadScan(payload: Viewer3crPayload): Promise { await this.sendPayload( FrontEndInterfaces.file_management, FileManagementActions.fm01, payload, ); } /** * FM-03: Load previous CurrentScanState values. * @param payload The load session payload. */ async loadScanSession( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.file_management, FileManagementActions.fm03, payload, ); } /** * FM-05: Sets the data overlay session with the given session file. * This will clear all previously loaded data overlay sessions. * @param payload The load session payload. */ async setDataOverlaySession( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.file_management, FileManagementActions.fm05, payload, ); } /** * FM-06: Adds a data overlay session to existing sessions. * @param payload The load session payload. */ async addDataOverlaySession( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.file_management, FileManagementActions.fm06, payload, ); } /** * FM-07: Receives URL from external UI for MCAD Object and reads meta-data of each object. * @param payload The load MCAD payload. */ async loadExternalMcadObject( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.file_management, FileManagementActions.fm07, payload, ); } /** * FM-08: Local File Path for Loading of a MCAD Object. * @param payload The load MCAD payload. */ async loadLocalMcadObject( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.file_management, FileManagementActions.fm08, payload, ); } /** * FM-09: Load separate MCAD file from external UI. * @param payload The load session payload. */ async loadMcadObjects( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.file_management, FileManagementActions.fm09, payload, ); } /** * IN-01: Enable or disable the mouse input. * @param payload The interactivity state payload. */ async setMouseInput( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.interactivity, InteractivityActions.in01, payload, ); } /** * IN-02: Enable or disable the keyboard input. * @param payload The interactivity state payload. */ async setKeyboardInput( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.interactivity, InteractivityActions.in02, payload, ); } /** * MC-03: Set visibility of MCAD objects. * @param payload The object visibility payload. */ async setMcadObjectVisibility( payload: Viewer3crPayload, ): Promise { await this.sendPayload(FrontEndInterfaces.mcad, McadActions.mc03, payload); } /** * MC-04: Set colour & opacity of MCAD objects. * @param payload The object colour payload. */ async setMcadObjectColour( payload: Viewer3crPayload, ): Promise { await this.sendPayload(FrontEndInterfaces.mcad, McadActions.mc04, payload); } /** * MC-05: Enables movement of MCAD objects. * @param payload The object state payload. */ async moveMcadObject( payload: Viewer3crPayload, ): Promise { await this.sendPayload(FrontEndInterfaces.mcad, McadActions.mc05, payload); } /** * MC-06: Enables rotation of MCAD objects. * @param payload The object state payload. */ async rotateMcadObject( payload: Viewer3crPayload, ): Promise { await this.sendPayload(FrontEndInterfaces.mcad, McadActions.mc06, payload); } /** * MC-09: Lock or unlock MCAD objects. * @param payload The lock payload. */ async lockMcad(payload: Viewer3crPayload): Promise { await this.sendPayload(FrontEndInterfaces.mcad, McadActions.mc09, payload); } /** * MC-10: Group MCAD objects. * @param payload The group MCAD payload. */ async groupMcad(payload: Viewer3crPayload): Promise { await this.sendPayload(FrontEndInterfaces.mcad, McadActions.mc10, payload); } /** * MC-11: Ungroup MCAD objects. * @param payload The ungroup MCAD payload. */ async ungroupMcad(payload: Viewer3crPayload): Promise { await this.sendPayload(FrontEndInterfaces.mcad, McadActions.mc11, payload); } /** * MC-16: Invert MCAD objects. * @param payload The object invert payload. */ async invertMcadObject( payload: Viewer3crPayload, ): Promise { await this.sendPayload(FrontEndInterfaces.mcad, McadActions.mc16, payload); } /** * MC-17: Remove MCAD objects. * @param payload The remove MCAD object payload. */ async removeMcadObject(payload: Viewer3crPayload): Promise { await this.sendPayload(FrontEndInterfaces.mcad, McadActions.mc17, payload); } /** * MC-18: Set MCAD object title. * @param payload The MCAD object title payload. */ async setMcadObjectTitle( payload: Viewer3crPayload, ): Promise { await this.sendPayload(FrontEndInterfaces.mcad, McadActions.mc18, payload); } /** * MU-01: Create a 2d annotation. * @param payload The 2d annotation interaction payload. */ async createAnnotation2dTool( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu01, payload, ); } /** * MU-02: Create a 3d annotation. * @param payload The 3d annotation interaction payload. */ async createAnnotation3dTool( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu02, payload, ); } /** * MU-03: Create Annotation(s) in 2D/3D. * @param payload The create annotation payload. */ async createAnnotation( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu03, payload, ); } /** * MU-04: Move annotation in 2D view. * @param payload The move annotation payload. */ async moveAnnotation2dTool( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu04, payload, ); } /** * MU-05: Move annotation in 3D view. * @param payload The move annotation payload. */ async moveAnnotation3dTool( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu05, payload, ); } /** * MU-06: Move multiple annotations. * @param payload The move annotations payload. */ async moveAnnotation( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu06, payload, ); } /** * MU-07: Remove annotation. * @param payload The remove annotation payload. */ async removeAnnotation(payload: Viewer3crPayload): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu07, payload, ); } /** * MU-08: Update annotation title. * @param payload The update annotation title payload. */ async updateAnnotationTitle( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu08, payload, ); } /** * MU-09: Update annotation description. * @param payload The update annotation description payload. */ async updateAnnotationDescription( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu09, payload, ); } /** * MU-10: Update annotation actions. * @param payload The update annotation actions payload. */ async updateAnnotationActions( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu10, payload, ); } /** * MU-16: Set 2D/3D visibility of measurements. * @param payload The measurement visibility payload. */ async setMeasurementVisibility( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu16, payload, ); } /** * MU-20: 2D length tool. * @param payload The tool interactivity payload. */ async lengthTool( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu20, payload, ); } /** * MU-21: 2D polygon tool. * @param payload The tool interactivity payload. */ async polygonTool( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu21, payload, ); } /** * MU-22: 2D angle tool. * @param payload The tool interactivity payload. */ async angleTool( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.markups, MarkupsActions.mu22, payload, ); } /** * NC-01: Set Navigation Cube Co-ordinates and Size. * @param payload The navigation cube payload. */ async setNavCubePositionSize( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.navigation_cube, NavigationCubeActions.nc01, payload, ); } /** * NC-02: Set Navigation Cube Visibility. * @param payload The navigation cube visibility payload. */ async setNavCubeVisibility( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.navigation_cube, NavigationCubeActions.nc02, payload, ); } /** * NC-03: Set Navigation Cube Interactivity. * @param payload The navigation cube interactivity payload. */ async setNavCubeInteractivity( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.navigation_cube, NavigationCubeActions.nc03, payload, ); } /** * NC-05: Set Navigation Cube Colour and Opacity. * All values must be floats between 0 and 1. * @param payload The navigation cube colour payload. */ async setNavCubeColourOpacity( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.navigation_cube, NavigationCubeActions.nc05, payload, ); } /** * NC-07: Set Navigation Cube Highlight Colour and Opacity. * All values must be floats between 0 and 255. * @param payload The navigation cube highlight colour payload. */ async setNavCubeHighlightColourOpacity( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.navigation_cube, NavigationCubeActions.nc07, payload, ); } /** * NC-08: Set Navigation Cube Face Graphics. * @param type Face type of cube. */ async setNavCubeGraphics(type: GraphicType): Promise { const message = { Version: '0.0.1', Value: type }; await this.sendPayload( FrontEndInterfaces.navigation_cube, NavigationCubeActions.nc08, { message }, ); } /** * SM-13: Pan the selected view to the left. * @param payload The scan movement payload. */ async panLeft(payload: Viewer3crPayload): Promise { await this.sendPayload( FrontEndInterfaces.scan_movement, ScanMovementActions.sm13, payload, ); } /** * SM-14: Pan the selected view to the right. * @param payload The scan movement payload. */ async panRight(payload: Viewer3crPayload): Promise { await this.sendPayload( FrontEndInterfaces.scan_movement, ScanMovementActions.sm14, payload, ); } /** * SM-15: Pan the selected view upwards. * @param payload The scan movement payload. */ async panUp(payload: Viewer3crPayload): Promise { await this.sendPayload( FrontEndInterfaces.scan_movement, ScanMovementActions.sm15, payload, ); } /** * SM-16: Pan the selected view downwards. * @param payload The scan movement payload. */ async panDown(payload: Viewer3crPayload): Promise { await this.sendPayload( FrontEndInterfaces.scan_movement, ScanMovementActions.sm16, payload, ); } /** * SM-17: Zoom In. * @param payload The scan zoom payload. */ async zoomIn(payload: Viewer3crPayload): Promise { await this.sendPayload( FrontEndInterfaces.scan_movement, ScanMovementActions.sm17, payload, ); } /** * SM-18: Zoom out. * @param payload The scan zoom payload. */ async zoomOut(payload: Viewer3crPayload): Promise { await this.sendPayload( FrontEndInterfaces.scan_movement, ScanMovementActions.sm18, payload, ); } /** * SM-26: Pan view. * @param payload The pan payload. */ async pan(payload: Viewer3crPayload): Promise { await this.sendPayload( FrontEndInterfaces.scan_movement, ScanMovementActions.sm26, payload, ); } /** * SO-01: Rotate 2D view by up to +-XXX degrees. * @param payload The scan movement payload. */ async rotateByDeg(payload: Viewer3crPayload) { await this.sendPayload( FrontEndInterfaces.scan_orientation, ScanOrientationActions.so01, payload, ); } /** * SO-02: Flip 2D View Horizontally. * @param payload The scan flip payload. */ async flipHorizontally(payload: Viewer3crPayload): Promise { await this.sendPayload( FrontEndInterfaces.scan_orientation, ScanOrientationActions.so02, payload, ); } /** * SO-03: Flip 2D View Vertically. * @param payload The scan flip payload. */ async flipVertically(payload: Viewer3crPayload): Promise { await this.sendPayload( FrontEndInterfaces.scan_orientation, ScanOrientationActions.so03, payload, ); } /** * SO-04: Invert Volume Rendering * @param payload The invert volume payload. */ async invertTransform( payload: Viewer3crPayload, ): Promise { await this.sendPayload( FrontEndInterfaces.scan_orientation, ScanOrientationActions.so04, payload, ); } async viewSelection(action: ViewSelectionActions) { const payload = { message: { Version: '1.0.0' } }; await this.sendPayload(FrontEndInterfaces.view_selection, action, payload); } async viewSelectionToggleView(payload: Viewer3crPayload) { await this.sendPayload( FrontEndInterfaces.view_selection, ViewSelectionActions.vs07, payload, ); } async sliderHandler(action: SlidersActions, value: number) { if (unref(transactionStarted)) return; await this.slider(action, value); } async scanMovementHandler(action: ScanMovementActions, value: number) { if (unref(transactionStarted)) return; await this.scanMovement(action, value); } async layouts(action: LayoutActions) { const payload = { message: { Version: '1.0.0' } }; await this.sendPayload(FrontEndInterfaces.layout, action, payload); } async customLayout(payload: Viewer3crPayload): Promise { await this.sendPayload( FrontEndInterfaces.layout, LayoutActions.lo04, payload, ); } async setPreset( action: PresetsActions, preset: ColourPresetData | GreyscalePresetData, ) { const payload = { message: preset }; await this.sendPayload(FrontEndInterfaces.presets, action, payload); if (action === PresetsActions.pr02) { currentColourPreset.value = preset as ColourPresetData; } } private async scanMovement(action: ScanMovementActions, value: number) { const payload = { message: { Version: '0.0.1', Value: value } }; await this.sendPayload(FrontEndInterfaces.scan_movement, action, payload); } private async slider(action: SlidersActions, value: number) { const payload = { message: { Version: '0.0.1', Value: value } }; await this.sendPayload(FrontEndInterfaces.sliders, action, payload); } async sendPayload( iface: string, action: string, payload: Viewer3crPayload, ): Promise { await executePayload({ Version: '0.0.1', Interface: iface as any, Action: action as any, Message: payload.message ? JSON.stringify(payload.message) : null, ReturnChannel: payload.returnChannel ? JSON.stringify(payload.returnChannel) : null, ReturnTo: payload.returnTo ?? null, }); } async onPayload(payload: FrontEndPayload): Promise { const { Interface, Message, Action, ReturnChannel, ReturnTo } = payload; await this.interfaceCallbacks.call( Interface, Message, Action, ReturnChannel, ReturnTo, ); await this.actionCallbacks.call(Action, Message, ReturnChannel, ReturnTo); } }