Skip to content

Commit a4c5e03

Browse files
author
Sascha Braun
committed
add rewritten (but still unused) core folder
1 parent a521b93 commit a4c5e03

18 files changed

+799
-0
lines changed

src/v2/core/Application.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { AssetManager } from "./AssetManager";
2+
import { CameraManager } from "./CameraManager";
3+
import { Loader } from "./Loader";
4+
import { RendererManager } from "./RendererManager";
5+
import { SceneManager } from "./SceneManager";
6+
7+
export class Application {
8+
private _scenes = new SceneManager(this);
9+
private _cameras = new CameraManager(this);
10+
private _renderers = new RendererManager(this);
11+
private _assets = new AssetManager(this);
12+
private _loader = new Loader();
13+
14+
private _lastUpdate = 0;
15+
private _animationFrame?: number;
16+
17+
private _onBeforeUpdate = new EventDispatcher<() => void>();
18+
private _onUpdate = new EventDispatcher<(dt: number) => void>();
19+
private _onAfterUpdate = new EventDispatcher<() => void>();
20+
21+
public get loader() {
22+
return this._loader;
23+
}
24+
public get scenes() {
25+
return this._scenes;
26+
}
27+
public get cameras() {
28+
return this._cameras;
29+
}
30+
public get renderers() {
31+
return this._renderers;
32+
}
33+
public get assets() {
34+
return this._assets;
35+
}
36+
37+
public activate() {
38+
if (!this._animationFrame) {
39+
this._lastUpdate = Date.now();
40+
this.update();
41+
}
42+
}
43+
44+
public deactivate() {
45+
if (this._animationFrame) {
46+
cancelAnimationFrame(this._animationFrame);
47+
this._animationFrame = undefined;
48+
}
49+
}
50+
51+
private update = () => {
52+
const now = Date.now();
53+
const deltaTime = (now - this._lastUpdate) * 0.001;
54+
this._animationFrame = requestAnimationFrame(this.update);
55+
this._lastUpdate = now;
56+
57+
this._onBeforeUpdate.listeners.forEach(fn => fn());
58+
this._onUpdate.listeners.forEach(fn => fn(deltaTime));
59+
this._onAfterUpdate.listeners.forEach(fn => fn());
60+
61+
this.renderers.render();
62+
};
63+
}

src/v2/core/AssetManager.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Application } from "./Application";
2+
import { AssetMap } from "./AssetMap";
3+
import { GeometryType, MaterialType, ModelType, TextureType } from "./AssetTypes";
4+
import { BundleManager } from "./BundleManager";
5+
6+
export class AssetManager {
7+
private _app: Application;
8+
private _bundles = new BundleManager(this._app);
9+
10+
private _textures = new AssetMap<TextureType>();
11+
private _materials = new AssetMap<MaterialType>();
12+
private _geometries = new AssetMap<GeometryType>();
13+
private _models = new AssetMap<ModelType>();
14+
15+
constructor(app: Application) {
16+
this._app = app;
17+
}
18+
19+
public get bundles() {
20+
return this._bundles;
21+
}
22+
23+
public get textures() {
24+
return this._textures;
25+
}
26+
public get materials() {
27+
return this._materials;
28+
}
29+
public get geometries() {
30+
return this._geometries;
31+
}
32+
public get models() {
33+
return this._models;
34+
}
35+
}

src/v2/core/AssetMap.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { HandlerMapErrors } from "./Errors";
2+
3+
interface DisposableAsset {
4+
dispose?: () => void;
5+
}
6+
7+
export class AssetMap<T> {
8+
protected _data = new Map<string, Promise<T>>();
9+
10+
public set(name: string, asset: Promise<T>): void {
11+
if (this._data.has(name)) {
12+
throw HandlerMapErrors.ALREADY_EXISTS;
13+
}
14+
this._data.set(name, asset);
15+
}
16+
public get(name: string): Promise<T> | undefined {
17+
return this._data.get(name);
18+
}
19+
public dispose(name?: string) {
20+
if (!name) {
21+
this._data.forEach(item => {
22+
this.disposeHook(item);
23+
});
24+
this._data.clear();
25+
return;
26+
}
27+
28+
const handler = this._data.get(name);
29+
if (handler) {
30+
this.disposeHook(handler);
31+
}
32+
}
33+
34+
protected disposeHook(asset: Promise<T>) {
35+
const disposable = asset as DisposableAsset;
36+
if (disposable.dispose) {
37+
disposable.dispose();
38+
}
39+
}
40+
}

