Skip to content
This repository has been archived by the owner on Feb 10, 2023. It is now read-only.

Commit

Permalink
feat(core): refactor how Geometry/Material works
Browse files Browse the repository at this point in the history
- Before Geometry and Material are added to the parent Object3d (Mesh)
  by Content Querying for `NgtMaterial` and `NgtGeometry` on
  `ContentMaterialController` and `ContentGeometryController` (respectively)
- This causes a problem where the following wouldn't work:

```html
<ngt-mesh>
   <ngt-box-geometry></ngt-box-geometry>
   <some-abstract-material-component></some-abstract-material-component>
</ngt-mesh>
```

- `some-abstract-material-component` is a wrapper around a Material.
  Think of making a Material a component so that it can be managed on
  its own (maybe it has `texture` that loads from external sources
  etc...). Content Querying cannot query for the Material that
  `some-abstract-material-component` wraps.

- This has been changed to using DI to try to inject the parent Mesh
  into the Geometry and Material instead. The Geometry and Material then
  assign themselves on the Mesh. This requires that the Mesh needs to be
  provided by:
  - All Meshes
  - All Soba shapes
  - Any Material/Geometry objects
  • Loading branch information
nartc committed Dec 13, 2021
1 parent 7a33b49 commit 979f83a
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 93 deletions.
3 changes: 3 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export * from './lib/three/material';
export * from './lib/three/mesh';
export * from './lib/three/sprite';
export * from './lib/three/camera';
export * from './lib/three/extender';

export * from './lib/resize/tokens';
export * from './lib/resize/resize.service';
Expand All @@ -53,3 +54,5 @@ export * from './lib/utils/build-graph';
export * from './lib/utils/make-id';
export * from './lib/utils/make';
export * from './lib/utils/is-webgl-available';

export * from './lib/providers/object3d';
14 changes: 5 additions & 9 deletions packages/core/src/lib/controllers/content-geometry.controller.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// GENERATED
import { ContentChild, Directive, Input, NgModule } from '@angular/core';
import { Directive, Input, NgModule, NgZone } from '@angular/core';
import * as THREE from 'three';
import { NgtGeometry } from '../three/geometry';
import { Controller, createControllerProviderFactory } from './controller';

