@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.
Files changed (36) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/needle-engine.js +11190 -11279
  3. package/dist/needle-engine.umd.cjs +232 -232
  4. package/lib/engine/api.d.ts +2 -0
  5. package/lib/engine/api.js +2 -0
  6. package/lib/engine/api.js.map +1 -1
  7. package/lib/engine/engine_assetdatabase.js +24 -17
  8. package/lib/engine/engine_assetdatabase.js.map +1 -1
  9. package/lib/engine/engine_components.js +3 -3
  10. package/lib/engine/engine_components.js.map +1 -1
  11. package/lib/engine/engine_components_internal.d.ts +6 -3
  12. package/lib/engine/engine_components_internal.js +34 -21
  13. package/lib/engine/engine_components_internal.js.map +1 -1
  14. package/lib/engine/engine_constants.d.ts +1 -1
  15. package/lib/engine/engine_constants.js +2 -1
  16. package/lib/engine/engine_constants.js.map +1 -1
  17. package/lib/engine/engine_gameobject.js +5 -5
  18. package/lib/engine/engine_gameobject.js.map +1 -1
  19. package/lib/engine/engine_gltf_builtin_components.js +2 -2
  20. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  21. package/lib/engine/engine_patcher.d.ts +4 -3
  22. package/lib/engine/engine_patcher.js +61 -44
  23. package/lib/engine/engine_patcher.js.map +1 -1
  24. package/lib/tsconfig.tsbuildinfo +1 -1
  25. package/package.json +2 -6
  26. package/plugins/vite/alias.js +45 -0
  27. package/plugins/vite/index.js +2 -0
  28. package/src/engine/api.ts +3 -2
  29. package/src/engine/engine_assetdatabase.ts +29 -18
  30. package/src/engine/engine_components.ts +3 -3
  31. package/src/engine/engine_components_internal.ts +33 -20
  32. package/src/engine/engine_constants.ts +2 -3
  33. package/src/engine/engine_gameobject.ts +5 -5
  34. package/src/engine/engine_gltf_builtin_components.ts +2 -2
  35. package/src/engine/engine_patcher.ts +104 -47
  36. 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": "2.67.10-pre",
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.7",
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
+ };
@@ -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
- function wrapMethod(fn: Function) {
294
- return function (this: WebGLRenderer, ...args) {
295
- noUpdateScope++;
296
- const result = fn.apply(this, args);
297
- noUpdateScope--;
298
- return result;
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, __internalDispatchComponentLifecycleEvent } from "./engine_components_internal";
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
- __internalDispatchComponentLifecycleEvent(ComponentEvents.Removing, componentInstance);
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
- __internalDispatchComponentLifecycleEvent(ComponentEvents.Added, componentInstance);
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
- export function __internalAddComponentLifecycleEventListener(evt: string, cb: (data: IComponent) => void) {
12
- if (!eventListeners.has(evt)) eventListeners.set(evt, []);
13
- eventListeners.get(evt)?.push(cb);
14
- }
9
+ const debug = getParam("debugcomponentevents");
15
10
 
16
- export function __internalRemoveComponentLifecycleEventListener(evt: string, cb: (data: IComponent) => void) {
17
- const listeners = eventListeners.get(evt);
18
- if (!listeners) return;
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
- export function __internalDispatchComponentLifecycleEvent(evt: string, data: IComponent) {
25
- const listeners = eventListeners.get(evt);
26
- if (!listeners) return;
27
- for (const listener of listeners) {
28
- listener(data);
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 { $originalGuid } from "./engine_constants";
14
- import { __internalDispatchComponentLifecycleEvent, ComponentEvents } from "./engine_components_internal";
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[$originalGuid] !== undefined)
377
- copy[$originalGuid] = comp[$originalGuid];
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
- __internalDispatchComponentLifecycleEvent(ComponentEvents.Added, copy);
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 { $originalGuid, builtinComponentKeyName } from "./engine_constants";
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[$originalGuid] = compData.guid;
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
- export declare type FieldPatch = (instance: object, oldValue: any, newValue: any) => any;
7
- export type MethodPatch<T> = (instance: T, result: any, ...args) => any;
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<TType extends object, TCallback extends (FieldPatch | MethodPatch<any>)>(prototype: TType, fieldName: string, cb: TCallback) {
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, cb);
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
- const prev = this[backingField];
57
- this[backingField] = value;
58
- executePatches(prototype, fieldName, this, prev, value);
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
- return this[backingField];
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
- const patches = new WeakMap<object, Map<string, Function[]>>();
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, cb: Function) {
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(cb);
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 executePatches(prototype, fieldName: string, instance: object, oldValue: any, newValue: any) {
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 patch of patches) {
110
- patch(instance, oldValue, newValue);
166
+ for (const patchInfo of patches) {
167
+ patchInfo.postfix?.call(instance, result, ...args);
111
168
  }
112
169
  }
113
170
  }
@@ -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
- });