src/v2/core/AssetTypes.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as THREE from "three";
2+
3+
import { Application } from "./Application";
4+
5+
export type TextureType = THREE.Texture;
6+
export type MaterialType =
7+
| THREE.MeshBasicMaterial
8+
| THREE.MeshDepthMaterial
9+
| THREE.MeshFaceMaterial
10+
| THREE.MeshLambertMaterial
11+
| THREE.MeshNormalMaterial
12+
| THREE.MeshPhongMaterial
13+
| THREE.MeshStandardMaterial
14+
| THREE.ShaderMaterial
15+
| THREE.ShadowMaterial;
16+
export type GeometryType = THREE.Geometry | THREE.BufferGeometry;
17+
export type ModelType = THREE.Object3D;
18+
export type LightType = THREE.Light;
19+
export type CameraType = THREE.Camera;
20+
21+
export type AssetType = GeometryType | MaterialType | TextureType | ModelType;
22+
23+
export type ModelFactory = (app: Application) => Promise<ModelType>;
24+
export type GeometryFactory = (app: Application) => Promise<GeometryType>;
25+
export type MaterialFactory = (app: Application) => Promise<MaterialType>;
26+
export type TextureFactory = (app: Application) => Promise<TextureType>;
27+
export type LightFactory = (app: Application) => Promise<LightType>;
28+
export type CameraFactory = (app: Application) => Promise<CameraType>;

src/v2/core/BundleHandle.ts

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import { AssetType } from "./AssetTypes";
2+
import { Handle } from "./Handle";
3+
4+
export class BundleHandle extends Handle {
5+
private _assets: Array<Promise<AssetType>> = [];
6+
private _dependencies: BundleHandle[] = [];
7+
private _registered = this.queue;
8+
9+
private _onLoadProgress = new EventDispatcher<
10+
(amount: number, total: number) => Promise<void>
11+
>();
12+
13+
public get onLoadProgress() {
14+
return this._onLoadProgress;
15+
}
16+
17+
/**
18+
* Register asset
19+
* @param bundles
20+
*/
21+
public registerAsset(pAsset: Promise<AssetType>) {
22+
this._assets.push(pAsset);
23+
}
24+
25+
/**
26+
* Register dependency
27+
* @param bundle
28+
*/
29+
public registerDependency(bundle: BundleHandle) {
30+
this._dependencies.push(bundle);
31+
bundle.use();
32+
// we don't need to wait until it is completely loaded
33+
// only until all assets are registered
34+
return bundle._registered;
35+
}
36+
37+
/**
38+
* Register multiple dependencies
39+
* @param bundles
40+
*/
41+
public registerDependencies(bundles: BundleHandle[]) {
42+
const p = bundles.map(bundle => this.registerDependency(bundle));
43+
return Promise.all(p);
44+
}
45+
46+
/**
47+
* Count total number of assets across all given bundle and all their dependencies
48+
* @param bundles
49+
*/
50+
public static countAssets(bundles: BundleHandle[]): number {
51+
const countMap = new Map<BundleHandle, number>();
52+
bundles.forEach(bundle => this.recursiveCountAssets(countMap, bundle));
53+
54+
let total = 0;
55+
countMap.forEach(amount => {
56+
total += amount;
57+
});
58+
return total;
59+
}
60+
/**
61+
* Count total number of assets across this bundle and all dependencies
62+
*/
63+
public countAssets() {
64+
return BundleHandle.countAssets([this]);
65+
}
66+
67+
/**
68+
* List of all assets across all given bundles and all their dependencies
69+
* @param bundles
70+
*/
71+
public static listAssets(bundles: BundleHandle[]): Array<Promise<AssetType>> {
72+
const map = new Map<BundleHandle, Array<Promise<AssetType>>>();
73+
bundles.forEach(bundle => this.recursiveListAssets(map, bundle));
74+
75+
const arr: Array<Promise<AssetType>> = [];
76+
const list = Array.from(map.values());
77+
const assets = arr.concat(...list);
78+
return assets;
79+
}
80+
/**
81+
* List of all assets across this bundle and all dependencies
82+
*/
83+
public listAssets() {
84+
return BundleHandle.listAssets([this]);
85+
}
86+
87+
protected load() {
88+
this._registered = super.load();
89+
return this._registered
90+
.then(() => {
91+
// go to next tick to allow user code to execute first before ready
92+
return new Promise(r => setTimeout(r, 0));
93+
})
94+
.then(() => {
95+
return this.awaitAllAssets();
96+
});
97+
}
98+
99+
protected unload() {
100+
const p = super.unload();
101+
return p
102+
.then(() => {
103+
const deps = this._dependencies.map(dep => dep.unuse());
104+
return Promise.all(deps) as Promise<any>;
105+
})
106+
.then(() => {
107+
this._dependencies = [];
108+
this._assets = [];
109+
return Promise.resolve();
110+
});
111+
}
112+
113+
private awaitAllAssets(): Promise<void> {
114+
const allAssets = this.listAssets();
115+
const total = allAssets.length;
116+
let count = 0;
117+
118+
const pAssets = allAssets.map(assets => {
119+
return assets.then(() => {
120+
++count;
121+
const progress = this._onLoadProgress.listeners.map(fn =>
122+
fn(count, total)
123+
);
124+
return Promise.all(progress);
125+
});
126+
});
127+
128+
return Promise.all(pAssets).then(Promise.resolve);
129+
}
130+
131+
private static recursiveCountAssets(
132+
map: Map<BundleHandle, number>,
133+
pBundle: BundleHandle
134+
) {
135+
if (!map.has(pBundle)) {
136+
map.set(pBundle, pBundle._assets.length);
137+
}
138+
pBundle._dependencies.forEach(bundle => {
139+
this.recursiveCountAssets(map, bundle);
140+
});
141+
}
142+
143+
private static recursiveListAssets(
144+
map: Map<BundleHandle, Array<Promise<AssetType>>>,
145+
pBundle: BundleHandle
146+
) {
147+
if (!map.has(pBundle)) {
148+
map.set(pBundle, pBundle._assets);
149+
}
150+
pBundle._dependencies.forEach(bundle => {
151+
this.recursiveListAssets(map, bundle);
152+
});
153+
}
154+
}

