-
-
-
-
- JSON Output
-
-
- {{ generateJson() }}
-
-
+
+
+
+
+
+
+
+
+
+
+
+ {{ planePosition }} offset from center
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/app/particles/particles.component.scss b/frontend/src/app/particles/particles.component.scss
index ebb1f73..cf8954f 100644
--- a/frontend/src/app/particles/particles.component.scss
+++ b/frontend/src/app/particles/particles.component.scss
@@ -5,8 +5,7 @@
}
.renderer-container {
- width: 100%;
- height: 400px;
+ height: 1000px;
border: 1px solid #ccc;
border-radius: 4px;
overflow: hidden;
@@ -16,6 +15,18 @@
align-items: center;
}
+.side-column {
+ flex: 1;
+ flex-direction: column;
+ gap: 20px;
+}
+
+.middle-column {
+ flex: 2;
+ flex-direction: column;
+ gap: 20px;
+}
+
.plane-controls {
margin-top: 10px;
padding: 10px;
@@ -30,12 +41,6 @@
flex: 1;
}
-.controls-section {
- flex: 1;
- min-width: 300px;
- gap: 20px;
-}
-
.form-row {
margin-bottom: 15px;
}
@@ -43,86 +48,3 @@
mat-form-field {
width: 100%;
}
-
-.color-picker-card {
- margin-top: 20px;
-}
-
-.color-picker {
- display: flex;
- align-items: center;
- gap: 15px;
-}
-
-.color-picker input[type="color"] {
- width: 50px;
- height: 50px;
- border: none;
- border-radius: 4px;
- cursor: pointer;
-}
-
-.frames-section {
- margin-bottom: 20px;
-}
-
-.frames-container {
- margin-top: 10px;
-}
-
-.frame-content {
- padding: 15px;
-}
-
-.particles-list {
- max-height: 300px;
- overflow-y: auto;
- border: 1px solid #eee;
- border-radius: 4px;
- padding: 10px;
- margin-bottom: 15px;
-}
-
-.particle-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 8px;
- border-bottom: 1px solid #eee;
-}
-
-.particle-item:last-child {
- border-bottom: none;
-}
-
-.no-particles {
- padding: 20px;
- text-align: center;
- color: #888;
-}
-
-.frame-actions {
- display: flex;
- justify-content: flex-end;
- margin-top: 10px;
-}
-
-.add-frame {
- margin-top: 15px;
- display: flex;
- justify-content: center;
-}
-
-.json-output {
- margin-top: 20px;
-}
-
-.json-output pre {
- background-color: #f5f5f5;
- padding: 15px;
- border-radius: 4px;
- overflow-x: auto;
- max-height: 300px;
- font-family: monospace;
- white-space: pre-wrap;
-}
diff --git a/frontend/src/app/particles/particles.component.ts b/frontend/src/app/particles/particles.component.ts
index c769d1f..f78ea76 100644
--- a/frontend/src/app/particles/particles.component.ts
+++ b/frontend/src/app/particles/particles.component.ts
@@ -18,10 +18,12 @@ 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';
+import {PropertiesComponent} from './components/properties/properties.component';
+import {ParticleComponent} from './components/particle/particle.component';
+import {FramesComponent} from './components/frames/frames.component';
+import {MatSnackBar} from '@angular/material/snack-bar';
@Component({
selector: 'app-particles',
@@ -39,7 +41,10 @@ import {ParticleData, ParticleType} from './models/particle.model';
MatTabsModule,
MatCardModule,
MatIconModule,
- HeaderComponent
+ HeaderComponent,
+ PropertiesComponent,
+ ParticleComponent,
+ FramesComponent,
],
templateUrl: './particles.component.html',
styleUrl: './particles.component.scss'
@@ -48,16 +53,13 @@ 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
+ private matSnackBar: MatSnackBar,
) {
}
@@ -131,41 +133,6 @@ export class ParticlesComponent implements OnInit, AfterViewInit, OnDestroy {
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
*/
@@ -179,19 +146,6 @@ export class ParticlesComponent implements OnInit, AfterViewInit, OnDestroy {
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
@@ -200,17 +154,9 @@ export class ParticlesComponent implements OnInit, AfterViewInit, OnDestroy {
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);
+ public copyJson() {
+ navigator.clipboard.writeText(this.generateJson()).then(() => {
+ this.matSnackBar.open('Copied to clipboard', '', {duration: 2000})
+ });
}
}
diff --git a/frontend/src/styles.scss b/frontend/src/styles.scss
index 032cac3..c7b4650 100644
--- a/frontend/src/styles.scss
+++ b/frontend/src/styles.scss
@@ -1,4 +1,5 @@
@import '@angular/material/prebuilt-themes/azure-blue.css';
+@import url('https://fonts.googleapis.com/icon?family=Material+Icons');
:root {
--white: #FFFFFF;