Add toggle for enabling/disabling grid snap in RenderContainerComponent and update snapping logic.

This commit is contained in:
akastijn 2026-01-19 23:51:50 +01:00
parent 984bbae7e3
commit b7fe37d9c4
4 changed files with 28 additions and 3 deletions

View File

@ -35,6 +35,11 @@
[matTooltip]="gridVisible ? 'Hide grid' : 'Show grid'"> [matTooltip]="gridVisible ? 'Hide grid' : 'Show grid'">
<mat-icon>{{ gridVisible ? 'grid_off' : 'grid_on' }}</mat-icon> <mat-icon>{{ gridVisible ? 'grid_off' : 'grid_on' }}</mat-icon>
</button> </button>
<button mat-mini-fab color="primary" (click)="gridSnapEnabled = !gridSnapEnabled"
[matTooltip]="gridSnapEnabled ? 'Disable grid snap' : 'Enable grid snap'">
<mat-icon>{{ gridSnapEnabled ? 'push_pin' : 'pinch' }}</mat-icon>
</button>
</div> </div>
@if (isPlaneLocked) { @if (isPlaneLocked) {

View File

@ -103,6 +103,15 @@ export class RenderContainerComponent implements AfterViewInit, OnDestroy {
this.intersectionPlaneService.setGridDensity(d); this.intersectionPlaneService.setGridDensity(d);
} }
// Grid snap proxies
public get gridSnapEnabled(): boolean {
return this.intersectionPlaneService.getGridSnapEnabled();
}
public set gridSnapEnabled(v: boolean) {
this.intersectionPlaneService.setGridSnapEnabled(v);
}
/** /**
* Toggle the plane locked state * Toggle the plane locked state
*/ */

View File

@ -32,6 +32,7 @@ export class IntersectionPlaneService {
private gridHelper?: THREE.GridHelper; private gridHelper?: THREE.GridHelper;
private gridVisible: boolean = true; private gridVisible: boolean = true;
private gridDensity: number = 4; private gridDensity: number = 4;
private gridSnapEnabled: boolean = true;
// Emits whenever plane position, orientation, or lock-affecting orientation updates change visuals // Emits whenever plane position, orientation, or lock-affecting orientation updates change visuals
public readonly planeChanged$ = new Subject<void>(); public readonly planeChanged$ = new Subject<void>();
@ -111,6 +112,14 @@ export class IntersectionPlaneService {
return this.gridDensity; return this.gridDensity;
} }
public setGridSnapEnabled(enabled: boolean): void {
this.gridSnapEnabled = enabled;
}
public getGridSnapEnabled(): boolean {
return this.gridSnapEnabled;
}
/** /**
* Creates the intersection plane and adds it to the scene * Creates the intersection plane and adds it to the scene
*/ */

View File

@ -57,9 +57,11 @@ export class ParticleManagerService {
const divisions = Math.max(1, Math.floor(planeSize * this.intersectionPlaneService.getGridDensity())); const divisions = Math.max(1, Math.floor(planeSize * this.intersectionPlaneService.getGridDensity()));
const gridStepPlane = planeSize / divisions; const gridStepPlane = planeSize / divisions;
if (this.intersectionPlaneService.getGridSnapEnabled()) {
x = Math.round(x / gridStepPlane) * gridStepPlane; x = Math.round(x / gridStepPlane) * gridStepPlane;
y = Math.round(y / gridStepPlane) * gridStepPlane; y = Math.round(y / gridStepPlane) * gridStepPlane;
z = Math.round(z / gridStepPlane) * gridStepPlane; z = Math.round(z / gridStepPlane) * gridStepPlane;
}
// Create a visual representation of the particle // Create a visual representation of the particle
const particleGeometry = new THREE.SphereGeometry(0.03 * this.selectedSize, 16, 16); const particleGeometry = new THREE.SphereGeometry(0.03 * this.selectedSize, 16, 16);
const particleMaterial = new THREE.MeshBasicMaterial({color: this.selectedColor}); const particleMaterial = new THREE.MeshBasicMaterial({color: this.selectedColor});