Skip to content

Commit 13e69aa

Browse files
committed
chore: more clean up
1 parent 7276467 commit 13e69aa

File tree

14 files changed

+104
-110
lines changed

14 files changed

+104
-110
lines changed

apps/example/src/app/scene/blue-scene.component.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,34 @@
11
import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, inject, ViewChild } from '@angular/core';
22
import { injectBeforeRender, NgtStore } from 'angular-three';
3+
import { CursorPointer } from './cursor';
34

45
@Component({
56
standalone: true,
67
template: `
78
<ngt-spot-light [position]="5" />
89
<ngt-point-light [position]="-5" />
910
10-
<ngt-mesh #cube>
11+
<ngt-mesh #cube cursorPointer (pointerover)="hovered = true" (pointerout)="hovered = false">
1112
<ngt-icosahedron-geometry />
12-
<ngt-mesh-standard-material color="blue" />
13+
<ngt-mesh-standard-material [color]="hovered ? 'green' : 'blue'" />
1314
</ngt-mesh>
1415
`,
16+
imports: [CursorPointer],
1517
schemas: [CUSTOM_ELEMENTS_SCHEMA],
1618
})
1719
export default class BlueScene {
1820
@ViewChild('cube', { static: true }) cube!: ElementRef<THREE.Mesh>;
1921

2022
readonly store = inject(NgtStore);
2123

24+
hovered = false;
25+
2226
constructor() {
2327
injectBeforeRender(({ clock }) => {
2428
this.cube.nativeElement.rotation.x = clock.elapsedTime;
2529
this.cube.nativeElement.rotation.y = clock.elapsedTime;
2630
});
27-
console.log(this.store.get('scene'));
31+
console.log('blue instantiated', this.store.get('scene'));
2832
}
2933

3034
ngOnDestroy() {

apps/example/src/app/scene/cursor.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { DOCUMENT } from '@angular/common';
2+
import { Directive, ElementRef, inject, OnInit, Renderer2 } from '@angular/core';
3+
import { getLocalState, injectNgtDestroy } from 'angular-three';
4+
5+
@Directive({ selector: 'ngt-mesh[cursorPointer]', standalone: true })
6+
export class CursorPointer implements OnInit {
7+
private readonly elementRef = inject(ElementRef) as ElementRef<THREE.Mesh>;
8+
private readonly renderer = inject(Renderer2);
9+
private readonly document = inject(DOCUMENT);
10+
private pointerOver?: () => void;
11+
private pointerOut?: () => void;
12+
13+
constructor() {
14+
injectNgtDestroy(() => {
15+
this.pointerOver?.();
16+
this.pointerOut?.();
17+
});
18+
}
19+
20+
ngOnInit() {
21+
const localState = getLocalState(this.elementRef.nativeElement);
22+
23+
if (localState.eventCount) {
24+
const originalPointerOver = localState.handlers.pointerover;
25+
this.pointerOver = this.renderer.listen(this.elementRef.nativeElement, 'pointerover', (event) => {
26+
this.document.body.style.cursor = 'pointer';
27+
originalPointerOver?.(event);
28+
});
29+
30+
const originalPointerOut = localState.handlers.pointerout;
31+
this.pointerOut = this.renderer.listen(this.elementRef.nativeElement, 'pointerout', (event) => {
32+
this.document.body.style.cursor = 'auto';
33+
originalPointerOut?.(event);
34+
});
35+
}
36+
}
37+
}

apps/example/src/app/scene/red-scene.component.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,34 @@
11
import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, inject, ViewChild } from '@angular/core';
22
import { injectBeforeRender, NgtStore } from 'angular-three';
3+
import { CursorPointer } from './cursor';
34

45
@Component({
56
standalone: true,
67
template: `
78
<ngt-point-light [position]="5" />
89
<ngt-spot-light [position]="-5" />
910
10-
<ngt-mesh #cube>
11+
<ngt-mesh #cube cursorPointer (pointerover)="hovered = true" (pointerout)="hovered = false">
1112
<ngt-box-geometry />
12-
<ngt-mesh-standard-material color="red" />
13+
<ngt-mesh-standard-material [color]="hovered ? 'yellow' : 'red'" />
1314
</ngt-mesh>
1415
`,
16+
imports: [CursorPointer],
1517
schemas: [CUSTOM_ELEMENTS_SCHEMA],
1618
})
1719
export default class RedScene {
1820
@ViewChild('cube', { static: true }) cube!: ElementRef<THREE.Mesh>;
1921

2022
readonly store = inject(NgtStore);
2123

24+
hovered = false;
25+
2226
constructor() {
2327
injectBeforeRender(({ clock }) => {
2428
this.cube.nativeElement.rotation.x = clock.elapsedTime;
2529
this.cube.nativeElement.rotation.y = clock.elapsedTime;
2630
});
27-
console.log(this.store.get('scene'));
31+
console.log('red instantiated', this.store.get('scene'));
2832
}
2933

3034
ngOnDestroy() {

libs/angular-three/src/lib/canvas.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ export class NgtCanvas extends NgtRxStore<NgtCanvasInputs> implements OnInit, On
7171
});
7272
}
7373

