Skip to content

Commit 9a51990

Browse files
committed
adaptive
1 parent 15a65ff commit 9a51990

File tree

10 files changed

+370
-156
lines changed

10 files changed

+370
-156
lines changed

libs/core/src/lib/store.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
import { DOCUMENT } from '@angular/common';
2-
import { ElementRef, InjectionToken, Injector, Optional, SkipSelf, effect, runInInjectionContext } from '@angular/core';
2+
import {
3+
ChangeDetectorRef,
4+
ElementRef,
5+
InjectionToken,
6+
Injector,
7+
Optional,
8+
SkipSelf,
9+
effect,
10+
inject,
11+
runInInjectionContext,
12+
} from '@angular/core';
313
import { Subject, type Observable } from 'rxjs';
414
import * as THREE from 'three';
515
import type { NgtCamera, NgtDomEvent, NgtEventManager, NgtPointerCaptureTarget, NgtThreeEvent } from './events';
@@ -8,6 +18,7 @@ import { NGT_LOOP, type NgtLoop } from './loop';
818
import { createInjectionToken } from './utils/create-injection-token';
919
import { is } from './utils/is';
1020
import { makeDpr } from './utils/make';
21+
import { safeDetectChanges } from './utils/safe-detect-changes';
1122
import { signalStore, type NgtSignalStore } from './utils/signal-store';
1223
import { updateCamera } from './utils/update';
1324

@@ -152,6 +163,8 @@ function storeFactory(loop: NgtLoop, document: Document, injector: Injector, par
152163
throw new Error(`[NGT] Window is not available.`);
153164
}
154165

166+
const cdr = inject(ChangeDetectorRef);
167+
155168
// NOTE: using Subject because we do not care about late-subscribers
156169
const pointerMissed$ = new Subject<MouseEvent>();
157170

@@ -225,11 +238,12 @@ function storeFactory(loop: NgtLoop, document: Document, injector: Injector, par
225238
// Set lower bound performance
226239
if (state.performance.current !== state.performance.min)
227240
setPerformanceCurrent(state.performance.min);
241+
228242
// Go back to upper bound performance after a while unless something regresses meanwhile
229-
performanceTimeout = setTimeout(
230-
() => setPerformanceCurrent(get('performance', 'max')),
231-
state.performance.debounce,
232-
);
243+
performanceTimeout = setTimeout(() => {
244+
setPerformanceCurrent(get('performance', 'max'));
245+
safeDetectChanges(cdr);
246+
}, state.performance.debounce);
233247
},
234248
},
235249

libs/soba/controls/src/orbit-controls/orbit-controls.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,9 @@ export class NgtsOrbitControls {
8080

8181
private store = injectNgtStore();
8282
private invalidate = this.store.select('invalidate');
83-
private performance = this.store.select('performance');
83+
private performanceRegress = this.store.select('performance', 'regress');
8484
private defaultCamera = this.store.select('camera');
8585
private glDomElement = this.store.select('gl', 'domElement');
86-
8786
private regress = this.inputs.select('regress');
8887
private camera = this.inputs.select('camera');
8988
private domElement = this.inputs.select('domElement');
@@ -157,16 +156,16 @@ export class NgtsOrbitControls {
157156

158157
private setEvents() {
159158
effect((onCleanup) => {
160-
const [controls, invalidate, performance, regress] = [
159+
const [controls, invalidate, performanceRegress, regress] = [
161160
this.controlsRef.nativeElement,
162161
this.invalidate(),
163-
this.performance(),
162+
this.performanceRegress(),
164163
this.regress(),
165164
];
166165
if (!controls) return;
167166
const changeCallback: (e: THREE.Event) => void = (e) => {
168167
invalidate();
169-
if (regress) performance.regress();
168+
if (regress) performanceRegress();
170169
if (this.change.observed) this.change.emit(e);
171170
};
172171

libs/soba/performances/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# angular-three-soba/performances
2+
3+
Secondary entry point of `angular-three-soba`. It can be used by importing from `angular-three-soba/performances`.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"lib": {
3+
"entryFile": "src/index.ts"
4+
}
5+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Directive, Input, effect, signal, untracked } from '@angular/core';
2+
import { injectNgtStore } from 'angular-three';
3+
4+
@Directive({ selector: 'ngts-adaptive-dpr', standalone: true })
5+
export class NgtsAdaptiveDpr {
6+
private pixelated = signal(false);
7+
@Input({ alias: 'pixelated' }) set _pixelated(pixelated: boolean) {
8+
this.pixelated.set(pixelated);
9+
}
10+
11+
private store = injectNgtStore();
12+
private current = this.store.select('performance', 'current');
13+
private active = this.store.get('internal', 'active');
14+
private setDpr = this.store.get('setDpr');
15+
private initialDpr = this.store.get('viewport', 'initialDpr');
16+
private domElement = this.store.get('gl', 'domElement');
17+
18+
constructor() {
19+
effect((onCleanup) => {
20+
onCleanup(() => {
21+
if (this.active) {
22+
this.setDpr(this.initialDpr);
23+
}
24+
if (this.pixelated() && this.domElement) {
25+
this.domElement.style.imageRendering = 'auto';
26+
}
27+
});
28+
});
29+
30+
effect(() => {
31+
const current = this.current();
32+
this.setDpr(current * this.initialDpr);
33+
if (untracked(this.pixelated) && this.domElement) {
34+
this.domElement.style.imageRendering = current === 1 ? 'auto' : 'pixelated';
35+
}
36+
});
37+
}
38+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Directive, effect } from '@angular/core';
2+
import { injectNgtStore } from 'angular-three';
3+
4+
@Directive({ selector: 'ngts-adaptive-events', standalone: true })
5+
export class NgtsAdaptiveEvents {
6+
private store = injectNgtStore();
7+
private setEvents = this.store.get('setEvents');
8+
private current = this.store.select('performance', 'current');
9+
10+
constructor() {
11+
effect((onCleanup) => {
12+
const enabled = this.store.get('events', 'enabled');
13+
onCleanup(() => {
14+
this.setEvents({ enabled });
15+
});
16+
});
17+
18+
effect(() => {
19+
const current = this.current();
20+
this.setEvents({ enabled: current === 1 });
21+
});
22+
}
23+
}

libs/soba/performances/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './adaptive-dpr/adaptive-dpr';
2+
export * from './adaptive-events/adaptive-events';

0 commit comments

Comments
 (0)