2025-06-21 22:40:16 +00:00
|
|
|
<app-header current_page="particles" height="200px" background_image="/public/img/backgrounds/staff.png"
|
|
|
|
|
[overlay_gradient]="0.5">
|
|
|
|
|
<div class="title" header-content>
|
|
|
|
|
<h1>Particle Creator</h1>
|
|
|
|
|
</div>
|
|
|
|
|
</app-header>
|
|
|
|
|
|
|
|
|
|
<main>
|
|
|
|
|
<section class="darkmodeSection">
|
|
|
|
|
<section class="column">
|
|
|
|
|
<div class="renderer-section row column">
|
|
|
|
|
<div #rendererContainer class="renderer-container column row"></div>
|
|
|
|
|
<div class="plane-controls">
|
|
|
|
|
<label>Plane Position (Z-axis):</label>
|
2025-06-22 15:59:29 +00:00
|
|
|
<mat-slider [min]="minOffset" [max]="maxOffset" step="1" #planeSlider>
|
2025-06-21 22:40:16 +00:00
|
|
|
<input matSliderThumb [(ngModel)]="planePosition" (input)="updatePlanePosition($event)">
|
|
|
|
|
</mat-slider>
|
2025-06-22 15:59:29 +00:00
|
|
|
<span>{{ planePosition }} offset from center</span>
|
2025-06-21 22:40:16 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="row">
|
|
|
|
|
<div class="column controls-section">
|
|
|
|
|
<mat-card>
|
|
|
|
|
<mat-card-header>
|
|
|
|
|
<mat-card-title>Particle Properties</mat-card-title>
|
|
|
|
|
</mat-card-header>
|
|
|
|
|
<mat-card-content>
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<mat-form-field appearance="outline">
|
|
|
|
|
<mat-label>Particle Name</mat-label>
|
|
|
|
|
<input matInput [(ngModel)]="particleData.particle_name" placeholder="Enter particle name">
|
|
|
|
|
</mat-form-field>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<mat-form-field appearance="outline">
|
|
|
|
|
<mat-label>Display Name</mat-label>
|
|
|
|
|
<input matInput [(ngModel)]="particleData.display_name" placeholder="Enter display name">
|
|
|
|
|
</mat-form-field>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<mat-form-field appearance="outline">
|
|
|
|
|
<mat-label>Particle Type</mat-label>
|
|
|
|
|
<mat-select [(ngModel)]="particleData.particle_type">
|
|
|
|
|
<mat-option *ngFor="let type of particleTypes" [value]="type">{{ type }}</mat-option>
|
|
|
|
|
</mat-select>
|
|
|
|
|
</mat-form-field>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<mat-form-field appearance="outline">
|
|
|
|
|
<mat-label>Lore</mat-label>
|
|
|
|
|
<textarea matInput [(ngModel)]="particleData.lore" placeholder="Enter lore"></textarea>
|
|
|
|
|
</mat-form-field>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<mat-form-field appearance="outline">
|
|
|
|
|
<mat-label>Display Item</mat-label>
|
|
|
|
|
<input matInput [(ngModel)]="particleData.display_item" placeholder="Enter display item">
|
|
|
|
|
</mat-form-field>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<mat-form-field appearance="outline">
|
|
|
|
|
<mat-label>Permission</mat-label>
|
|
|
|
|
<input matInput [(ngModel)]="particleData.permission" placeholder="Enter permission">
|
|
|
|
|
</mat-form-field>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<mat-form-field appearance="outline">
|
|
|
|
|
<mat-label>Package Permission</mat-label>
|
|
|
|
|
<input matInput [(ngModel)]="particleData.package_permission" placeholder="Enter package permission">
|
|
|
|
|
</mat-form-field>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<mat-form-field appearance="outline">
|
|
|
|
|
<mat-label>Frame Delay</mat-label>
|
|
|
|
|
<input matInput type="number" [(ngModel)]="particleData.frame_delay" placeholder="Enter frame delay">
|
|
|
|
|
</mat-form-field>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<mat-form-field appearance="outline">
|
|
|
|
|
<mat-label>Repeat</mat-label>
|
|
|
|
|
<input matInput type="number" [(ngModel)]="particleData.repeat" placeholder="Enter repeat count">
|
|
|
|
|
</mat-form-field>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<mat-form-field appearance="outline">
|
|
|
|
|
<mat-label>Repeat Delay</mat-label>
|
|
|
|
|
<input matInput type="number" [(ngModel)]="particleData.repeat_delay"
|
|
|
|
|
placeholder="Enter repeat delay">
|
|
|
|
|
</mat-form-field>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<mat-form-field appearance="outline">
|
|
|
|
|
<mat-label>Random Offset</mat-label>
|
|
|
|
|
<input matInput type="number" [(ngModel)]="particleData.random_offset"
|
|
|
|
|
placeholder="Enter random offset">
|
|
|
|
|
</mat-form-field>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<mat-checkbox [(ngModel)]="particleData.stationary">Stationary</mat-checkbox>
|
|
|
|
|
</div>
|
|
|
|
|
</mat-card-content>
|
|
|
|
|
</mat-card>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="column">
|
|
|
|
|
<mat-card class="color-picker-card">
|
|
|
|
|
<mat-card-header>
|
|
|
|
|
<mat-card-title>Particle Color</mat-card-title>
|
|
|
|
|
</mat-card-header>
|
|
|
|
|
<mat-card-content>
|
|
|
|
|
<div class="color-picker">
|
|
|
|
|
<input type="color" [(ngModel)]="selectedColor">
|
|
|
|
|
<span>Selected Color: {{ selectedColor }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</mat-card-content>
|
|
|
|
|
</mat-card>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="column frames-section">
|
|
|
|
|
<mat-card>
|
|
|
|
|
<mat-card-header>
|
|
|
|
|
<mat-card-title>Frames</mat-card-title>
|
|
|
|
|
</mat-card-header>
|
|
|
|
|
<mat-card-content>
|
|
|
|
|
<div class="frames-container">
|
|
|
|
|
<mat-tab-group [selectedIndex]="frames.indexOf(currentFrame)"
|
|
|
|
|
(selectedIndexChange)="switchFrame(frames[$event])">
|
|
|
|
|
<mat-tab *ngFor="let frameId of frames" [label]="frameId">
|
|
|
|
|
<div class="frame-content">
|
|
|
|
|
<h3>Particles in {{ frameId }}</h3>
|
|
|
|
|
<div class="particles-list">
|
|
|
|
|
<div *ngFor="let particle of particleData.frames[frameId]; let i = index" class="particle-item">
|
|
|
|
|
<span>Particle {{ i + 1 }}: ({{ particle.x.toFixed(2) }}, {{ particle.y.toFixed(2) }}
|
|
|
|
|
, {{ particle.z.toFixed(2) }})</span>
|
|
|
|
|
<button mat-icon-button color="warn" (click)="removeParticle(frameId, i)">
|
|
|
|
|
<mat-icon>delete</mat-icon>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div *ngIf="!particleData.frames[frameId] || particleData.frames[frameId].length === 0"
|
|
|
|
|
class="no-particles">
|
|
|
|
|
No particles in this frame. Click on the plane to add particles.
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="frame-actions">
|
|
|
|
|
<button mat-raised-button color="warn" (click)="removeFrame(frameId)"
|
|
|
|
|
[disabled]="frames.length <= 1">
|
|
|
|
|
Remove Frame
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</mat-tab>
|
|
|
|
|
</mat-tab-group>
|
|
|
|
|
<div class="add-frame">
|
|
|
|
|
<button mat-raised-button color="primary" (click)="addFrame()">
|
|
|
|
|
Add New Frame
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</mat-card-content>
|
|
|
|
|
</mat-card>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="column json-output">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<mat-card>
|
|
|
|
|
<mat-card-header>
|
|
|
|
|
<mat-card-title>JSON Output</mat-card-title>
|
|
|
|
|
</mat-card-header>
|
|
|
|
|
<mat-card-content>
|
|
|
|
|
<pre>{{ generateJson() }}</pre>
|
|
|
|
|
</mat-card-content>
|
|
|
|
|
</mat-card>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
</section>
|
|
|
|
|
</main>
|