Needle Engine

Changes between version 2.67.10-pre and 3.0.0-alpha
Files changed (9) hide show
  1. plugins/generate-font.js +0 -65
  2. plugins/vite/index.js +2 -0
  3. src/engine/api.ts +3 -2
  4. src/engine/engine_components_internal.ts +33 -20
  5. src/engine/engine_components.ts +3 -3
  6. src/engine/engine_constants.ts +2 -3
  7. src/engine/engine_gameobject.ts +5 -5
  8. src/engine/engine_gltf_builtin_components.ts +2 -2
  9. plugins/vite/alias.js +45 -0
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
- });
plugins/vite/index.js CHANGED
@@ -5,6 +5,7 @@
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 @@
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),
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";
src/engine/engine_components_internal.ts CHANGED
@@ -1,30 +1,43 @@
1
1
  import { IComponent } from "./engine_types";
2
+ import { getParam } from "./engine_utils";
2
3
 
3
-
4
- const eventListeners = new Map<string, ((data: IComponent) => void)[]>();
5
-
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 {
23
12
 
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);
13
+ private static eventListeners = new Map<string, ((data: IComponent) => void)[]>();
14
+
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
+ }
src/engine/engine_components.ts CHANGED
@@ -6,7 +6,7 @@
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 @@
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 @@
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);
src/engine/engine_constants.ts CHANGED
@@ -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";
src/engine/engine_gameobject.ts CHANGED
@@ -10,8 +10,8 @@
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 @@
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
 
src/engine/engine_gltf_builtin_components.ts CHANGED
@@ -8,7 +8,7 @@
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 @@
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
plugins/vite/alias.js ADDED
@@ -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
+ };