Back to home page

EIC code displayed by LXR

 
 

    


Warning, /firebird/packages/firebird-ng/display/src/lib/components/scene-export/scene-export.ts is written in an unsupported language. File is not indexed.

0001 import {
0002   Component,
0003   ViewChild,
0004   TemplateRef,
0005   ElementRef,
0006   ViewContainerRef,
0007   ChangeDetectionStrategy,
0008   signal
0009 } from '@angular/core';
0010 import * as THREE from 'three';
0011 
0012 import { ThreeService } from '../../services/three.service';
0013 import { MatIconButton } from "@angular/material/button";
0014 import { MatDialog, MatDialogClose, MatDialogRef } from "@angular/material/dialog";
0015 import { MatIcon } from "@angular/material/icon";
0016 import { MatTooltip } from "@angular/material/tooltip";
0017 import { MatMenuItem } from "@angular/material/menu";
0018 import { MatSlideToggle } from "@angular/material/slide-toggle";
0019 import { FormsModule } from "@angular/forms";
0020 
0021 import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter.js';
0022 
0023 @Component({
0024   selector: 'app-scene-export',
0025   templateUrl: './scene-export.html',
0026   styleUrls: ['./scene-export.scss'],
0027   changeDetection: ChangeDetectionStrategy.OnPush,
0028   imports: [
0029     MatIconButton,
0030     MatIcon,
0031     MatDialogClose,
0032     MatTooltip,
0033     MatMenuItem,
0034     MatSlideToggle,
0035     FormsModule,
0036   ]
0037 })
0038 export class SceneExportComponent {
0039   @ViewChild('openBtn', { read: ElementRef }) openBtn!: ElementRef;
0040   @ViewChild('dialogTemplate') dialogTemplate!: TemplateRef<any>;
0041   dialogRef: MatDialogRef<any> | null = null;
0042 
0043   // signal: cleared inside GLTFExporter's async callback, which schedules
0044   // no change detection under zoneless
0045   isExporting = signal(false);
0046   useBinaryFormat = true; // GLB by default
0047 
0048   constructor(
0049     private threeService: ThreeService,
0050     private dialog: MatDialog,
0051     private viewContainerRef: ViewContainerRef,
0052   ) {}
0053 
0054   openDialog(): void {
0055     if (this.dialogRef) {
0056       this.dialogRef.close();
0057       return;
0058     }
0059 
0060     const rect = this.openBtn.nativeElement.getBoundingClientRect();
0061     const dialogWidth = 280;
0062 
0063     const left = Math.max(rect.right - dialogWidth, 8);
0064     const top = rect.bottom + 12;
0065 
0066     this.dialogRef = this.dialog.open(this.dialogTemplate, {
0067       position: {
0068         top: `${top}px`,
0069         left: `${left}px`
0070       },
0071       hasBackdrop: false,
0072       panelClass: 'custom-position-dialog',
0073       autoFocus: false,
0074       viewContainerRef: this.viewContainerRef
0075     });
0076 
0077     this.dialogRef.afterClosed().subscribe(() => {
0078       this.dialogRef = null;
0079     });
0080   }
0081 
0082   exportFullScene(): void {
0083     const ext = this.useBinaryFormat ? 'glb' : 'gltf';
0084     this.exportToGLTF(this.threeService.scene, `firebird-scene.${ext}`);
0085   }
0086 
0087   exportGeometryOnly(): void {
0088     const ext = this.useBinaryFormat ? 'glb' : 'gltf';
0089     this.exportToGLTF(this.threeService.sceneGeometry, `firebird-geometry.${ext}`);
0090   }
0091 
0092   private exportToGLTF(object: THREE.Object3D, filename: string): void {
0093     if (this.isExporting()) return;
0094 
0095     this.isExporting.set(true);
0096     const exporter = new GLTFExporter();
0097 
0098     exporter.parse(
0099       object,
0100       (result) => {
0101         this.downloadFile(result, filename);
0102         this.isExporting.set(false);
0103         if (this.dialogRef) {
0104           this.dialogRef.close();
0105         }
0106       },
0107       (error) => {
0108         console.error('Error exporting scene:', error);
0109         this.isExporting.set(false);
0110       },
0111       { binary: this.useBinaryFormat }
0112     );
0113   }
0114 
0115   private downloadFile(data: ArrayBuffer | object, filename: string): void {
0116     let blob: Blob;
0117 
0118     if (data instanceof ArrayBuffer) {
0119       blob = new Blob([data], { type: 'application/octet-stream' });
0120     } else {
0121       const jsonString = JSON.stringify(data);
0122       blob = new Blob([jsonString], { type: 'application/json' });
0123     }
0124 
0125     const url = URL.createObjectURL(blob);
0126     const link = document.createElement('a');
0127     link.href = url;
0128     link.download = filename;
0129     link.click();
0130 
0131     URL.revokeObjectURL(url);
0132   }
0133 }