74-
@HostBinding('class.ngt-canvas') readonly hostClass = true;
75-
@HostBinding('style.pointerEvents') get pointerEvents() {
74+
@HostBinding('class.ngt-canvas') readonly hbClass = true;
75+
@HostBinding('style.pointerEvents') get hbPointerEvents() {
7676
return this.get('eventSource') !== this.host.nativeElement ? 'none' : 'auto';
7777
}
7878

@@ -209,9 +209,7 @@ export class NgtCanvas extends NgtRxStore<NgtCanvasInputs> implements OnInit, On
209209
}
210210

211211
// emit created event if observed
212-
if (this.created.observed) {
213-
this.created.emit(this.store.get());
214-
}
212+
if (this.created.observed) this.created.emit(this.store.get());
215213

216214
// render
217215
if (this.glRef) this.glRef.destroy();
@@ -246,7 +244,7 @@ export class NgtCanvas extends NgtRxStore<NgtCanvasInputs> implements OnInit, On
246244
const originalDetectChanges = this.cdr.detectChanges.bind(this.cdr);
247245
this.cdr.detectChanges = () => {
248246
originalDetectChanges();
249-
safeDetectChanges(this.glRef?.changeDetectorRef);
247+
safeDetectChanges(this.glRef?.changeDetectorRef);
250248
};
251249
}
252250

