import { Component, AfterViewInit, OnDestroy, ViewChild, ElementRef, ChangeDetectorRef, CUSTOM_ELEMENTS_SCHEMA, EventEmitter, Output, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { MetricsTrackerService } from '../../../../services/metrics-tracker.service'; import '../../../../../assets/scripts/model-viewer'; @Component({ selector: 'app-spatial-position-assessment', standalone: true, imports: [CommonModule, FormsModule], templateUrl: './spatial-position-assessment.component.html', styleUrls: ['./spatial-position-assessment.component.css'], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class SpatialPositionAssessmentComponent implements AfterViewInit { @ViewChild('modelViewer') modelViewerRef!: ElementRef; @Output() testComplete = new EventEmitter(); @Output() redoTest = new EventEmitter(); private metricsService = inject(MetricsTrackerService); public scale = 1; public verticalOffset = 0; protected isModelPlaced = false; private initialArAnchor: { x: number; y: number; z: number } | null = null; constructor(private cdr: ChangeDetectorRef) { this.logInteraction = this.logInteraction.bind(this); } ngAfterViewInit() { const mv = this.modelViewerRef.nativeElement; mv.addEventListener('ar-status', (e: any) => { if (e.detail.status === 'session-started') { setTimeout(() => this.captureAnchor(), 500); this.metricsService.startTracking(mv); } }); } public logInteraction(event: Event) { this.metricsService.logInteraction(event); } private async captureAnchor() { const mv = this.modelViewerRef.nativeElement; const anchor = mv.getAnchor(); if (!anchor.includes('not placed')) { const [x, y, z] = anchor.split(' ').map(parseFloat); this.initialArAnchor = { x, y, z }; this.isModelPlaced = true; this.cdr.detectChanges(); } else { setTimeout(() => this.captureAnchor(), 500); } } onSliderInput() { if (!this.initialArAnchor) return; const { x, y, z } = this.initialArAnchor!; const newY = y + this.verticalOffset; this.modelViewerRef.nativeElement.setAttribute('ar-anchor', `${x} ${newY} ${z}`); } resetPosition() { this.scale = 1; this.verticalOffset = 0; this.onSliderInput(); } confirmPlacement() { const finalPlacement = { finalScale: this.scale, finalVerticalOffset: this.verticalOffset, initialAnchor: this.initialArAnchor, finalAnchor: this.modelViewerRef.nativeElement.getAttribute('ar-anchor') }; this.metricsService.logInteraction(new CustomEvent('test-results', { detail: { testName: 'SpatialPositionAssessment', results: finalPlacement } })); console.log('Spatial position results captured locally.'); this.testComplete.emit(); } retryCurrent() { this.redoTest.emit(1); } }