@@ -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,
|
7
|
+
export const needleDefines = (command, needleEngineConfig, userSettings) => {
|
7
8
|
|
8
9
|
if (!userSettings) userSettings = {};
|
9
10
|
|
10
11
|
let useRapier = true;
|
11
|
-
if (
|
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(
|
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 @@
|
|
21
28
|
}
|
22
29
|
}
|
23
30
|
console.log("UseRapier?", useRapier);
|
24
|
-
if (
|
25
|
-
|
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 @@
|
|
15
16
|
|
16
17
|
return {
|
17
18
|
// replace meta tags
|
18
|
-
name: 'needle-meta
|
19
|
+
name: 'needle-meta',
|
19
20
|
transformIndexHtml: {
|
20
21
|
enforce: 'pre',
|
21
22
|
transform(html, _ctx) {
|
@@ -91,15 +92,27 @@
|
|
91
92
|
}
|
92
93
|
}
|
93
94
|
|
94
|
-
|
95
|
-
|
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 } });
|
96
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")
|
108
|
+
|
97
109
|
return { html, tags }
|
98
110
|
},
|
99
111
|
}
|
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;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { TypeStore } from "./../engine_typestore"
|
2
|
-
|
2
|
+
|
3
3
|
// Import types
|
4
4
|
import { __Ignore } from "../../engine-components/codegen/components";
|
5
5
|
import { ActionBuilder } from "../../engine-components/export/usdz/extensions/behavior/BehavioursBuilder";
|
@@ -54,6 +54,7 @@
|
|
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 @@
|
|
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";
|
@@ -215,7 +215,7 @@
|
|
215
215
|
import { XRGrabRendering } from "../../engine-components/webxr/WebXRGrabRendering";
|
216
216
|
import { XRRig } from "../../engine-components/webxr/WebXRRig";
|
217
217
|
import { XRState } from "../../engine-components/XRFlag";
|
218
|
-
|
218
|
+
|
219
219
|
// Register types
|
220
220
|
TypeStore.add("__Ignore", __Ignore);
|
221
221
|
TypeStore.add("ActionBuilder", ActionBuilder);
|
@@ -270,6 +270,7 @@
|
|
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 @@
|
|
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);
|
@@ -52,6 +52,7 @@
|
|
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 @@
|
|
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";
|
@@ -353,8 +353,8 @@
|
|
353
353
|
|
354
354
|
|
355
355
|
|
356
|
+
const failedTexturePromise = Promise.resolve(null);
|
356
357
|
|
357
|
-
|
358
358
|
export class ImageReference {
|
359
359
|
|
360
360
|
private static imageReferences = new Map<string, ImageReference>();
|
@@ -392,6 +392,7 @@
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
436
436
|
if (isPrimitiveType(data[key]) && !isPrimitiveType(member)) {
|
437
437
|
|
438
438
|
const prop = tryFindPropertyDescriptor(member, key);
|
439
|
-
if (prop?.writable ===
|
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;
|
@@ -174,7 +174,6 @@
|
|
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 @@
|
|
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 {
|
@@ -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 @@
|
|
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 @@
|
|
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 @@
|
|
50
59
|
|
51
60
|
|
52
61
|
|
53
|
-
import "./engine/engine_license";
|
62
|
+
import "./engine/engine_license";
|
@@ -61,10 +61,11 @@
|
|
61
61
|
}
|
62
62
|
|
63
63
|
set text(val: string) {
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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) {
|
@@ -18,7 +18,7 @@
|
|
18
18
|
|
19
19
|
const debug = getParam("debugusdz");
|
20
20
|
|
21
|
-
export class
|
21
|
+
export class CustomBranding {
|
22
22
|
@serializable()
|
23
23
|
callToAction?: string;
|
24
24
|
@serializable()
|
@@ -45,8 +45,8 @@
|
|
45
45
|
@serializable(URL)
|
46
46
|
customUsdzFile?: string;
|
47
47
|
|
48
|
-
@serializable(
|
49
|
-
|
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 @@
|
|
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 @@
|
|
249
250
|
if (debug)
|
250
251
|
showBalloonMessage("Quicklook url: " + callToActionURL);
|
251
252
|
if (callToActionURL) {
|
252
|
-
|
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():
|
260
|
-
const obj:
|
261
|
-
if (this.
|
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)
|
@@ -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
|
+
}
|