Add modular services for Three.js integration in ParticlesComponent
Implemented dedicated Angular services (e.g., RendererService, InputHandlerService, PlayerModelService) to modularize and simplify Three.js integration within the `ParticlesComponent`. Refactored component logic to delegate rendering, input handling, and model creation to respective services. Updated particle data models and removed redundant logic from the component.
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import * as THREE from 'three';
|
||||
import { RendererService } from './renderer.service';
|
||||
import { ParticleData, ParticleInfo, ParticleType } from '../models/particle.model';
|
||||
|
||||
/**
|
||||
* Service responsible for managing particles in the scene
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ParticleManagerService {
|
||||
private particles: THREE.Mesh[] = [];
|
||||
private particleData: ParticleData = {
|
||||
particle_name: '',
|
||||
display_name: '',
|
||||
particle_type: ParticleType.REDSTONE,
|
||||
lore: '',
|
||||
display_item: 'REDSTONE',
|
||||
permission: '',
|
||||
package_permission: '',
|
||||
frame_delay: 1,
|
||||
repeat: 1,
|
||||
repeat_delay: 0,
|
||||
random_offset: 0,
|
||||
stationary: true,
|
||||
frames: {
|
||||
'frame1': []
|
||||
}
|
||||
};
|
||||
private currentFrame: string = 'frame1';
|
||||
private frames: string[] = ['frame1'];
|
||||
private selectedColor: string = '#ff0000';
|
||||
|
||||
constructor(private rendererService: RendererService) {}
|
||||
|
||||
/**
|
||||
* Adds a particle at the specified position
|
||||
*/
|
||||
addParticle(x: number, y: number, z: number): void {
|
||||
// Create a visual representation of the particle
|
||||
const particleGeometry = new THREE.SphereGeometry(0.03, 16, 16);
|
||||
const particleMaterial = new THREE.MeshBasicMaterial({color: this.selectedColor});
|
||||
const particleMesh = new THREE.Mesh(particleGeometry, particleMaterial);
|
||||
|
||||
particleMesh.position.set(x, y, z);
|
||||
this.rendererService.scene.add(particleMesh);
|
||||
this.particles.push(particleMesh);
|
||||
|
||||
// Add to particle data
|
||||
const hexColor = this.selectedColor.replace('#', '');
|
||||
const r = parseInt(hexColor.substring(0, 2), 16) / 255;
|
||||
const g = parseInt(hexColor.substring(2, 4), 16) / 255;
|
||||
const b = parseInt(hexColor.substring(4, 6), 16) / 255;
|
||||
|
||||
const particleInfo: ParticleInfo = {
|
||||
particle_type: ParticleType.REDSTONE,
|
||||
x: x,
|
||||
y: y,
|
||||
z: z,
|
||||
color: `${r},${g},${b}`,
|
||||
extra: 1
|
||||
};
|
||||
|
||||
if (!this.particleData.frames[this.currentFrame]) {
|
||||
this.particleData.frames[this.currentFrame] = [];
|
||||
}
|
||||
|
||||
this.particleData.frames[this.currentFrame].push(particleInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all particle visuals from the scene
|
||||
*/
|
||||
clearParticleVisuals(): void {
|
||||
for (const particle of this.particles) {
|
||||
this.rendererService.scene.remove(particle);
|
||||
}
|
||||
this.particles = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders particles for a specific frame
|
||||
*/
|
||||
renderFrameParticles(frameId: string): void {
|
||||
if (!this.particleData.frames[frameId]) return;
|
||||
|
||||
for (const particleInfo of this.particleData.frames[frameId]) {
|
||||
const particleGeometry = new THREE.SphereGeometry(0.03, 16, 16);
|
||||
|
||||
// Parse color
|
||||
const colorParts = particleInfo.color.split(',');
|
||||
const color = new THREE.Color(
|
||||
parseFloat(colorParts[0]),
|
||||
parseFloat(colorParts[1]),
|
||||
parseFloat(colorParts[2])
|
||||
);
|
||||
|
||||
const particleMaterial = new THREE.MeshBasicMaterial({color});
|
||||
const particleMesh = new THREE.Mesh(particleGeometry, particleMaterial);
|
||||
|
||||
particleMesh.position.set(particleInfo.x, particleInfo.y, particleInfo.z);
|
||||
this.rendererService.scene.add(particleMesh);
|
||||
this.particles.push(particleMesh);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a particle from a specific frame
|
||||
*/
|
||||
removeParticle(frameId: string, index: number): void {
|
||||
if (this.particleData.frames[frameId] && this.particleData.frames[frameId].length > index) {
|
||||
this.particleData.frames[frameId].splice(index, 1);
|
||||
|
||||
// Update visuals if this is the current frame
|
||||
if (frameId === this.currentFrame) {
|
||||
this.clearParticleVisuals();
|
||||
this.renderFrameParticles(frameId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the selected color for new particles
|
||||
*/
|
||||
setSelectedColor(color: string): void {
|
||||
this.selectedColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selected color
|
||||
*/
|
||||
getSelectedColor(): string {
|
||||
return this.selectedColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the particle data
|
||||
*/
|
||||
getParticleData(): ParticleData {
|
||||
return this.particleData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the particle data
|
||||
*/
|
||||
setParticleData(data: ParticleData): void {
|
||||
this.particleData = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current frame
|
||||
*/
|
||||
getCurrentFrame(): string {
|
||||
return this.currentFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current frame
|
||||
*/
|
||||
setCurrentFrame(frameId: string): void {
|
||||
this.currentFrame = frameId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all frames
|
||||
*/
|
||||
getFrames(): string[] {
|
||||
return this.frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all frames
|
||||
*/
|
||||
setFrames(frames: string[]): void {
|
||||
this.frames = frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates JSON output of the particle data
|
||||
*/
|
||||
generateJson(): string {
|
||||
return JSON.stringify(this.particleData, null, 2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user