Warning, /firebird/packages/firebird-ng/display/src/lib/components/tool-panel/tool-panel.component.ts is written in an unsupported language. File is not indexed.
0001 import { Component, Output, EventEmitter, ChangeDetectionStrategy, Signal, inject } from '@angular/core';
0002 import { NgIf } from '@angular/common';
0003 import { toSignal } from '@angular/core/rxjs-interop';
0004 import { MatIcon } from '@angular/material/icon';
0005 import { ViewOptionsComponent } from '../view-options/view-options.component';
0006 import { ThreeService } from '../../services/three.service';
0007 import { ConfigService } from '@dexvis/app-features';
0008 import {MatIconButton} from "@angular/material/button";
0009 import {MatTooltip} from "@angular/material/tooltip";
0010 import * as THREE from 'three';
0011
0012
0013 @Component({
0014 selector: 'app-tool-panel',
0015 imports: [
0016 NgIf,
0017 MatIcon,
0018 ViewOptionsComponent,
0019 MatIconButton,
0020 MatTooltip,
0021
0022 ],
0023 templateUrl: './tool-panel.component.html',
0024 changeDetection: ChangeDetectionStrategy.OnPush,
0025 styleUrls: ['./tool-panel.component.scss']
0026 })
0027 export class ToolPanelComponent {
0028 @Output() cameraControlsToggle = new EventEmitter<void>();
0029
0030 isCollapsed = false;
0031
0032 /** Factor to zoom by. */
0033 private zoomFactor = 1.1;
0034 /** Whether camera is orthographic or perspective. */
0035 private orthographicView = false;
0036
0037 /**
0038 * Draw event data over geometry regardless of depth — tracks stay visible
0039 * from every camera angle instead of hiding behind detector volumes.
0040 * Config-backed (`display.tracksOnTop`), so the mode is deep-linkable and
0041 * survives reloads; EventDisplayService applies it to the main view.
0042 */
0043 private tracksOnTopProperty = inject(ConfigService).getConfigOrCreate<boolean>('display.tracksOnTop', false);
0044 tracksOnTop: Signal<boolean> = toSignal(this.tracksOnTopProperty.subject, { requireSync: true });
0045
0046 toggleTracksOnTop() {
0047 this.tracksOnTopProperty.value = !this.tracksOnTopProperty.value;
0048 }
0049
0050 constructor(
0051 private threeService: ThreeService // no more EventDisplayService
0052 ) {}
0053
0054 /**
0055 * Zoom in or out around the orbit controls target.
0056 * Use OrbitControls or direct camera logic from threeService.
0057 */
0058 private zoomTo(factor: number): void {
0059 const controls = this.threeService.controls;
0060 const cam = this.threeService.camera as THREE.Camera;
0061
0062 // Ensure matrices are up to date
0063 cam.updateMatrixWorld(true);
0064
0065 const target = controls.target;
0066
0067 if ((cam as any).isOrthographicCamera) {
0068 const ortho = cam as THREE.OrthographicCamera;
0069 const newZoom = ortho.zoom / Math.max(1e-6, factor);
0070
0071 ortho.zoom = THREE.MathUtils.clamp(newZoom, 0.01, 1e5);
0072 ortho.updateProjectionMatrix();
0073
0074 } else if ((cam as any).isPerspectiveCamera) {
0075 const persp = cam as THREE.PerspectiveCamera;
0076
0077 const dir = new THREE.Vector3().subVectors(persp.position, target).normalize();
0078 const dist = persp.position.distanceTo(target);
0079
0080 let newDist = dist * factor;
0081
0082 const minD = (controls as any).minDistance ?? 0.001;
0083 const maxD = (controls as any).maxDistance ?? Infinity;
0084 newDist = THREE.MathUtils.clamp(newDist, minD, maxD);
0085
0086 const newPos = new THREE.Vector3().copy(target).addScaledVector(dir, newDist);
0087 persp.position.copy(newPos);
0088
0089 persp.lookAt(target);
0090 }
0091
0092 controls.update();
0093 }
0094
0095 onLeftClick(event: MouseEvent, action: string) {
0096 // Only respond to left-button
0097 if (event.button === 0) {
0098 if (action === 'zoomIn') {
0099 this.zoomIn();
0100 } else if (action === 'zoomOut') {
0101 this.zoomOut();
0102 }
0103 }
0104 }
0105
0106 zoomIn() {
0107 this.zoomTo(1 / this.zoomFactor);
0108 }
0109
0110 zoomOut() {
0111 this.zoomTo(this.zoomFactor);
0112 }
0113
0114 clearZoom() {
0115 // If you had logic for continuous zoom while mouse is held, you can clear it here
0116 }
0117
0118 togglePanel() {
0119 this.isCollapsed = !this.isCollapsed;
0120 }
0121
0122 /**
0123 * Switch between orthographic and perspective camera.
0124 * You can define a method in ThreeService to do the actual swap or toggling.
0125 */
0126 switchMainView() {
0127 this.orthographicView = !this.orthographicView;
0128 this.threeService.toggleOrthographicView(this.orthographicView);
0129 }
0130
0131 onCameraControlsToggle() {
0132 this.cameraControlsToggle.emit();
0133 }
0134 }