@needle-tools/engine 2.67.10-pre → 3.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/needle-engine.js +11190 -11279
- package/dist/needle-engine.umd.cjs +232 -232
- package/lib/engine/api.d.ts +2 -0
- package/lib/engine/api.js +2 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/engine_assetdatabase.js +24 -17
- package/lib/engine/engine_assetdatabase.js.map +1 -1
- package/lib/engine/engine_components.js +3 -3
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_components_internal.d.ts +6 -3
- package/lib/engine/engine_components_internal.js +34 -21
- package/lib/engine/engine_components_internal.js.map +1 -1
- package/lib/engine/engine_constants.d.ts +1 -1
- package/lib/engine/engine_constants.js +2 -1
- package/lib/engine/engine_constants.js.map +1 -1
- package/lib/engine/engine_gameobject.js +5 -5
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_gltf_builtin_components.js +2 -2
- package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
- package/lib/engine/engine_patcher.d.ts +4 -3
- package/lib/engine/engine_patcher.js +61 -44
- package/lib/engine/engine_patcher.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -6
- package/plugins/vite/alias.js +45 -0
- package/plugins/vite/index.js +2 -0
- package/src/engine/api.ts +3 -2
- package/src/engine/engine_assetdatabase.ts +29 -18
- package/src/engine/engine_components.ts +3 -3
- package/src/engine/engine_components_internal.ts +33 -20
- package/src/engine/engine_constants.ts +2 -3
- package/src/engine/engine_gameobject.ts +5 -5
- package/src/engine/engine_gltf_builtin_components.ts +2 -2
- package/src/engine/engine_patcher.ts +104 -47
- package/plugins/generate-font.js +0 -65
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/engine",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.1",
|
|
4
4
|
"description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development, and can be deployed anywhere. It is flexible, extensible, and collaboration and XR come naturally.",
|
|
5
5
|
"main": "dist/needle-engine.umd.cjs",
|
|
6
6
|
"module": "lib/needle-engine.js",
|
|
@@ -25,8 +25,6 @@
|
|
|
25
25
|
"build:dist": "vite build",
|
|
26
26
|
"build:src": "tsc --outDir ./lib --noEmit false --declaration",
|
|
27
27
|
"build:license": "node plugins/publish/create-license.mjs",
|
|
28
|
-
"pack-gltf": "node --no-experimental-fetch node_modules/@needle-tools/gltf-transform-extensions/pack-gltf.mjs",
|
|
29
|
-
"transform:make-progressive": "node node_modules/@needle-tools/gltf-transform-extensions/make-progressive.mjs",
|
|
30
28
|
"test:circular-imports": "node plugins/check-circular-imports.js",
|
|
31
29
|
"test:tsc": "tsc"
|
|
32
30
|
},
|
|
@@ -62,7 +60,7 @@
|
|
|
62
60
|
"simplex-noise": "^4.0.1",
|
|
63
61
|
"postprocessing": "^6.30.1",
|
|
64
62
|
"stats.js": "^0.17.0",
|
|
65
|
-
"three": "npm:@needle-tools/three@^0.146.
|
|
63
|
+
"three": "npm:@needle-tools/three@^0.146.6",
|
|
66
64
|
"three-mesh-ui": "^6.4.5",
|
|
67
65
|
"three.quarks": "^0.7.3",
|
|
68
66
|
"uuid": "^9.0.0",
|
|
@@ -71,7 +69,6 @@
|
|
|
71
69
|
"devDependencies": {
|
|
72
70
|
"@babel/runtime": "^7.16.0",
|
|
73
71
|
"@luncheon/esbuild-plugin-gzip": "^0.1.0",
|
|
74
|
-
"@needle-tools/gltf-transform-extensions": "^0.11.2-pre",
|
|
75
72
|
"@needle-tools/helper": "^0.4.5",
|
|
76
73
|
"@needle-tools/needle-component-compiler": "1.9.3",
|
|
77
74
|
"@types/three": "0.146.0",
|
|
@@ -82,7 +79,6 @@
|
|
|
82
79
|
"jsdoc-babel": "^0.5.0",
|
|
83
80
|
"jsdoc-to-markdown": "^7.1.1",
|
|
84
81
|
"madge": "^5.0.1",
|
|
85
|
-
"msdf-bmfont-xml": "^2.7.0",
|
|
86
82
|
"npm-watch": "^0.11.0",
|
|
87
83
|
"typescript": "^4.5.5",
|
|
88
84
|
"vite": "^4.0.4"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const projectDir = process.cwd() + "/";
|
|
5
|
+
|
|
6
|
+
const packages_to_resolve = {
|
|
7
|
+
'three': {},
|
|
8
|
+
'@needle-tools/engine': {},
|
|
9
|
+
'peerjs': {},
|
|
10
|
+
'websocket-ts': {},
|
|
11
|
+
'md5': {},
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const needleViteAlias = (command, config, userSettings) => {
|
|
15
|
+
|
|
16
|
+
if (config?.noAlias === true || userSettings?.noAlias === true)
|
|
17
|
+
return;
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
name: "needle-alias",
|
|
21
|
+
config(config) {
|
|
22
|
+
setTimeout(() => {
|
|
23
|
+
console.log('[needle-alias] ProjectDirectory: ' + projectDir);
|
|
24
|
+
}, 150);
|
|
25
|
+
|
|
26
|
+
if (!config.resolve) config.resolve = {};
|
|
27
|
+
if (!config.resolve.alias) config.resolve.alias = {};
|
|
28
|
+
const aliasDict = config.resolve.alias;
|
|
29
|
+
for (const name in packages_to_resolve) {
|
|
30
|
+
if (!aliasDict[name]) {
|
|
31
|
+
addPathResolver(name, aliasDict);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function addPathResolver(name, aliasList) {
|
|
38
|
+
// If a package at the node_modules path exist we resolve the request there
|
|
39
|
+
// introduced in 89a50718c38940abb99ee16c5e029065e41d7d65
|
|
40
|
+
const res = path.resolve(projectDir, 'node_modules', name);
|
|
41
|
+
if (existsSync(res)) {
|
|
42
|
+
aliasList[name] = () => res;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
package/plugins/vite/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { needleReload } from "./reload.js"
|
|
|
5
5
|
import { needleDrop } from "./drop.js";
|
|
6
6
|
import { editorConnection } from "./editor-connection.js";
|
|
7
7
|
import { needleCopyFiles } from "./copyfiles.js";
|
|
8
|
+
import { needleViteAlias } from "./alias.js";
|
|
8
9
|
|
|
9
10
|
export * from "./gzip.js";
|
|
10
11
|
export * from "./config.js";
|
|
@@ -18,6 +19,7 @@ export const needlePlugins = async (command, config, userSettings) => {
|
|
|
18
19
|
// ensure we have user settings initialized with defaults
|
|
19
20
|
userSettings = { ...defaultUserSettings, ...userSettings }
|
|
20
21
|
const array = [
|
|
22
|
+
needleViteAlias(command, config, userSettings),
|
|
21
23
|
needleMeta(command, config, userSettings),
|
|
22
24
|
needlePoster(command),
|
|
23
25
|
needleReload(command, config, userSettings),
|
package/src/engine/api.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
export * from "./engine_constants";
|
|
2
2
|
export { TypeStore } from "./engine_typestore";
|
|
3
3
|
export * from "./engine_context_registry";
|
|
4
4
|
export * from "./extensions/extensions"
|
|
5
5
|
export { InstancingUtil } from "./engine_instancing";
|
|
6
6
|
export * from "./engine_gameobject";
|
|
7
|
-
export * from "./engine_components"
|
|
7
|
+
export * from "./engine_components";
|
|
8
|
+
export * from "./engine_components_internal";
|
|
8
9
|
export { AssetReference } from "./engine_addressables";
|
|
9
10
|
export { Context, FrameEvent } from "./engine_setup";
|
|
10
11
|
export * from "./debug/debug";
|
|
@@ -278,27 +278,21 @@ function updateUsers(symbol: symbol, user: object, object: object | object[], ad
|
|
|
278
278
|
|
|
279
279
|
// We dont want to update users during rendering
|
|
280
280
|
|
|
281
|
-
const $renderMethod = Symbol("render-method");
|
|
282
|
-
|
|
283
|
-
Object.defineProperty(WebGLRenderer.prototype, "render", {
|
|
284
|
-
set: function (this: WebGLRenderer, value: Function) {
|
|
285
|
-
this[$renderMethod] = wrapMethod(value);
|
|
286
|
-
},
|
|
287
|
-
get: function (this: WebGLRenderer) {
|
|
288
|
-
return this[$renderMethod];
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
281
|
|
|
282
|
+
try {
|
|
292
283
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
284
|
+
// addPatch(WebGLRenderer.prototype, "render",
|
|
285
|
+
// () => {
|
|
286
|
+
// noUpdateScope++;
|
|
287
|
+
// },
|
|
288
|
+
// () => {
|
|
289
|
+
// noUpdateScope--;
|
|
290
|
+
// }
|
|
291
|
+
// );
|
|
292
|
+
}
|
|
293
|
+
catch (e) {
|
|
294
|
+
console.warn("Could not wrap WebGLRenderer.render", e);
|
|
300
295
|
}
|
|
301
|
-
|
|
302
296
|
|
|
303
297
|
|
|
304
298
|
// addGltfLoadEventListener(GltfLoadEventType.BeforeLoad, (_) => {
|
|
@@ -320,3 +314,20 @@ function wrapMethod(fn: Function) {
|
|
|
320
314
|
// }
|
|
321
315
|
// });
|
|
322
316
|
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
// class MyObject {
|
|
322
|
+
// myNumber: number = 1;
|
|
323
|
+
// }
|
|
324
|
+
|
|
325
|
+
// addPatch(MyObject.prototype, "myNumber", (obj, oldValue, newValue) => {
|
|
326
|
+
// console.log("myNumber changed", oldValue, newValue);
|
|
327
|
+
// });
|
|
328
|
+
|
|
329
|
+
// const i = new MyObject();
|
|
330
|
+
// setInterval(() => {
|
|
331
|
+
// console.log("RUN");
|
|
332
|
+
// i.myNumber += 1;
|
|
333
|
+
// }, 1000);
|
|
@@ -6,7 +6,7 @@ import { removeScriptFromContext, updateActiveInHierarchyWithoutEventCall } from
|
|
|
6
6
|
import { activeInHierarchyFieldName } from "./engine_constants";
|
|
7
7
|
import { apply } from "../engine-components/js-extensions/Object3D";
|
|
8
8
|
import { InstantiateIdProvider } from "./engine_networking_instantiate";
|
|
9
|
-
import { ComponentEvents,
|
|
9
|
+
import { ComponentEvents, ComponentLifecycleEvents } from "./engine_components_internal";
|
|
10
10
|
|
|
11
11
|
const debug = getParam("debuggetcomponent");
|
|
12
12
|
|
|
@@ -30,7 +30,7 @@ export function removeComponent(go: Object3D, componentInstance: IComponent) {
|
|
|
30
30
|
const index = go.userData.components.indexOf(componentInstance);
|
|
31
31
|
if (index < 0) return;
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
ComponentLifecycleEvents.dispatchComponentLifecycleEvent(ComponentEvents.Removing, componentInstance);
|
|
34
34
|
|
|
35
35
|
//@ts-ignore
|
|
36
36
|
componentInstance.gameObject = null;
|
|
@@ -66,7 +66,7 @@ export function addNewComponent<T extends IComponent>(obj: Object3D, componentIn
|
|
|
66
66
|
updateActiveInHierarchyWithoutEventCall(obj);
|
|
67
67
|
componentInstance.__internalAwake();
|
|
68
68
|
}
|
|
69
|
-
|
|
69
|
+
ComponentLifecycleEvents.dispatchComponentLifecycleEvent(ComponentEvents.Added, componentInstance);
|
|
70
70
|
}
|
|
71
71
|
catch (err) {
|
|
72
72
|
console.error(err);
|
|
@@ -1,30 +1,43 @@
|
|
|
1
1
|
import { IComponent } from "./engine_types";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const eventListeners = new Map<string, ((data: IComponent) => void)[]>();
|
|
2
|
+
import { getParam } from "./engine_utils";
|
|
5
3
|
|
|
6
4
|
export enum ComponentEvents {
|
|
7
5
|
Added = "component-added",
|
|
8
6
|
Removing = "removing-component"
|
|
9
7
|
}
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
if (!eventListeners.has(evt)) eventListeners.set(evt, []);
|
|
13
|
-
eventListeners.get(evt)?.push(cb);
|
|
14
|
-
}
|
|
9
|
+
const debug = getParam("debugcomponentevents");
|
|
15
10
|
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const index = listeners.indexOf(cb);
|
|
20
|
-
if (index < 0) return;
|
|
21
|
-
listeners.splice(index, 1);
|
|
22
|
-
}
|
|
11
|
+
export class ComponentLifecycleEvents {
|
|
12
|
+
|
|
13
|
+
private static eventListeners = new Map<string, ((data: IComponent) => void)[]>();
|
|
23
14
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
15
|
+
static addComponentLifecylceEventListener(evt: string, cb: (data: IComponent) => void) {
|
|
16
|
+
if (this.eventListeners.has(evt)) {
|
|
17
|
+
this.eventListeners.set(evt, []);
|
|
18
|
+
}
|
|
19
|
+
let arr = this.eventListeners.get(evt);
|
|
20
|
+
if (!arr) arr = [];
|
|
21
|
+
arr.push(cb);
|
|
22
|
+
this.eventListeners.set(evt, arr);
|
|
23
|
+
if(debug) console.log("Added event listener for " + evt, this.eventListeners)
|
|
29
24
|
}
|
|
30
|
-
|
|
25
|
+
|
|
26
|
+
static removeComponentLifecylceEventListener(evt: string, cb: (data: IComponent) => void) {
|
|
27
|
+
const listeners = this.eventListeners.get(evt);
|
|
28
|
+
if (!listeners) return;
|
|
29
|
+
const index = listeners.indexOf(cb);
|
|
30
|
+
if (index < 0) return;
|
|
31
|
+
listeners.splice(index, 1);
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static dispatchComponentLifecycleEvent(evt: string, data: IComponent) {
|
|
36
|
+
const listeners = this.eventListeners.get(evt);
|
|
37
|
+
if(debug) console.log("Dispatching event " + evt, listeners)
|
|
38
|
+
if (!listeners) return;
|
|
39
|
+
for (const listener of listeners) {
|
|
40
|
+
listener(data);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
|
|
2
2
|
export const activeInHierarchyFieldName = Symbol("isActiveInHierarchy");
|
|
3
3
|
export const builtinComponentKeyName = "builtin_components";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export const $originalGuid = Symbol("originalGuid");
|
|
4
|
+
// It's easier to use a string than a symbol here because the symbol might not be the same when imported in other packages
|
|
5
|
+
export const editorGuidKeyName = "needle_editor_guid";
|
|
@@ -10,8 +10,8 @@ import { $isUsingInstancing, InstancingUtil } from "./engine_instancing";
|
|
|
10
10
|
import { activeInHierarchyFieldName } from "./engine_constants";
|
|
11
11
|
import { assign } from "./engine_serialization_core";
|
|
12
12
|
import { disposeObjectResources, __internalNotifyObjectDestroyed as __internalRemoveReferences } from "./engine_assetdatabase";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { editorGuidKeyName } from "./engine_constants";
|
|
14
|
+
import { ComponentLifecycleEvents, ComponentEvents } from "./engine_components_internal";
|
|
15
15
|
|
|
16
16
|
const debug = getParam("debuggetcomponent");
|
|
17
17
|
const debugInstantiate = getParam("debuginstantiate");
|
|
@@ -373,13 +373,13 @@ function internalInstantiate(
|
|
|
373
373
|
const copy = new comp.constructor();
|
|
374
374
|
assign(copy, comp);
|
|
375
375
|
// make sure the original guid stays intact
|
|
376
|
-
if (comp[
|
|
377
|
-
copy[
|
|
376
|
+
if (comp[editorGuidKeyName] !== undefined)
|
|
377
|
+
copy[editorGuidKeyName] = comp[editorGuidKeyName];
|
|
378
378
|
newComponents.push(copy);
|
|
379
379
|
copy.gameObject = clone;
|
|
380
380
|
// copy.transform = clone;
|
|
381
381
|
componentsList.push(copy);
|
|
382
|
-
|
|
382
|
+
ComponentLifecycleEvents.dispatchComponentLifecycleEvent(ComponentEvents.Added, copy);
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
385
|
|
|
@@ -8,7 +8,7 @@ import { deserializeObject, serializeObject } from "./engine_serialization";
|
|
|
8
8
|
import { assign, ImplementationInformation, ISerializable, SerializationContext } from "./engine_serialization_core";
|
|
9
9
|
import { NEEDLE_components } from "./extensions/NEEDLE_components";
|
|
10
10
|
import { debugExtension } from "./engine_default_parameters";
|
|
11
|
-
import {
|
|
11
|
+
import { editorGuidKeyName, builtinComponentKeyName } from "./engine_constants";
|
|
12
12
|
import { GuidsMap, IComponent, IGameObject, SourceIdentifier } from "./engine_types";
|
|
13
13
|
import { UIDProvider } from "./engine_types";
|
|
14
14
|
import { addNewComponent } from "./engine_components";
|
|
@@ -174,7 +174,7 @@ async function onCreateBuiltinComponents(context: SerializationContext, obj: THR
|
|
|
174
174
|
|
|
175
175
|
// assign the guid of the original instance
|
|
176
176
|
if("guid" in compData)
|
|
177
|
-
instance[
|
|
177
|
+
instance[editorGuidKeyName] = compData.guid;
|
|
178
178
|
|
|
179
179
|
// Object.assign(instance, compData);
|
|
180
180
|
// dont call awake here because some references might not be resolved yet and components that access those fields in awake will throw
|
|
@@ -3,67 +3,102 @@
|
|
|
3
3
|
|
|
4
4
|
const _wrappedMethods = new WeakSet();
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
export
|
|
6
|
+
|
|
7
|
+
// export function wrap<T>(prototype: object, methodName: string, before: (t: T) => void, after: (t: T) => void) {
|
|
8
|
+
|
|
9
|
+
// const $key = Symbol(methodName + "-patched");
|
|
10
|
+
|
|
11
|
+
// const alreadyDefined = Object.getOwnPropertyDescriptor(prototype, methodName);
|
|
12
|
+
// if (alreadyDefined) {
|
|
13
|
+
// const originalRender = alreadyDefined.get;
|
|
14
|
+
// if (originalRender) {
|
|
15
|
+
// // Object.defineProperty(prototype, "render", {
|
|
16
|
+
// // set: function (this: any, value: Function) {
|
|
17
|
+
// // originalRender.call(this);
|
|
18
|
+
// // },
|
|
19
|
+
// // get: function (this: ) {
|
|
20
|
+
// // return originalRender.call(this);
|
|
21
|
+
// // }
|
|
22
|
+
// // });
|
|
23
|
+
// }
|
|
24
|
+
// }
|
|
25
|
+
// else {
|
|
26
|
+
// Object.defineProperty(prototype, methodName, {
|
|
27
|
+
// set: function (this: any, value: Function) {
|
|
28
|
+
// this[$key] = value;
|
|
29
|
+
// },
|
|
30
|
+
// get: function (this: any) {
|
|
31
|
+
// return this[$key];
|
|
32
|
+
// }
|
|
33
|
+
// });
|
|
34
|
+
// }
|
|
35
|
+
// }
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
// export declare type FieldPatch = (instance: object, oldValue: any, newValue: any) => any;
|
|
39
|
+
|
|
40
|
+
export type Prefix = (...args) => any;
|
|
41
|
+
export type Postfix = (...args) => any;
|
|
8
42
|
|
|
9
43
|
/**
|
|
10
44
|
* Use patcher for patching properties insteadof calling Object.defineProperty individually
|
|
11
45
|
* since this will cause conflicts if multiple patches need to be applied to the same property
|
|
12
46
|
*/
|
|
13
|
-
export function addPatch<
|
|
47
|
+
export function addPatch<T extends object>(prototype: T, fieldName: string, beforeCallback?: Prefix, afterCallback?: Postfix) {
|
|
48
|
+
|
|
49
|
+
// TODO
|
|
50
|
+
return;
|
|
14
51
|
|
|
15
52
|
// TODO: we probably want to turn this into a symbol to prevent anyone from overriding it
|
|
16
53
|
// But when we need to store the symbol per prototype to allow e.g. material disposing to iterate those and dispose all
|
|
17
|
-
const backingField = fieldName + "__needle";// Symbol(fieldName);// + " (patched)";
|
|
54
|
+
const backingField = Symbol(fieldName + "__needle");// Symbol(fieldName);// + " (patched)";
|
|
18
55
|
|
|
19
|
-
internalAddPatch(prototype, fieldName,
|
|
56
|
+
internalAddPatch(prototype, fieldName, afterCallback, beforeCallback);
|
|
20
57
|
|
|
21
58
|
const desc = Object.getOwnPropertyDescriptor(prototype, fieldName);
|
|
59
|
+
|
|
60
|
+
const existing = prototype[fieldName];
|
|
61
|
+
console.log(prototype);
|
|
22
62
|
|
|
23
63
|
if (desc) {
|
|
24
|
-
// TODO: check if the property is writable
|
|
25
|
-
// the property might be a method in which case we want to wrap it
|
|
26
|
-
if (typeof desc.value === "function") {
|
|
27
|
-
const method = desc.value;
|
|
28
|
-
if (method) {
|
|
29
|
-
if (_wrappedMethods.has(method)) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
_wrappedMethods.add(method);
|
|
33
|
-
prototype[fieldName] = function (this: object, ...args: any[]) {
|
|
34
|
-
// call the original method
|
|
35
|
-
const result = method.apply(this, args);
|
|
36
|
-
// call the patches
|
|
37
|
-
const patches = getPatches(prototype, fieldName);
|
|
38
|
-
if (patches) {
|
|
39
|
-
for (const patch of patches) {
|
|
40
|
-
patch(this, result, ...args);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return result;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
// TODO: declare method?
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
else if (prototype.hasOwnProperty(backingField)) {
|
|
52
64
|
}
|
|
53
65
|
else {
|
|
54
66
|
Object.defineProperty(prototype, fieldName, {
|
|
55
67
|
set: function (this: object, value: any) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
68
|
+
console.log("setting", fieldName, value);
|
|
69
|
+
if (typeof value === "function") {
|
|
70
|
+
this[backingField] = addWrapper(value, prototype, fieldName);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
const prev = this[backingField];
|
|
74
|
+
executePrefixes(prototype, fieldName, this, prev, value);
|
|
75
|
+
this[backingField] = value;
|
|
76
|
+
executePostFixes(prototype, fieldName, this, prev, value);
|
|
77
|
+
}
|
|
59
78
|
},
|
|
60
79
|
get: function (this: any) {
|
|
61
|
-
|
|
80
|
+
console.log("GET", fieldName);
|
|
81
|
+
const value = this[backingField];
|
|
82
|
+
if (typeof value === "function") {
|
|
83
|
+
if (value[backingField]) {
|
|
84
|
+
return value[backingField];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return value;
|
|
62
88
|
}
|
|
63
89
|
});
|
|
64
90
|
}
|
|
65
91
|
}
|
|
66
92
|
|
|
93
|
+
function addWrapper(originalFunction: Function, prototype, fieldname) {
|
|
94
|
+
return function (this: object, ...args: any[]) {
|
|
95
|
+
executePrefixes(prototype, fieldname, this, ...args);
|
|
96
|
+
const result = originalFunction.apply(this, args);
|
|
97
|
+
executePostFixes(prototype, fieldname, this, result, ...args);
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
67
102
|
export function removePatch(prototype: object, fieldName: string, cb: Function) {
|
|
68
103
|
const patches = getPatches(prototype, fieldName);
|
|
69
104
|
if (patches) {
|
|
@@ -76,38 +111,60 @@ export function removePatch(prototype: object, fieldName: string, cb: Function)
|
|
|
76
111
|
}
|
|
77
112
|
|
|
78
113
|
|
|
114
|
+
export const NeedlePatchesKey = "Needle:Patches";
|
|
79
115
|
|
|
80
|
-
|
|
81
|
-
|
|
116
|
+
declare type PatchInfo = {
|
|
117
|
+
prefix?: Prefix;
|
|
118
|
+
postfix?: Postfix;
|
|
119
|
+
}
|
|
120
|
+
function patches(): WeakMap<object, Map<string, PatchInfo[]>> {
|
|
121
|
+
if (!globalThis[NeedlePatchesKey]) {
|
|
122
|
+
globalThis[NeedlePatchesKey] = new WeakMap<object, Map<string, PatchInfo[]>>();
|
|
123
|
+
}
|
|
124
|
+
return globalThis[NeedlePatchesKey];
|
|
125
|
+
}
|
|
82
126
|
|
|
83
127
|
function getPatches(prototype, fieldName: string) {
|
|
84
|
-
let patchesMap = patches.get(prototype);
|
|
128
|
+
let patchesMap = patches().get(prototype);
|
|
85
129
|
if (!patchesMap) {
|
|
86
130
|
return null;
|
|
87
131
|
}
|
|
88
132
|
return patchesMap.get(fieldName);;
|
|
89
133
|
}
|
|
90
134
|
|
|
91
|
-
function internalAddPatch(prototype, fieldName: string,
|
|
92
|
-
let patchesMap = patches.get(prototype);
|
|
135
|
+
function internalAddPatch(prototype, fieldName: string, postfix?: Postfix, prefix?: Prefix) {
|
|
136
|
+
let patchesMap = patches().get(prototype);
|
|
93
137
|
if (!patchesMap) {
|
|
94
138
|
patchesMap = new Map();
|
|
95
|
-
patches.set(prototype, patchesMap);
|
|
139
|
+
patches().set(prototype, patchesMap);
|
|
96
140
|
}
|
|
97
141
|
let patchList = patchesMap.get(fieldName);
|
|
98
142
|
if (!patchList) {
|
|
99
143
|
patchList = [];
|
|
100
144
|
patchesMap.set(fieldName, patchList);
|
|
101
145
|
}
|
|
102
|
-
patchList.push(
|
|
146
|
+
patchList.push({
|
|
147
|
+
prefix: prefix,
|
|
148
|
+
postfix: postfix
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function executePrefixes(prototype, fieldName: string, instance: object, ...args) {
|
|
153
|
+
if (!instance) return;
|
|
154
|
+
const patches = getPatches(prototype, fieldName);
|
|
155
|
+
if (patches) {
|
|
156
|
+
for (const patchInfo of patches) {
|
|
157
|
+
patchInfo.prefix?.call(instance, ...args);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
103
160
|
}
|
|
104
161
|
|
|
105
|
-
function
|
|
162
|
+
function executePostFixes(prototype, fieldName: string, instance: object, result: any, ...args) {
|
|
106
163
|
if (!instance) return;
|
|
107
164
|
const patches = getPatches(prototype, fieldName);
|
|
108
165
|
if (patches) {
|
|
109
|
-
for (const
|
|
110
|
-
|
|
166
|
+
for (const patchInfo of patches) {
|
|
167
|
+
patchInfo.postfix?.call(instance, result, ...args);
|
|
111
168
|
}
|
|
112
169
|
}
|
|
113
170
|
}
|
package/plugins/generate-font.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import generateBMFont from 'msdf-bmfont-xml';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
const args = process.argv;
|
|
6
|
-
|
|
7
|
-
const fontPath = args[2];
|
|
8
|
-
const outputDir = args[3];
|
|
9
|
-
const charsetPath = args.length > 4 ? args[4] : null;
|
|
10
|
-
|
|
11
|
-
if (!fontPath || !fs.existsSync(fontPath)) {
|
|
12
|
-
console.error("Missing font path. Please call this script with a path to a font file. Called with: \"" + fontPath + "\"");
|
|
13
|
-
process.exit(1);
|
|
14
|
-
}
|
|
15
|
-
if (!outputDir || !fs.existsSync(outputDir)) {
|
|
16
|
-
console.error("Missing output directory, please provide an output directory as the second argument. Called with: \"" + outputDir + "\"");
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// https://soimy.github.io/msdf-bmfont-xml/#module-usage-examples
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
let message = "Generate font texture " + fontPath + " to " + outputDir;
|
|
24
|
-
|
|
25
|
-
let charset = null;
|
|
26
|
-
if (charsetPath && fs.existsSync(charsetPath)) {
|
|
27
|
-
message += " using chars from \"" + charsetPath + "\"";
|
|
28
|
-
charset = fs.readFileSync(charsetPath, 'utf8');
|
|
29
|
-
console.log("charset: ", charset);
|
|
30
|
-
if (charset.length <= 0) {
|
|
31
|
-
console.warn("WARN: Charset file is empty, using default charset");
|
|
32
|
-
charset = null;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
console.log(message);
|
|
37
|
-
const opts = {
|
|
38
|
-
outputType: "json",
|
|
39
|
-
fieldType: "msdf",
|
|
40
|
-
textureSize: [4096, 4096],
|
|
41
|
-
smartSize: true, // shrink atlas to the smallest possible square
|
|
42
|
-
// rtl: true, // use RTL(Arabic/Persian) charators fix
|
|
43
|
-
};
|
|
44
|
-
if (charset?.length)
|
|
45
|
-
opts.charset = charset;
|
|
46
|
-
|
|
47
|
-
generateBMFont(fontPath, opts,
|
|
48
|
-
(error, textures, font) => {
|
|
49
|
-
if (error) throw error;
|
|
50
|
-
textures.forEach((texture, index) => {
|
|
51
|
-
const fileName = path.parse(texture.filename).name.toLocaleLowerCase() + ".png";
|
|
52
|
-
const outputPath = outputDir + "/" + fileName;
|
|
53
|
-
console.log("Write to", outputPath);
|
|
54
|
-
if (index > 0) console.log("WARN: Multiple font textures generated but they will override each other. You have currently " + charset?.length + " characters configured. Maybe too many?");
|
|
55
|
-
fs.writeFile(outputPath, texture.texture, (err) => {
|
|
56
|
-
if (err) throw err;
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const fileName = path.parse(font.filename).name;
|
|
61
|
-
const name = outputDir + "/" + fileName.toLocaleLowerCase() + "-msdf.json";
|
|
62
|
-
fs.writeFile(name, font.data, (err) => {
|
|
63
|
-
if (err) throw err;
|
|
64
|
-
});
|
|
65
|
-
});
|