Warning, /firebird/firebird-ng/src/app/components/cube-viewport-control/cube-viewport-control.component.ts is written in an unsupported language. File is not indexed.
0001 // cube-viewport-control.component.ts
0002 import { Component, ElementRef, OnInit, OnDestroy, NgZone } from '@angular/core';
0003 import { GizmoOptions, ViewportGizmo } from 'three-viewport-gizmo';
0004 import { ThreeService } from '../../services/three.service';
0005 import {
0006 OrthographicCamera,
0007 PerspectiveCamera,
0008 Scene,
0009 WebGLRenderer
0010 } from 'three';
0011
0012 @Component({
0013 selector: 'app-cube-viewport-control',
0014 standalone: true,
0015 templateUrl: './cube-viewport-control.component.html',
0016 })
0017 export class CubeViewportControlComponent implements OnInit, OnDestroy {
0018 // References to externally provided objects
0019 public camera!: PerspectiveCamera | OrthographicCamera;
0020 public scene!: Scene;
0021 public renderer!: WebGLRenderer;
0022
0023 // The ViewportGizmo instance
0024 public gizmo!: ViewportGizmo;
0025
0026 private lastCamera!: PerspectiveCamera | OrthographicCamera;
0027 private animationFrameId: number | null = null;
0028
0029 constructor(
0030 private elRef: ElementRef,
0031 private threeService: ThreeService,
0032 private ngZone: NgZone
0033 ) {}
0034
0035 ngOnInit(): void {
0036 // We do NOT call initThreeJS() here.
0037 // The external scene/camera/renderer will be provided from outside.
0038 }
0039
0040 ngOnDestroy(): void {
0041 // Clean up animation frame on component destruction
0042 if (this.animationFrameId !== null) {
0043 cancelAnimationFrame(this.animationFrameId);
0044 }
0045
0046 // Clean up any event listeners
0047 this.threeService.controls.removeEventListener('change', this.handleControlsChange);
0048
0049 // Dispose of the gizmo if it exists
0050 if (this.gizmo) {
0051 this.gizmo.dispose();
0052 }
0053 }
0054
0055 /**
0056 * Called from the parent component (e.g. MainDisplayComponent) to link
0057 * the same scene/camera/renderer that are used for the main 3D view.
0058 */
0059 public initWithExternalScene(
0060 scene: Scene,
0061 camera: PerspectiveCamera | OrthographicCamera,
0062 renderer: WebGLRenderer
0063 ): void {
0064 this.scene = scene;
0065 this.camera = camera;
0066 this.renderer = renderer;
0067 this.lastCamera = camera;
0068
0069 const container = this.elRef.nativeElement.querySelector('.three-container');
0070 const gizmoConfig: GizmoOptions = {
0071 container: container,
0072 size: 90,
0073 type: 'cube',
0074 offset: { top: 85 },
0075 background: { color: 0x444444, hover: { color: 0x444444 } },
0076 corners: {
0077 color: 0x333333,
0078 hover: { color: 0x4bac84 },
0079 },
0080 front: { label: "Right" }, // Original left face
0081 left: { label: "Front" }, // Original back face
0082 back: { label: "Left" }, // Original right face
0083 right: { label: "Back" } // Original front face
0084 };
0085
0086 // Create gizmo with custom config (autoPlace = false)
0087 this.gizmo = new ViewportGizmo(this.camera, this.renderer, gizmoConfig);
0088
0089 // Bind the method to maintain 'this' context
0090 this.handleControlsChange = this.handleControlsChange.bind(this);
0091
0092 // Listen for any changes to OrbitControls
0093 this.threeService.controls.addEventListener('change', this.handleControlsChange);
0094
0095 // Start continuous update loop for the gizmo
0096 this.startGizmoUpdateLoop();
0097 }
0098
0099 private handleControlsChange = (): void => {
0100 this.updateGizmo();
0101 }
0102
0103 // Update the gizmo when controls change
0104 private updateGizmo(): void {
0105 if (!this.gizmo) return;
0106
0107 // Check if camera reference has changed
0108 const current = this.threeService.camera;
0109 if (current && current !== this.lastCamera) {
0110 this.lastCamera = current;
0111 this.camera = current;
0112 this.gizmo.camera = current;
0113 }
0114
0115 // Always update the gizmo to match camera orientation
0116 this.gizmo.cameraUpdate();
0117 }
0118
0119 // Start a continuous update loop to keep the gizmo in sync with camera
0120 private startGizmoUpdateLoop(): void {
0121 this.ngZone.runOutsideAngular(() => {
0122 const animate = () => {
0123 this.updateGizmo();
0124 this.animationFrameId = requestAnimationFrame(animate);
0125 };
0126 this.animationFrameId = requestAnimationFrame(animate);
0127 });
0128 }
0129 }