src/v2/core/BundleManager.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Application } from "./Application";
2+
import { BundleHandle } from "./BundleHandle";
3+
import { HandleMap } from "./HandleMap";
4+
5+
export class BundleManager extends HandleMap<BundleHandle> {
6+
constructor(private app: Application) {
7+
super(BundleHandle);
8+
}
9+
}

src/v2/core/CameraHandle.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Camera } from "three";
2+
3+
import { Handle } from "./Handle";
4+
5+
export class CameraHandle extends Handle {
6+
private _camera?: Camera;
7+
8+
public set(camera?: Camera) {
9+
this._camera = camera;
10+
}
11+
public get() {
12+
return this._camera;
13+
}
14+
}

src/v2/core/CameraManager.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Application } from "./Application";
2+
import { CameraHandle } from "./CameraHandle";
3+
import { HandleMap } from "./HandleMap";
4+
5+
export class CameraManager extends HandleMap<CameraHandle> {
6+
constructor(private app: Application) {
7+
super(CameraHandle);
8+
}
9+
}

src/v2/core/Errors.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const HandlerMapErrors = {
2+
ALREADY_EXISTS: {
3+
code: "entry_already_exists",
4+
message: "An handler with the given name already exists"
5+
}
6+
};

src/v2/core/EventDispatcher.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class EventDispatcher<Func extends Function> {
2+
private _listeners: Func[] = [];
3+
4+
public get listeners() {
5+
return this._listeners;
6+
}
7+
8+
public on(fn: Func): void {
9+
this._listeners.push(fn);
10+
}
11+
public off(fn?: Func): void {
12+
if (!fn) {
13+
this._listeners = [];
14+
return;
15+
}
16+
const index = this._listeners.indexOf(fn);
17+
if (index !== -1) {
18+
this._listeners.splice(index, 1);
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)