@Directive({
Expand All @@ -16,13 +15,6 @@ import { Controller, createControllerProviderFactory } from './controller';
exportAs: 'ngtContentGeometryController',
})
export class NgtContentGeometryController extends Controller {
@ContentChild(NgtGeometry)
set geometryDirective(v: NgtGeometry) {
if (this.geometry == null && v) {
this.geometry = v.geometry;
}
}

#geometryInput?: THREE.BufferGeometry | undefined;

@Input() set geometry(v: THREE.BufferGeometry | undefined) {
Expand All @@ -40,6 +32,10 @@ export class NgtContentGeometryController extends Controller {

#geometry: THREE.BufferGeometry | undefined = undefined;

constructor(ngZone: NgZone) {
super(ngZone);
}

construct() {
this.#geometry = this.#getGeometry(this.#geometryInput);
}
Expand Down
27 changes: 7 additions & 20 deletions packages/core/src/lib/controllers/content-material.controller.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
// GENERATED
import {
ContentChildren,
Directive,
Input,
NgModule,
QueryList,
} from '@angular/core';
import { Directive, Input, NgModule, NgZone } from '@angular/core';
import * as THREE from 'three';
import { NgtMaterial } from '../three/material';
import { Controller, createControllerProviderFactory } from './controller';

@Directive({
Expand Down Expand Up @@ -40,17 +33,6 @@ import { Controller, createControllerProviderFactory } from './controller';
exportAs: 'ngtContentMaterialController',
})
export class NgtContentMaterialController extends Controller {
@ContentChildren(NgtMaterial, { descendants: true }) set materialDirectives(
v: QueryList<NgtMaterial>
) {
if (this.material == null && v) {
this.material =
v.length === 1
? v.first.material
: v.toArray().map((dir) => dir.material);
}
}

#materialInput?: THREE.Material | THREE.Material[] | undefined;

@Input() set material(v: THREE.Material | THREE.Material[] | undefined) {
Expand All @@ -62,8 +44,13 @@ export class NgtContentMaterialController extends Controller {
}
}

@Input() isMaterialArray = false;
@Input() contentMaterialController?: NgtContentMaterialController;

constructor(ngZone: NgZone) {
super(ngZone);
}

get material() {
return this.#material;
}
Expand Down Expand Up @@ -97,7 +84,7 @@ export class NgtContentMaterialController extends Controller {
}

get props(): string[] {
return ['material'];
return ['material', 'isArrayMaterial'];
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// GENERATED
import {
AfterContentInit,
Directive,
Inject,
InjectionToken,
Input,
NgModule,
NgZone,
OnInit,
} from '@angular/core';
import * as THREE from 'three';
import { AnyConstructor, AnyExtenderFunction, UnknownRecord } from '../models';
Expand Down Expand Up @@ -55,7 +55,7 @@ export const NGT_OBJECT_POST_INIT = new InjectionToken('Object3d PostInit', {
})
export class NgtMaterialGeometryController
extends Controller
implements AfterContentInit
implements OnInit
{
#meshArgs: unknown[] = [];
set meshArgs(v: unknown | unknown[]) {
Expand Down Expand Up @@ -100,8 +100,8 @@ export class NgtMaterialGeometryController
}

const object = new this.objectType(
this.#contentGeometryController.geometry,
this.#contentMaterialController.material,
this.#contentGeometryController.geometry || undefined,
this.#contentMaterialController.material || undefined,
...this.#meshArgs
);

Expand All @@ -123,7 +123,8 @@ export class NgtMaterialGeometryController
};
}

ngAfterContentInit() {
ngOnInit() {
super.ngOnInit();
this.ngZone.runOutsideAngular(() => {
this.objectController.init();
});
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/lib/models/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export type UnknownRecord = Record<string, unknown>;
export type AnyFunction<TObject> = () => TObject;
export type AnyConstructor<TObject> = new (...args: any[]) => TObject;
export type AnyExtenderFunction<TObject> = (object: TObject) => void;

Expand Down
30 changes: 30 additions & 0 deletions packages/core/src/lib/providers/object3d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { InjectionToken, Optional, Provider, SkipSelf } from '@angular/core';
import * as THREE from 'three';
import {
NGT_OBJECT_WATCHED_CONTROLLER,
NgtObject3dController,
} from '../controllers/object-3d.controller';
import { AnyFunction } from '../models';
import { NgtSobaExtender } from '../three/extender';

export const NGT_OBJECT_3D = new InjectionToken<AnyFunction<THREE.Object3D>>(
'THREE_OBJECT_3D'
);

export const NGT_OBJECT_3D_PROVIDER: Provider = {
provide: NGT_OBJECT_3D,
useFactory: (
sobaExtender: NgtSobaExtender<THREE.Object3D>,
objectController: NgtObject3dController
) => {
return () => {
if (sobaExtender) return sobaExtender.object;
if (objectController) return objectController.object3d;
return null;
};
},
deps: [
[new Optional(), new SkipSelf(), NgtSobaExtender],
[new Optional(), new SkipSelf(), NGT_OBJECT_WATCHED_CONTROLLER],
],
};
28 changes: 18 additions & 10 deletions packages/core/src/lib/three/geometry.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import {
Directive,
EventEmitter,
Inject,
NgZone,
OnDestroy,
OnInit,
Optional,
Output,
} from '@angular/core';
import { requestAnimationFrame } from '@rx-angular/cdk/zone-less';
import * as THREE from 'three';
import { NgtObject3dController } from '../controllers/object-3d.controller';
import type { AnyConstructor, UnknownRecord } from '../models';
import type { AnyConstructor, AnyFunction, UnknownRecord } from '../models';
import { NGT_OBJECT_3D } from '../providers/object3d';

@Directive()
export abstract class NgtGeometry<
Expand All @@ -20,7 +21,7 @@ export abstract class NgtGeometry<

constructor(
protected ngZone: NgZone,
@Optional() private parentObject: NgtObject3dController
@Inject(NGT_OBJECT_3D) protected parentObject: AnyFunction<THREE.Object3D>
) {}

abstract geometryType: AnyConstructor<TGeometry>;
Expand All @@ -46,26 +47,33 @@ export abstract class NgtGeometry<
if (this.geometry) {
// cleanup
if (this.parentObject) {
const object3d = this.parentObject.object3d as unknown as UnknownRecord;
const object3d = this.parentObject as unknown as UnknownRecord;
if (object3d.geometry) {
(object3d.geometry as THREE.BufferGeometry).dispose();
}
}

// reconstruct
this.#construct();
if (this.parentObject) {
const object3d = this.parentObject.object3d as unknown as UnknownRecord;
object3d.geometry = this.geometry;
}
this.#assign();
} else {
this.#construct();
this.#assign();
}
}

#assign() {
requestAnimationFrame(() => {
const parentObject = this.parentObject() as THREE.Mesh;
if (parentObject) {
parentObject.geometry = this.geometry;
}
this.ready.emit();
});
}

#construct() {
this.#geometry = new this.geometryType(...this.#geometryArgs);
this.ready.emit();
}

#geometry!: TGeometry;
Expand Down
12 changes: 3 additions & 9 deletions packages/core/src/lib/three/helper.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
AfterContentInit,
Directive,
Inject,
NgZone,
OnChanges,
} from '@angular/core';
import { Directive, Inject, NgZone, OnChanges, OnInit } from '@angular/core';
import * as THREE from 'three';
import {
NGT_OBJECT_WATCHED_CONTROLLER,
Expand All @@ -14,7 +8,7 @@ import { AnyConstructor } from '../models';

@Directive()
export abstract class NgtHelper<THelper extends THREE.Object3D>
implements AfterContentInit, OnChanges
implements OnInit, OnChanges
{
abstract helperType: AnyConstructor<THelper>;

Expand Down Expand Up @@ -44,7 +38,7 @@ export abstract class NgtHelper<THelper extends THREE.Object3D>
});
}

ngAfterContentInit() {
ngOnInit() {
this.ngZone.runOutsideAngular(() => {
if (!this.#helper) {
this.objectController.init();
Expand Down
38 changes: 35 additions & 3 deletions packages/core/src/lib/three/material.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import {
Directive,
EventEmitter,
Inject,
Input,
NgZone,
OnDestroy,
OnInit,
Optional,
Output,
} from '@angular/core';
import { requestAnimationFrame } from '@rx-angular/cdk/zone-less';
import * as THREE from 'three';
import type { AnyConstructor, NgtColor, UnknownRecord } from '../models';
import { NgtContentMaterialController } from '../controllers/content-material.controller';
import type {
AnyConstructor,
AnyFunction,
NgtColor,
UnknownRecord,
} from '../models';
import { NGT_OBJECT_3D } from '../providers/object3d';
import { NgtStore } from '../stores/store';
import { makeColor } from '../utils/make';

Expand All @@ -35,7 +45,13 @@ export abstract class NgtMaterial<

#parameters?: TMaterialParameters;

constructor(protected ngZone: NgZone, protected store: NgtStore) {}
constructor(
protected ngZone: NgZone,
protected store: NgtStore,
@Inject(NGT_OBJECT_3D) protected parentObject: AnyFunction<THREE.Object3D>,
@Optional()
protected contentMaterialController: NgtContentMaterialController
) {}

abstract materialType: AnyConstructor<TMaterial>;

Expand All @@ -45,7 +61,23 @@ export abstract class NgtMaterial<
this.#convertColorToLinear(this.parameters);
}
this.#material = new this.materialType(this.parameters);
this.ready.emit();
requestAnimationFrame(() => {
const parentObject = this.parentObject() as THREE.Mesh;
if (parentObject) {
if (
this.contentMaterialController &&
this.contentMaterialController.isMaterialArray
) {
if (!Array.isArray(parentObject.material)) {
parentObject.material = [];
}
(parentObject.material as THREE.Material[]).push(this.material);
} else {
parentObject.material = this.material;
}
}
this.ready.emit();
});
});
}

Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/lib/three/sprite.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {
AfterContentInit,
ContentChild,
Directive,
Inject,
Input,
NgZone,
OnInit,
} from '@angular/core';
import * as THREE from 'three';
import {
Expand All @@ -17,7 +17,7 @@ import { NgtMaterial } from './material';
@Directive()
export abstract class NgtCommonSprite<
TSprite extends THREE.Sprite = THREE.Sprite
> implements AfterContentInit
> implements OnInit
{
@Input() material?: THREE.SpriteMaterial;

Expand Down Expand Up @@ -45,7 +45,7 @@ export abstract class NgtCommonSprite<
};
}

ngAfterContentInit() {
ngOnInit() {
this.ngZone.runOutsideAngular(() => {
this.objectController.init();
});
Expand Down
Loading

0 comments on commit 979f83a

Please sign in to comment.