libs/angular-three/src/lib/di/before-render.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { injectNgtDestroy } from './destroy';
66
export function injectBeforeRender(cb: NgtBeforeRenderRecord['callback'], priority = 0) {
77
try {
88
const store = inject(NgtStore);
9-
const sub = store.get('internal').subscribe((state) => cb(state), priority, store);
9+
const sub = store.get('internal').subscribe(cb, priority, store);
1010
injectNgtDestroy(() => void sub());
1111
return sub;
1212
} catch (e) {

libs/angular-three/src/lib/di/ref.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,17 @@ export function injectNgtRef<T>(initialValue: NgtInjectedRef<T> | (T | null) = n
3838
const cdRefs = [] as ChangeDetectorRef[];
3939
const ref$ = new BehaviorSubject<T>(lastValue);
4040

41-
const { destroy$, cdr } = injectNgtDestroy(() => {
42-
ref$.complete();
43-
});
41+
const { destroy$, cdr } = injectNgtDestroy(() => void ref$.complete());
4442

4543
cdRefs.push(cdr);
4644

4745
const obs$ = ref$.asObservable().pipe(distinctUntilChanged(), takeUntil(destroy$));
4846

49-
const subscribe: Subscribe<T> = (callback) => {
50-
return obs$.subscribe((current) => {
47+
const subscribe: Subscribe<T> = (callback) =>
48+
obs$.subscribe((current) => {
5149
callback(current, lastValue);
5250
lastValue = current;
5351
});
54-
};
5552

5653
const useCDR = (cdr: ChangeDetectorRef) => void cdRefs.push(cdr);
5754

libs/angular-three/src/lib/directives/args.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ export class NgtArgs extends NgtCommonDirective {
66
private injectedArgs: any[] = [];
77

88
@Input() set args(args: any[] | null) {
9-
if (args == null || !Array.isArray(args)) return;
10-
if (args.length === 1 && args[0] === null) return;
9+
if (args == null || !Array.isArray(args) || (args.length === 1 && args[0] === null)) return;
1110
this.injected = false;
1211
this.injectedArgs = args;
1312
this.createView();

libs/angular-three/src/lib/portal.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,7 @@ export interface NgtPortalInputs {
5353
>;
5454
}
5555

56-
@Directive({
57-
selector: 'ngt-portal-before-render',
58-
standalone: true,
59-
})
56+
@Directive({ selector: '[ngtPortalBeforeRender]', standalone: true })
6057
export class NgtPortalBeforeRender implements OnInit, OnDestroy {
6158
private readonly portalStore = inject(NgtStore);
6259

@@ -113,8 +110,9 @@ export class NgtPortalContent {
113110
standalone: true,
114111
template: `
115112
<ng-container #portalContentAnchor>
116-
<ngt-portal-before-render
113+
<ng-container
117114
*ngIf="autoRender && portalContentRendered"
115+
ngtPortalBeforeRender
118116
[renderPriority]="autoRenderPriority"
119117
[parentScene]="parentScene"
120118
[parentCamera]="parentCamera"

libs/angular-three/src/lib/renderer/provider.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,8 @@ export type NgtRendererProviderOptions = {
1010
};
1111

1212
export function provideNgtRenderer({ store, changeDetectorRef, compoundPrefixes = [] }: NgtRendererProviderOptions) {
13-
if (!compoundPrefixes.includes('ngts')) {
14-
compoundPrefixes.push('ngts');
15-
}
16-
17-
if (!compoundPrefixes.includes('ngtp')) {
18-
compoundPrefixes.push('ngtp');
19-
}
13+
if (!compoundPrefixes.includes('ngts')) compoundPrefixes.push('ngts');
14+
if (!compoundPrefixes.includes('ngtp')) compoundPrefixes.push('ngtp');
2015

2116
return makeEnvironmentProviders([
2217
{ provide: RendererFactory2, useClass: NgtRendererFactory },

libs/angular-three/src/lib/renderer/renderer.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,18 @@ import { is } from '../utils/is';
1717
import { safeDetectChanges } from '../utils/safe-detect-changes';
1818
import { NGT_COMPOUND_PREFIXES } from './di';
1919
import { NgtRendererClassId } from './enums';
20-
import { NgtRendererNode, NgtRendererState, NgtRendererStore } from './state';
20+
import { NgtRendererNode, NgtRendererState, NgtRendererStore } from './store';
2121
import { attachThreeChild, kebabToPascal, processThreeEvent, removeThreeChild, SPECIAL_DOM_TAG } from './utils';
2222

2323
@Injectable()
2424
export class NgtRendererFactory implements RendererFactory2 {
2525
private readonly delegateRendererFactory = inject(RendererFactory2, { skipSelf: true });
2626
private readonly catalogue = inject(NGT_CATALOGUE);
2727

28-
private rendererMap = new Map<string, Renderer2>();
29-
private routedSet = new Set<string>();
30-
private rendererStore = new NgtRendererStore({
28+
private readonly rendererMap = new Map<string, Renderer2>();
29+
private readonly routedSet = new Set<string>();
30+
// all Renderer instances share the same Store
31+
private readonly rendererStore = new NgtRendererStore({
3132
store: inject(NgtStore),
3233
cdr: inject(ChangeDetectorRef),
3334
portals: [],

libs/angular-three/src/lib/renderer/state.ts renamed to libs/angular-three/src/lib/renderer/store.ts

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@ export class NgtRendererStore {
7070
const rendererNode = Object.assign(node, { __ngt_renderer__: state });
7171

7272
// assign ownerDocument to node so we can use HostListener in Component
73-
if (!rendererNode['ownerDocument']) {
74-
rendererNode['ownerDocument'] = this.root.document;
75-
}
73+
if (!rendererNode['ownerDocument']) rendererNode['ownerDocument'] = this.root.document;
7674

7775
// assign injectorFactory on non-three type since
7876
// rendererNode is an instance of DOM Node
@@ -84,9 +82,9 @@ export class NgtRendererStore {
8482
// we attach an arrow function to the Comment node
8583
// In our directives, we can call this function to then start tracking the RendererNode
8684
// this is done to limit the amount of Nodes we need to process for getCreationState
87-
rendererNode['__ngt_renderer_add_comment__'] = (portalNode?: NgtRendererNode) => {
88-
if (portalNode && portalNode.__ngt_renderer__[NgtRendererClassId.type] === 'portal') {
89-
this.portals.push(portalNode);
85+
rendererNode['__ngt_renderer_add_comment__'] = (node?: NgtRendererNode) => {
86+
if (node && node.__ngt_renderer__[NgtRendererClassId.type] === 'portal') {
87+
this.portals.push(node);
9088
} else {
9189
this.comments.push(rendererNode);
9290
}
@@ -129,15 +127,12 @@ export class NgtRendererStore {
129127
const attributes = Object.keys(rS[NgtRendererClassId.attributes]);
130128
const properties = Object.keys(rS[NgtRendererClassId.properties]);
131129

132-
if (attributes.length) {
133-
for (const key of attributes) {
134-
this.applyAttribute(instance, key, rS[NgtRendererClassId.attributes][key]);
135-
}
130+
for (const key of attributes) {
131+
this.applyAttribute(instance, key, rS[NgtRendererClassId.attributes][key]);
136132
}
137-
if (properties.length) {
138-
for (const key of properties) {
139-
this.applyProperty(instance, key, rS[NgtRendererClassId.properties][key]);
140-
}
133+
134+
for (const key of properties) {
135+
this.applyProperty(instance, key, rS[NgtRendererClassId.properties][key]);
141136
}
142137

143138
this.executeOperation(compound);
@@ -147,7 +142,7 @@ export class NgtRendererStore {
147142
node.__ngt_renderer__[NgtRendererClassId.queueOps].add(op);
148143
}
149144

150-
executeOperation(node: NgtRendererNode, type: NgtQueueOp[NgtQueueOpClassId.type] = 'op') {
145+
private executeOperation(node: NgtRendererNode, type: NgtQueueOp[NgtQueueOpClassId.type] = 'op') {
151146
const rS = node.__ngt_renderer__;
152147
if (rS[NgtRendererClassId.queueOps]?.size) {
153148
rS[NgtRendererClassId.queueOps].forEach((op) => {

libs/angular-three/src/lib/renderer/utils.ts

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,7 @@ export function attachThreeChild(parent: NgtInstanceNode, child: NgtInstanceNode
9090

9191
cLS.parent = parent;
9292

93-
if (cLS.afterAttach) {
94-
cLS.afterAttach.emit({ parent, node: child });
95-
}
93+
if (cLS.afterAttach) cLS.afterAttach.emit({ parent, node: child });
9694

9795
invalidateInstance(child);
9896
invalidateInstance(parent);
@@ -106,13 +104,8 @@ export function removeThreeChild(parent: NgtInstanceNode, child: NgtInstanceNode
106104
cLS.parent = null;
107105

108106
// remove child from parent
109-
if (pLS.objects) {
110-
pLS.remove(child, 'objects');
111-
}
112-
113-
if (pLS.nonObjects) {
114-
pLS.remove(child, 'nonObjects');
115-
}
107+
if (pLS.objects) pLS.remove(child, 'objects');
108+
if (pLS.nonObjects) pLS.remove(child, 'nonObjects');
116109

117110
if (cLS.attach) {
118111
detach(parent, child, cLS.attach);
@@ -155,16 +148,13 @@ export function processThreeEvent(
155148
}
156149

157150
if (eventName === SPECIAL_EVENTS.AFTER_UPDATE || eventName === SPECIAL_EVENTS.AFTER_ATTACH) {
158-
if (!lS[eventName]) {
159-
lS[eventName] = new EventEmitter();
160-
}
161-
const sub = lS[eventName]?.subscribe(callback);
151+
let emitter = lS[eventName];
152+
if (!emitter) emitter = new EventEmitter();
153+
const sub = emitter.subscribe(callback);
162154
return sub!.unsubscribe.bind(sub);
163155
}
164156

165-
if (!lS.handlers) {
166-
lS.handlers = {};
167-
}
157+
if (!lS.handlers) lS.handlers = {};
168158

169159
// try to get the previous handler. compound might have one, the THREE object might also have one with the same name
170160
const previousHandler = lS.handlers[eventName as keyof typeof lS.handlers];
@@ -174,24 +164,18 @@ export function processThreeEvent(
174164
callback(event);
175165
};
176166

177-
lS.handlers = {
178-
...lS.handlers,
179-
[eventName]: eventToHandler(updatedCallback, cdr, targetCdr),
180-
};
167+
Object.assign(lS.handlers, { [eventName]: eventToHandler(updatedCallback, cdr, targetCdr) });
168+
181169
// increment the count everytime
182170
lS.eventCount += 1;
183171
// but only add the instance (target) to the interaction array (so that it is handled by the EventManager with Raycast)
184172
// the first time eventCount is incremented
185-
if (lS.eventCount === 1 && instance['raycast']) {
186-
lS.store.get('addInteraction')(instance);
187-
}
173+
if (lS.eventCount === 1 && instance['raycast']) lS.store.get('addInteraction')(instance);
188174

189175
// clean up the event listener by removing the target from the interaction array
190176
return () => {
191177
const localState = getLocalState(instance);
192-
if (localState && localState.eventCount) {
193-
localState.store.get('removeInteraction')(instance['uuid']);
194-
}
178+
if (localState && localState.eventCount) localState.store.get('removeInteraction')(instance['uuid']);
195179
};
196180
}
197181

@@ -208,9 +192,7 @@ export function kebabToPascal(str: string): string {
208192
const parts = str.split('-');
209193

210194
// map over the parts, capitalizing the first letter of each part
211-
const pascalParts = parts.map((part) => {
212-
return part.charAt(0).toUpperCase() + part.slice(1);
213-
});
195+
const pascalParts = parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1));
214196

215197
// join the parts together to create the final PascalCase string
216198
return pascalParts.join('');

0 commit comments

Comments
 (0)