@needle-tools/engine 3.5.3-alpha → 3.5.4-alpha

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 (43) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/needle-engine.js +6824 -6812
  3. package/dist/needle-engine.min.js +306 -306
  4. package/dist/needle-engine.umd.cjs +303 -303
  5. package/lib/engine/codegen/register_types.js +2 -2
  6. package/lib/engine/codegen/register_types.js.map +1 -1
  7. package/lib/engine/engine_addressables.js +3 -0
  8. package/lib/engine/engine_addressables.js.map +1 -1
  9. package/lib/engine/engine_constants.d.ts +2 -0
  10. package/lib/engine/engine_constants.js +2 -0
  11. package/lib/engine/engine_constants.js.map +1 -1
  12. package/lib/engine/engine_context.d.ts +2 -0
  13. package/lib/engine/engine_context.js +5 -0
  14. package/lib/engine/engine_context.js.map +1 -1
  15. package/lib/engine/engine_serialization_core.js +1 -1
  16. package/lib/engine/engine_serialization_core.js.map +1 -1
  17. package/lib/engine-components/codegen/components.d.ts +1 -1
  18. package/lib/engine-components/codegen/components.js +1 -1
  19. package/lib/engine-components/codegen/components.js.map +1 -1
  20. package/lib/engine-components/export/usdz/USDZExporter.d.ts +2 -2
  21. package/lib/engine-components/export/usdz/USDZExporter.js +23 -11
  22. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  23. package/lib/engine-components/ui/Graphic.js +3 -2
  24. package/lib/engine-components/ui/Graphic.js.map +1 -1
  25. package/lib/engine-components/ui/Text.js +5 -2
  26. package/lib/engine-components/ui/Text.js.map +1 -1
  27. package/lib/needle-engine.js +5 -0
  28. package/lib/needle-engine.js.map +1 -1
  29. package/lib/tsconfig.tsbuildinfo +1 -1
  30. package/package.json +1 -1
  31. package/plugins/vite/defines.js +12 -6
  32. package/plugins/vite/meta.js +16 -3
  33. package/plugins/vite/utils.js +11 -0
  34. package/src/engine/codegen/register_types.js +2 -2
  35. package/src/engine/engine_addressables.ts +2 -1
  36. package/src/engine/engine_constants.ts +3 -0
  37. package/src/engine/engine_context.ts +6 -0
  38. package/src/engine/engine_serialization_core.ts +1 -1
  39. package/src/engine-components/codegen/components.ts +1 -1
  40. package/src/engine-components/export/usdz/USDZExporter.ts +19 -7
  41. package/src/engine-components/ui/Graphic.ts +3 -1
  42. package/src/engine-components/ui/Text.ts +5 -4
  43. package/src/needle-engine.ts +10 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/engine",
3
- "version": "3.5.3-alpha",
3
+ "version": "3.5.4-alpha",
4
4
  "description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in",
5
5
  "main": "dist/needle-engine.umd.cjs",
6
6
  "type": "module",
@@ -1,19 +1,26 @@
1
1
  import { loadConfig } from "./config.js";
2
+ import { tryGetNeedleEngineVersion } from "./utils.js";
2
3
 
3
4
  /** used to pass config variables into vite.config.define
4
5
  * for example "useRapier"
5
6
  */
