Skip to content

Commit 68da7aa

Browse files
committed
fix(core): applyProps assign geometry directly instead of copying
1 parent a25f7c7 commit 68da7aa

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

apps/examples/src/app/soba/lod/scene.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input } from '@angular/core';
1+
import { ChangeDetectionStrategy, Component, computed, CUSTOM_ELEMENTS_SCHEMA, input } from '@angular/core';
22
import { NgtEuler, NgtVector3 } from 'angular-three';
33
import { NgtsOrbitControls } from 'angular-three-soba/controls';
44
import { injectGLTF } from 'angular-three-soba/loaders';
@@ -54,7 +54,7 @@ export class LODBust {
5454
@Component({
5555
selector: 'app-lod-scene-graph',
5656
template: `
57-
@for (p of positions; track $index) {
57+
@for (p of positions(); track $index) {
5858
<app-bust [position]="p.position" [rotation]="p.rotation" />
5959
}
6060
@@ -74,7 +74,11 @@ export class LODBust {
7474
})
7575
export class SceneGraph {
7676
protected Math = Math;
77-
protected positions = positions;
7877

7978
asRenderTexture = input(false);
79+
protected positions = computed(() => {
80+
const asRenderTexture = this.asRenderTexture();
81+
if (!asRenderTexture) return positions;
82+
return positions.slice(250);
83+
});
8084
}

libs/core/src/lib/utils/apply-props.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ const colorMaps = ['map', 'emissiveMap', 'sheenColorMap', 'specularColorMap', 'e
3535

3636
type ClassConstructor = { new (): void };
3737

38+
const MEMOIZED_PROTOTYPES = new Map();
39+
40+
function getMemoizedPrototype(root: any) {
41+
let ctor = MEMOIZED_PROTOTYPES.get(root.constructor);
42+
try {
43+
if (!ctor) {
44+
ctor = new root.constructor();
45+
MEMOIZED_PROTOTYPES.set(root.constructor, ctor);
46+
}
47+
} catch (e) {
48+
// ...
49+
}
50+
return ctor;
51+
}
52+
3853
// This function applies a set of changes to the instance
3954
export function applyProps<T extends NgtAnyRecord>(instance: NgtInstanceState<T>['object'], props: NgtAnyRecord) {
4055
// if props is empty
@@ -77,7 +92,21 @@ export function applyProps<T extends NgtAnyRecord>(instance: NgtInstanceState<T>
7792
(value as ClassConstructor | undefined)?.constructor &&
7893
(targetProp as ClassConstructor).constructor === (value as ClassConstructor).constructor
7994
) {
80-
targetProp.copy(value);
95+
// If both are geometries, we should assign the value directly instead of copying
96+
if (
97+
is.three<THREE.BufferGeometry>(targetProp, 'isBufferGeometry') &&
98+
is.three<THREE.BufferGeometry>(value, 'isBufferGeometry')
99+
) {
100+
Object.assign(currentInstance, { [key]: value });
101+
} else {
102+
// fetch the default state of the target
103+
const ctor = getMemoizedPrototype(currentInstance);
104+
// The target key was originally null or undefined, which indicates that the object which
105+
// is now present was externally set by the user, we should therefore assign the value directly
106+
if (ctor !== undefined && ctor[key] == null) Object.assign(currentInstance, { [key]: value });
107+
// Otherwise copy is correct
108+
else targetProp.copy(value);
109+
}
81110
}
82111
// Layers have no copy function, we must therefore copy the mask property
83112
else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers) {

0 commit comments

Comments
 (0)