AltitudeWeb/frontend/src/app/particles/particles.component.ts

217 lines
5.7 KiB
TypeScript
Raw Normal View History

import {AfterViewInit, Component, ElementRef, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {CommonModule} from '@angular/common';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button';
import {MatInputModule} from '@angular/material/input';
import {MatFormFieldModule} from '@angular/material/form-field';
import {MatSelectModule} from '@angular/material/select';
import {MatSliderModule} from '@angular/material/slider';
import {MatCheckboxModule} from '@angular/material/checkbox';
import {MatTabsModule} from '@angular/material/tabs';
import {MatCardModule} from '@angular/material/card';
import {MatIconModule} from '@angular/material/icon';
import {HeaderComponent} from '../header/header.component';
// Services
import {RendererService} from './services/renderer.service';
import {PlayerModelService} from './services/player-model.service';
import {IntersectionPlaneService} from './services/intersection-plane.service';
import {ParticleManagerService} from './services/particle-manager.service';
import {InputHandlerService} from './services/input-handler.service';
import {FrameManagerService} from './services/frame-manager.service';
// Models
import {ParticleData, ParticleType} from './models/particle.model';
@Component({
selector: 'app-particles',
standalone: true,
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatSelectModule,
MatSliderModule,
MatCheckboxModule,
MatTabsModule,
MatCardModule,
MatIconModule,
HeaderComponent
],
templateUrl: './particles.component.html',
styleUrl: './particles.component.scss'
})
export class ParticlesComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('rendererContainer') rendererContainer!: ElementRef;
@ViewChild('planeSlider') planeSlider!: ElementRef;
// UI state
public particleTypes = Object.values(ParticleType);
constructor(
private rendererService: RendererService,
private playerModelService: PlayerModelService,
private intersectionPlaneService: IntersectionPlaneService,
private particleManagerService: ParticleManagerService,
private inputHandlerService: InputHandlerService,
private frameManagerService: FrameManagerService
) {
}
/**
* Initialize component
*/
ngOnInit(): void {
// No initialization needed here
}
/**
* Initialize Three.js scene after view is initialized
*/
ngAfterViewInit(): void {
this.initializeScene();
this.animate();
}
/**
* Clean up resources when component is destroyed
*/
ngOnDestroy(): void {
// Clean up event listeners
if (this.rendererService.renderer) {
this.inputHandlerService.cleanup(this.rendererService.renderer.domElement);
}
}
/**
* Initialize the 3D scene and all related components
*/
private initializeScene(): void {
// Initialize renderer
this.rendererService.initializeRenderer(this.rendererContainer);
// Create player model
this.playerModelService.createPlayerModel();
// Create intersection plane
this.intersectionPlaneService.createIntersectionPlane();
// Initialize input handlers
this.inputHandlerService.initializeInputHandlers(this.rendererService.renderer.domElement);
}
/**
* Update plane position based on slider
*/
public updatePlanePosition(event: Event): void {
const slider = event.target as HTMLInputElement;
const value = Number(slider.value);
this.intersectionPlaneService.updatePlanePosition(value);
}
/**
* Get the current plane position
*/
public get planePosition(): number {
return this.intersectionPlaneService.getPlanePosition();
}
public set planePosition(newPlanePosition: number) {
this.intersectionPlaneService.updatePlanePosition(newPlanePosition);
}
public get maxOffset(): number {
return this.intersectionPlaneService.getMaxOffset();
}
public get minOffset(): number {
return this.intersectionPlaneService.getMinOffset();
}
/**
* Get the selected color
*/
public get selectedColor(): string {
return this.particleManagerService.getSelectedColor();
}
/**
* Set the selected color
*/
public set selectedColor(color: string) {
this.particleManagerService.setSelectedColor(color);
}
/**
* Get the particle data
*/
public get particleData(): ParticleData {
return this.particleManagerService.getParticleData();
}
/**
* Get the current frame
*/
public get currentFrame(): string {
return this.particleManagerService.getCurrentFrame();
}
/**
* Get all frames
*/
public get frames(): string[] {
return this.particleManagerService.getFrames();
}
/**
* Animation loop
*/
private animate(): void {
requestAnimationFrame(this.animate.bind(this));
// Update plane orientation based on camera position
this.intersectionPlaneService.updatePlaneOrientation(this.rendererService.camera);
// Render the scene
this.rendererService.render();
}
/**
* Add a new frame
*/
public addFrame(): void {
this.frameManagerService.addFrame();
}
/**
* Switch to a different frame
*/
public switchFrame(frameId: string): void {
this.frameManagerService.switchFrame(frameId);
}
/**
* Generate JSON output
*/
public generateJson(): string {
return this.particleManagerService.generateJson();
}
/**
* Remove a particle
*/
public removeParticle(frameId: string, index: number): void {
this.particleManagerService.removeParticle(frameId, index);
}
/**
* Remove a frame
*/
public removeFrame(frameId: string): void {
this.frameManagerService.removeFrame(frameId);
}
}