6
- export const needleDefines = (command, config, userSettings) => {
7
+ export const needleDefines = (command, needleEngineConfig, userSettings) => {
7
8
 
8
9
  if (!userSettings) userSettings = {};
9
10
 
10
11
  let useRapier = true;
11
- if (config.useRapier === false || userSettings?.useRapier === false) useRapier = false;
12
+ if (needleEngineConfig.useRapier === false || userSettings?.useRapier === false) useRapier = false;
12
13
 
13
14
  return {
14
15
  name: 'needle-defines',
15
16
  enforce: 'pre',
16
- config(config) {
17
+ config(viteConfig) {
18
+ if (!viteConfig.define) viteConfig.define = {};
19
+ viteConfig.define.NEEDLE_ENGINE_META = {
20
+ version: tryGetNeedleEngineVersion(),
21
+ generator: needleEngineConfig.generator,
22
+ }
23
+
17
24
  if (useRapier && userSettings?.useRapier !== true) {
18
25
  const meta = loadConfig();
19
26
  if (meta?.useRapier === false) {
@@ -21,9 +28,8 @@ export const needleDefines = (command, config, userSettings) => {
21
28
  }
22
29
  }
23
30
  console.log("UseRapier?", useRapier);
24
- if (!config.define) config.define = {};
25
- if (config.define.NEEDLE_USE_RAPIER === undefined) {
26
- config.define.NEEDLE_USE_RAPIER = useRapier;
31
+ if (viteConfig.define.NEEDLE_USE_RAPIER === undefined) {
32
+ viteConfig.define.NEEDLE_USE_RAPIER = useRapier;
27
33
  }
28
34
  }
29
35
  }
@@ -1,6 +1,7 @@
1
1
  import { loadConfig } from './config.js';
2
2
  import fs from 'fs';
3
3
  import { getPosterPath } from './poster.js';
4
+ import { tryGetNeedleEngineVersion } from './utils.js';
4
5
 
5
6
  export const needleMeta = (command, config, userSettings) => {
6
7
 
@@ -15,7 +16,7 @@ export const needleMeta = (command, config, userSettings) => {
15
16
 
16
17
  return {
17
18
  // replace meta tags
18
- name: 'needle-meta-tags',
19
+ name: 'needle-meta',
19
20
  transformIndexHtml: {
20
21
  enforce: 'pre',
21
22
  transform(html, _ctx) {
@@ -91,8 +92,19 @@ export const needleMeta = (command, config, userSettings) => {
91
92
  }
92
93
  }
93
94
 
94
- // if(!tags.filter(t => t.attrs?.name === "generator"))
95
- tags.push({ tag: 'meta', attrs: { name: 'generator', content: 'Needle' } });
95
+ let generator = "Needle";
96
+ if (config.generator?.length > 5) {
97
+ generator = config.generator;
98
+ }
99
+ tags.push({ tag: 'meta', attrs: { name: 'generator', content: generator } });
100
+
101
+ const needleEngineVersion = tryGetNeedleEngineVersion();
102
+ if (needleEngineVersion) {
103
+ if (command === "build")
104
+ console.log("Needle Engine version: " + needleEngineVersion);
105
+ tags.push({ tag: 'meta', attrs: { name: 'needle-engine', content: needleEngineVersion } });
106
+ }
107
+ else console.log("WARN: could not find needle engine package.json")
96
108
 
97
109
  return { html, tags }
98
110
  },
@@ -100,6 +112,7 @@ export const needleMeta = (command, config, userSettings) => {
100
112
  }
101
113
  }
102
114
 
115
+
103
116
  function updateUrlMetaTag(html, url) {
104
117
  html = html.replace(`<meta name="url" content="http://needle.tools">`, `<meta name="url" content="${url}">`);
105
118
  return html;
@@ -0,0 +1,11 @@
1
+ import { existsSync, readFileSync } from "fs";
2
+
3
+ export function tryGetNeedleEngineVersion() {
4
+ const needleEnginePackageJsonPath = process.cwd() + "/node_modules/@needle-tools/engine/package.json";
5
+ if (existsSync(needleEnginePackageJsonPath)) {
6
+ const json = JSON.parse(readFileSync(needleEnginePackageJsonPath));
7
+ const version = json.version;
8
+ return version;
9
+ }
10
+ return null;
11
+ }
@@ -54,6 +54,7 @@ import { ColorBySpeedModule } from "../../engine-components/ParticleSystemModule
54
54
  import { ColorOverLifetimeModule } from "../../engine-components/ParticleSystemModules";
55
55
  import { Component } from "../../engine-components/Component";
56
56
  import { ControlTrackHandler } from "../../engine-components/timeline/TimelineTracks";
57
+ import { CustomBranding } from "../../engine-components/export/usdz/USDZExporter";
57
58
  import { Deletable } from "../../engine-components/DeleteBox";
58
59
  import { DeleteBox } from "../../engine-components/DeleteBox";
59
60
  import { DepthOfField } from "../../engine-components/postprocessing/Effects/DepthOfField";
@@ -126,7 +127,6 @@ import { PostProcessingHandler } from "../../engine-components/postprocessing/Po
126
127
  import { PreliminaryAction } from "../../engine-components/export/usdz/extensions/behavior/BehaviourComponents";
127
128
  import { PreliminaryTrigger } from "../../engine-components/export/usdz/extensions/behavior/BehaviourComponents";
128
129
  import { PresentationMode } from "../../engine-components-experimental/Presentation";
129
- import { QuickLookOverlay } from "../../engine-components/export/usdz/USDZExporter";
130
130
  import { RawImage } from "../../engine-components/ui/Image";
131
131
  import { Raycaster } from "../../engine-components/ui/Raycaster";
132
132
  import { Rect } from "../../engine-components/ui/RectTransform";
@@ -270,6 +270,7 @@ TypeStore.add("ColorBySpeedModule", ColorBySpeedModule);
270
270
  TypeStore.add("ColorOverLifetimeModule", ColorOverLifetimeModule);
271
271
  TypeStore.add("Component", Component);
272
272
  TypeStore.add("ControlTrackHandler", ControlTrackHandler);
273
+ TypeStore.add("CustomBranding", CustomBranding);
273
274
  TypeStore.add("Deletable", Deletable);
274
275
  TypeStore.add("DeleteBox", DeleteBox);
275
276
  TypeStore.add("DepthOfField", DepthOfField);
@@ -342,7 +343,6 @@ TypeStore.add("PostProcessingHandler", PostProcessingHandler);
342
343
  TypeStore.add("PreliminaryAction", PreliminaryAction);
343
344
  TypeStore.add("PreliminaryTrigger", PreliminaryTrigger);
344
345
  TypeStore.add("PresentationMode", PresentationMode);
345
- TypeStore.add("QuickLookOverlay", QuickLookOverlay);
346
346
  TypeStore.add("RawImage", RawImage);
347
347
  TypeStore.add("Raycaster", Raycaster);
348
348
  TypeStore.add("Rect", Rect);
@@ -353,7 +353,7 @@ new AddressableSerializer();
353
353
 
354
354
 
355
355
 
356
-
356
+ const failedTexturePromise = Promise.resolve(null);
357
357
 
358
358
  export class ImageReference {
359
359
 
@@ -392,6 +392,7 @@ export class ImageReference {
392
392
 
393
393
  private loader: TextureLoader | null = null;
394
394
  createTexture(): Promise<Texture | null> {
395
+ if (!this.url) return failedTexturePromise;
395
396
  if (!this.loader) this.loader = new TextureLoader();
396
397
  this.loader.setCrossOrigin("anonymous");
397
398
  return this.loader.loadAsync(this.url);
@@ -1,3 +1,6 @@
1
+ declare const NEEDLE_ENGINE_META: { version: string, generator: string };
2
+ export const NEEDLE_ENGINE_VERSION = NEEDLE_ENGINE_META.version;
3
+ export const NEEDLE_ENGINE_GENERATOR = NEEDLE_ENGINE_META.generator;
1
4
 
2
5
  export const activeInHierarchyFieldName = "needle_isActiveInHierarchy";
3
6
  export const builtinComponentKeyName = "builtin_components";
@@ -29,6 +29,7 @@ import { CoroutineData, ICamera, IComponent, IContext, ILight } from "./engine_t
29
29
  import { destroy, foreachComponent } from './engine_gameobject';
30
30
  import { ContextEvent, ContextRegistry } from './engine_context_registry';
31
31
  import { delay } from './engine_utils';
32
+ import { NEEDLE_ENGINE_VERSION } from './engine_constants';
32
33
  // import { createCameraWithOrbitControl } from '../engine-components/CameraUtils';
33
34
 
34
35
 
@@ -93,6 +94,11 @@ export function registerComponent(script: IComponent, context?: Context) {
93
94
 
94
95
  export class Context implements IContext {
95
96
 
97
+ /** the needle engine version */
98
+ get version() {
99
+ return NEEDLE_ENGINE_VERSION;
100
+ }
101
+
96
102
  static get Current(): Context {
97
103
  return ContextRegistry.Current as Context;
98
104
  }
@@ -436,7 +436,7 @@ function implictlyAssignPrimitiveTypes(obj: any, serializedData: any) {
436
436
  if (isPrimitiveType(data[key]) && !isPrimitiveType(member)) {
437
437
 
438
438
  const prop = tryFindPropertyDescriptor(member, key);
439
- if (!prop?.writable === false || (prop && prop.set === undefined)) {
439
+ if (prop && (prop?.writable === undefined || prop?.writable === false) && (prop.set === undefined)) {
440
440
  if (debug)
441
441
  console.warn("Property is not writable \"" + key + "\"", member, prop, data[key], member[key]);
442
442
  continue;
@@ -52,6 +52,7 @@ export { ColorBySpeedModule } from "../ParticleSystemModules";
52
52
  export { ColorOverLifetimeModule } from "../ParticleSystemModules";
53
53
  export { Component } from "../Component";
54
54
  export { ControlTrackHandler } from "../timeline/TimelineTracks";
55
+ export { CustomBranding } from "../export/usdz/USDZExporter";
55
56
  export { Deletable } from "../DeleteBox";
56
57
  export { DeleteBox } from "../DeleteBox";
57
58
  export { DepthOfField } from "../postprocessing/Effects/DepthOfField";
@@ -121,7 +122,6 @@ export { PointerEventData } from "../ui/PointerEvents";
121
122
  export { PostProcessingHandler } from "../postprocessing/PostProcessingHandler";
122
123
  export { PreliminaryAction } from "../export/usdz/extensions/behavior/BehaviourComponents";
123
124
  export { PreliminaryTrigger } from "../export/usdz/extensions/behavior/BehaviourComponents";
124
- export { QuickLookOverlay } from "../export/usdz/USDZExporter";
125
125
  export { RawImage } from "../ui/Image";
126
126
  export { Raycaster } from "../ui/Raycaster";
127
127
  export { Rect } from "../ui/RectTransform";
@@ -18,7 +18,7 @@ import { AudioExtension } from "./extensions/behavior/AudioExtension";
18
18
 
19
19
  const debug = getParam("debugusdz");
20
20
 
21
- export class QuickLookOverlay {
21
+ export class CustomBranding {
22
22
  @serializable()
23
23
  callToAction?: string;
24
24
  @serializable()
@@ -45,8 +45,8 @@ export class USDZExporter extends Behaviour {
45
45
  @serializable(URL)
46
46
  customUsdzFile?: string;
47
47
 
48
- @serializable(QuickLookOverlay)
49
- overlay?: QuickLookOverlay;
48
+ @serializable(CustomBranding)
49
+ customBranding?: CustomBranding;
50
50
 
51
51
  // Currently not exposed to integrations - not fully tested. Set from code (e.g. image tracking)
52
52
  @serializable()
@@ -66,6 +66,7 @@ export class USDZExporter extends Behaviour {
66
66
  private webARSessionRoot: WebARSessionRoot | undefined;
67
67
 
68
68
  start() {
69
+ console.log(this.customUsdzFile);
69
70
  if (debug) {
70
71
  console.log(this);
71
72
  console.log("Debug USDZ, press 't' to export")
@@ -249,16 +250,27 @@ export class USDZExporter extends Behaviour {
249
250
  if (debug)
250
251
  showBalloonMessage("Quicklook url: " + callToActionURL);
251
252
  if (callToActionURL) {
252
- globalThis.open(callToActionURL, "_blank");
253
+ if (!hasProLicense()) {
254
+ console.warn("Quicklook closed: custom redirects require a Needle Engine Pro license: https://needle.tools/pricing", callToActionURL)
255
+ }
256
+ else {
257
+ globalThis.open(callToActionURL, "_blank");
258
+ }
253
259
  }
254
260
  }
255
261
  }
256
262
  }
257
263
  }
258
264
 
259
- private buildQuicklookOverlay(): QuickLookOverlay {
260
- const obj: QuickLookOverlay = {};
261
- if (this.overlay) Object.assign(obj, this.overlay);
265
+ private buildQuicklookOverlay(): CustomBranding {
266
+ const obj: CustomBranding = {};
267
+ if (this.customBranding) Object.assign(obj, this.customBranding);
268
+ if (!hasProLicense()) {
269
+ console.log("Custom Quicklook banner text requires pro license: https://needle.tools/pricing");
270
+ obj.callToAction = "Close";
271
+ obj.checkoutTitle = "🌵 Made with Needle";
272
+ obj.checkoutSubtitle = "_";
273
+ }
262
274
  if (!obj.callToAction?.length)
263
275
  obj.callToAction = "Close";
264
276
  if (!obj.checkoutTitle?.length)
@@ -174,7 +174,6 @@ export class Graphic extends BaseUIComponent implements IGraphic, IRectTransform
174
174
  static textureCache: Map<Texture, Texture> = new Map();
175
175
 
176
176
  protected async setTexture(tex: Texture | null | undefined) {
177
- if (!tex) return;
178
177
  this.setOptions({ backgroundOpacity: 0 });
179
178
  if (tex) {
180
179
  // workaround for https://github.com/needle-tools/needle-engine-support/issues/109
@@ -190,6 +189,9 @@ export class Graphic extends BaseUIComponent implements IGraphic, IRectTransform
190
189
  }
191
190
  this.setOptions({ backgroundImage: tex, borderRadius: 0, backgroundOpacity: this.color.alpha, backgroundSize: "stretch" });
192
191
  }
192
+ else {
193
+ this.setOptions({ backgroundImage: null, borderRadius: 0, backgroundOpacity: this.color.alpha });
194
+ }
193
195
  }
194
196
 
195
197
  protected onAfterAddedToScene(): void {
@@ -61,10 +61,11 @@ export class Text extends Graphic {
61
61
  }
62
62
 
63
63
  set text(val: string) {
64
-
65
-
66
- this._text = val;
67
- this.feedText(this.text, this.supportRichText);
64
+ if (val !== this._text) {
65
+ this._text = val;
66
+ this.feedText(this.text, this.supportRichText);
67
+ this.markDirty();
68
+ }
68
69
  }
69
70
 
70
71
  private set_text(val: string) {
@@ -1,6 +1,8 @@
1
1
  import { makeErrorsVisibleForDevelopment } from "./engine/debug/debug_overlay";
2
2
  makeErrorsVisibleForDevelopment();
3
3
 
4
+ import { NEEDLE_ENGINE_GENERATOR, NEEDLE_ENGINE_VERSION } from "./engine/engine_constants";
5
+
4
6
  import "./engine/engine_element";
5
7
  import "./engine/engine_setup";
6
8
  import "./engine-components/CameraUtils"
@@ -9,6 +11,7 @@ export * from "./engine/api";
9
11
  export * from "./engine-components/api";
10
12
  export * from "./engine-components-experimental/api";
11
13
 
14
+
12
15
  // make accessible for external javascript
13
16
  import { Context } from "./engine/engine_setup";
14
17
  const Needle = { Context: Context };
@@ -27,6 +30,12 @@ registerGlobal(Component);
27
30
  import * as Components from "./engine-components/codegen/components";
28
31
  registerGlobal(Components);
29
32
 
33
+ Needle["$meta"] = {
34
+ version: NEEDLE_ENGINE_VERSION,
35
+ generator: NEEDLE_ENGINE_GENERATOR
36
+ };
37
+
38
+
30
39
  import { GameObject } from "./engine-components/Component";
31
40
  for (const method of Object.getOwnPropertyNames(GameObject)) {
32
41
  switch (method) {
@@ -50,4 +59,4 @@ else console.warn("Threejs is already imported");
50
59
 
51
60
 
52
61
 
53
- import "./engine/engine_license";
62
+ import "./engine/engine_license";