@needle-tools/engine 3.0.1-alpha.4 → 3.1.0-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.
- package/CHANGELOG.md +51 -0
- package/dist/needle-engine.js +13110 -12429
- package/dist/needle-engine.min.js +378 -365
- package/dist/needle-engine.umd.cjs +366 -353
- package/lib/engine/api.d.ts +2 -1
- package/lib/engine/api.js +2 -1
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/codegen/register_types.js +8 -0
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/debug/debug_overlay.js +3 -0
- package/lib/engine/debug/debug_overlay.js.map +1 -1
- package/lib/engine/engine_addressables.d.ts +21 -1
- package/lib/engine/engine_addressables.js +83 -7
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_context.d.ts +2 -0
- package/lib/engine/engine_context.js +3 -0
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_element.d.ts +1 -1
- package/lib/engine/engine_element.js +2 -2
- package/lib/engine/engine_element.js.map +1 -1
- package/lib/engine/engine_element_loading.d.ts +7 -2
- package/lib/engine/engine_element_loading.js +67 -22
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_license.d.ts +1 -1
- package/lib/engine/engine_license.js +6 -19
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_networking.d.ts +1 -0
- package/lib/engine/engine_networking.js +3 -0
- package/lib/engine/engine_networking.js.map +1 -1
- package/lib/engine/engine_serialization.d.ts +2 -2
- package/lib/engine/engine_serialization.js +2 -3
- package/lib/engine/engine_serialization.js.map +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.d.ts +5 -0
- package/lib/engine/engine_serialization_builtin_serializer.js +16 -0
- package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
- package/lib/engine/engine_serialization_core.d.ts +1 -0
- package/lib/engine/engine_serialization_core.js +26 -20
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +9 -0
- package/lib/engine/engine_utils.js +33 -13
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_animator_controller_model.d.ts +1 -0
- package/lib/engine/extensions/NEEDLE_animator_controller_model.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_progressive.js +2 -2
- package/lib/engine/extensions/NEEDLE_progressive.js.map +1 -1
- package/lib/engine-components/AnimatorController.js +22 -3
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/AudioSource.d.ts +2 -3
- package/lib/engine-components/AudioSource.js +28 -32
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/CameraUtils.js.map +1 -1
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/ParticleSystem.d.ts +5 -2
- package/lib/engine-components/ParticleSystem.js +49 -10
- package/lib/engine-components/ParticleSystem.js.map +1 -1
- package/lib/engine-components/ParticleSystemModules.d.ts +2 -0
- package/lib/engine-components/ParticleSystemModules.js +23 -12
- package/lib/engine-components/ParticleSystemModules.js.map +1 -1
- package/lib/engine-components/ScreenCapture.d.ts +1 -0
- package/lib/engine-components/ScreenCapture.js +145 -46
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/Skybox.js +2 -2
- package/lib/engine-components/Skybox.js.map +1 -1
- package/lib/engine-components/SyncedRoom.js +1 -2
- package/lib/engine-components/SyncedRoom.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +4 -2
- package/lib/engine-components/VideoPlayer.js +35 -12
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +4 -1
- package/lib/engine-components/WebXR.js +10 -2
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRController.js +2 -2
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/WebXRImageTracking.d.ts +39 -0
- package/lib/engine-components/WebXRImageTracking.js +173 -0
- package/lib/engine-components/WebXRImageTracking.js.map +1 -0
- package/lib/engine-components/codegen/components.d.ts +4 -0
- package/lib/engine-components/codegen/components.js +4 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/DepthOfField.d.ts +2 -0
- package/lib/engine-components/postprocessing/Effects/DepthOfField.js +19 -1
- package/lib/engine-components/postprocessing/Effects/DepthOfField.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.d.ts +13 -0
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.js +63 -0
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.js.map +1 -0
- package/lib/engine-components/postprocessing/VolumeParameter.d.ts +1 -0
- package/lib/engine-components/postprocessing/VolumeParameter.js +4 -0
- package/lib/engine-components/postprocessing/VolumeParameter.js.map +1 -1
- package/lib/engine-components/timeline/PlayableDirector.d.ts +3 -1
- package/lib/engine-components/timeline/PlayableDirector.js +40 -2
- package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
- package/lib/engine-components/timeline/TimelineTracks.d.ts +2 -2
- package/lib/engine-components/timeline/TimelineTracks.js +14 -16
- package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
- package/lib/engine-components/ui/Text.js +7 -8
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/include/three/ARButton.d.ts +1 -1
- package/lib/include/three/ARButton.js +2 -1
- package/lib/include/three/ARButton.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -4
- package/plugins/vite/config.js +8 -0
- package/plugins/vite/copyfiles.js +12 -3
- package/plugins/vite/drop.js +1 -0
- package/plugins/vite/index.js +4 -0
- package/plugins/vite/license.js +24 -0
- package/plugins/vite/transform-codegen.js +45 -0
- package/src/engine/api.ts +2 -2
- package/src/engine/codegen/register_types.js +10 -2
- package/src/engine/debug/debug_overlay.ts +2 -0
- package/src/engine/engine_addressables.ts +102 -8
- package/src/engine/engine_context.ts +4 -1
- package/src/engine/engine_element.ts +2 -2
- package/src/engine/engine_element_loading.ts +68 -22
- package/src/engine/engine_license.ts +6 -17
- package/src/engine/engine_networking.ts +4 -0
- package/src/engine/engine_serialization.ts +5 -4
- package/src/engine/engine_serialization_builtin_serializer.ts +23 -3
- package/src/engine/engine_serialization_core.ts +27 -20
- package/src/engine/engine_utils.ts +35 -14
- package/src/engine/extensions/NEEDLE_animator_controller_model.ts +1 -0
- package/src/engine/extensions/NEEDLE_progressive.ts +2 -2
- package/src/engine-components/AnimatorController.ts +18 -3
- package/src/engine-components/AudioSource.ts +29 -38
- package/src/engine-components/CameraUtils.ts +2 -2
- package/src/engine-components/Component.ts +1 -1
- package/src/engine-components/ParticleSystem.ts +52 -10
- package/src/engine-components/ParticleSystemModules.ts +24 -12
- package/src/engine-components/ScreenCapture.ts +149 -49
- package/src/engine-components/Skybox.ts +2 -2
- package/src/engine-components/SyncedRoom.ts +1 -2
- package/src/engine-components/VideoPlayer.ts +33 -11
- package/src/engine-components/WebXR.ts +11 -2
- package/src/engine-components/WebXRController.ts +2 -2
- package/src/engine-components/WebXRImageTracking.ts +192 -0
- package/src/engine-components/codegen/components.ts +4 -0
- package/src/engine-components/postprocessing/Effects/DepthOfField.ts +21 -6
- package/src/engine-components/postprocessing/Effects/TiltShiftEffect.ts +56 -0
- package/src/engine-components/postprocessing/VolumeParameter.ts +5 -0
- package/src/engine-components/timeline/PlayableDirector.ts +38 -2
- package/src/engine-components/timeline/TimelineTracks.ts +15 -18
- package/src/engine-components/ui/Text.ts +7 -8
- package/src/include/three/ARButton.js +2 -2
- package/lib/engine/codegen/license.json +0 -1
- package/license-2447137e.js +0 -4
- package/src/engine/codegen/license.json +0 -1
|
@@ -47,6 +47,7 @@ export enum WebXREvent {
|
|
|
47
47
|
XRStopped = "xrStopped",
|
|
48
48
|
XRUpdate = "xrUpdate",
|
|
49
49
|
RequestVRSession = "requestVRSession",
|
|
50
|
+
ModifyAROptions = "modify-ar-options",
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
export declare type CreateButtonOptions = {
|
|
@@ -91,6 +92,9 @@ export class WebXR extends Behaviour {
|
|
|
91
92
|
this.events.removeEventListener(type, listener);
|
|
92
93
|
return listener;
|
|
93
94
|
}
|
|
95
|
+
private static dispatchEvent(type: string, event: any): void {
|
|
96
|
+
this.events.dispatchEvent({ type, detail: event });
|
|
97
|
+
}
|
|
94
98
|
|
|
95
99
|
public static createVRButton(webXR: WebXR, opts?: CreateButtonOptions): HTMLButtonElement | HTMLAnchorElement {
|
|
96
100
|
if (!WebXR.XRSupported) {
|
|
@@ -122,7 +126,7 @@ export class WebXR extends Behaviour {
|
|
|
122
126
|
console.warn("No dom overlay root found, HTML overlays on top of screen-based AR will not work.");
|
|
123
127
|
}
|
|
124
128
|
|
|
125
|
-
const arButton = ARButton.createButton(webXR.context.renderer, options);
|
|
129
|
+
const arButton = ARButton.createButton(webXR.context.renderer, options, this.onModifyAROptions.bind(this));
|
|
126
130
|
arButton.classList.add('webxr-ar-button');
|
|
127
131
|
arButton.classList.add('webxr-button');
|
|
128
132
|
WebXR.resetButtonStyles(arButton);
|
|
@@ -131,6 +135,10 @@ export class WebXR extends Behaviour {
|
|
|
131
135
|
return arButton;
|
|
132
136
|
}
|
|
133
137
|
|
|
138
|
+
private static onModifyAROptions(options){
|
|
139
|
+
WebXR.dispatchEvent(WebXREvent.ModifyAROptions, options);
|
|
140
|
+
}
|
|
141
|
+
|
|
134
142
|
public static resetButtonStyles(button) {
|
|
135
143
|
if (!button) return;
|
|
136
144
|
button.style.position = "";
|
|
@@ -233,7 +241,8 @@ export class WebXR extends Behaviour {
|
|
|
233
241
|
this.context.domElement.append(buttonsContainer);
|
|
234
242
|
|
|
235
243
|
// AR support
|
|
236
|
-
if (this.enableAR && this.createARButton && arSupported)
|
|
244
|
+
// if (this.enableAR && this.createARButton && arSupported)
|
|
245
|
+
{
|
|
237
246
|
arButton = WebXR.createARButton(this);
|
|
238
247
|
this._arButton = arButton;
|
|
239
248
|
buttonsContainer.appendChild(arButton);
|
|
@@ -8,7 +8,7 @@ import { InstancingUtil } from "../engine/engine_instancing";
|
|
|
8
8
|
import { Mathf } from "../engine/engine_math";
|
|
9
9
|
import { RaycastOptions } from "../engine/engine_physics";
|
|
10
10
|
import { getWorldPosition, getWorldQuaternion, setWorldPosition, setWorldQuaternion } from "../engine/engine_three_utils";
|
|
11
|
-
import { getParam,
|
|
11
|
+
import { getParam, resolveUrl } from "../engine/engine_utils";
|
|
12
12
|
import { addDracoAndKTX2Loaders } from "../engine/engine_loaders";
|
|
13
13
|
|
|
14
14
|
import { Avatar_POI } from "./avatar/Avatar_Brain_LookAt";
|
|
@@ -85,7 +85,7 @@ export class WebXRController extends Behaviour {
|
|
|
85
85
|
const loader = new GLTFLoader();
|
|
86
86
|
addDracoAndKTX2Loaders(loader, context);
|
|
87
87
|
if (ctrl.webXR.handModelPath && ctrl.webXR.handModelPath !== "")
|
|
88
|
-
loader.setPath(
|
|
88
|
+
loader.setPath(resolveUrl(owner.sourceId, ctrl.webXR.handModelPath));
|
|
89
89
|
else
|
|
90
90
|
// from XRHandMeshModel.js
|
|
91
91
|
loader.setPath('https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles/generic-hand/');
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { WebXR } from "./WebXR";
|
|
2
|
+
import { serializable } from "../engine/engine_serialization";
|
|
3
|
+
import { Behaviour } from "./Component";
|
|
4
|
+
import { Matrix4, Object3D, Quaternion, Vector, Vector3 } from "three";
|
|
5
|
+
import { CircularBuffer, getParam } from "../engine/engine_utils";
|
|
6
|
+
|
|
7
|
+
// https://github.com/immersive-web/marker-tracking/blob/main/explainer.md
|
|
8
|
+
|
|
9
|
+
const debug = getParam("debugimagetracking");
|
|
10
|
+
|
|
11
|
+
const _scaleTemp = new Vector3();
|
|
12
|
+
|
|
13
|
+
export class WebXRTrackedImage {
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
get url(): string { return this._trackedImage.image ?? ""; }
|
|
17
|
+
get widthInMeters() { return this._trackedImage.widthInMeters ?? undefined; }
|
|
18
|
+
get bitmap(): ImageBitmap { return this._bitmap; }
|
|
19
|
+
readonly measuredSize: number;
|
|
20
|
+
readonly state: "tracked" | "emulated";
|
|
21
|
+
|
|
22
|
+
// private _matrix: Matrix4 | null = null;
|
|
23
|
+
// private get matrix(): Matrix4 {
|
|
24
|
+
// if (!this._matrix) {
|
|
25
|
+
// // this._matrix = WebXRTrackedImage._matrixBuffer.get();
|
|
26
|
+
// // const matrix = this._pose.transform.matrix;
|
|
27
|
+
// // this._matrix.fromArray(matrix);
|
|
28
|
+
// }
|
|
29
|
+
// return this._matrix!;
|
|
30
|
+
// }
|
|
31
|
+
|
|
32
|
+
/** Copy the image position to a vector */
|
|
33
|
+
getPosition(vec: Vector3) {
|
|
34
|
+
this.ensureTransformData();
|
|
35
|
+
vec.copy(this._position);
|
|
36
|
+
return vec;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Copy the image rotation to a quaternion */
|
|
40
|
+
getQuaternion(quat: Quaternion) {
|
|
41
|
+
this.ensureTransformData();
|
|
42
|
+
quat.copy(this._rotation);
|
|
43
|
+
return quat;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
applyToObject(object: Object3D) {
|
|
47
|
+
this.ensureTransformData();
|
|
48
|
+
object.position.copy(this._position);
|
|
49
|
+
object.quaternion.copy(this._rotation);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// private static _matrixBuffer: CircularBuffer<Matrix4> = new CircularBuffer(() => new Matrix4(), 20);
|
|
53
|
+
private static _positionBuffer: CircularBuffer<Vector3> = new CircularBuffer(() => new Vector3(), 20);
|
|
54
|
+
private static _rotationBuffer: CircularBuffer<Quaternion> = new CircularBuffer(() => new Quaternion(), 20);
|
|
55
|
+
private _position!: Vector3;
|
|
56
|
+
private _rotation!: Quaternion;
|
|
57
|
+
private ensureTransformData() {
|
|
58
|
+
if (!this._position) {
|
|
59
|
+
this._position = WebXRTrackedImage._positionBuffer.get();
|
|
60
|
+
this._rotation = WebXRTrackedImage._rotationBuffer.get();
|
|
61
|
+
const t = this._pose.transform;
|
|
62
|
+
this._position.set(-t.position.x, t.position.y, -t.position.z);
|
|
63
|
+
this._rotation.set(-t.orientation.x, t.orientation.y, -t.orientation.z, t.orientation.w);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private readonly _trackingComponent: WebXRImageTracking;;
|
|
68
|
+
private readonly _trackedImage: WebXRImageTrackingModel;
|
|
69
|
+
private readonly _bitmap: ImageBitmap;
|
|
70
|
+
private readonly _pose: any;
|
|
71
|
+
|
|
72
|
+
constructor(context: WebXRImageTracking, trackedImage: WebXRImageTrackingModel, bitmap: ImageBitmap, measuredSize: number, state: "tracked" | "emulated", pose: any) {
|
|
73
|
+
this._trackingComponent = context;;
|
|
74
|
+
this._trackedImage = trackedImage;
|
|
75
|
+
this._bitmap = bitmap;
|
|
76
|
+
this.measuredSize = measuredSize;
|
|
77
|
+
this.state = state;
|
|
78
|
+
this._pose = pose;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
declare type WebXRImageTrackingEvent = (images: WebXRImageTrackingEvent[]) => void;
|
|
84
|
+
|
|
85
|
+
export class WebXRImageTrackingModel {
|
|
86
|
+
|
|
87
|
+
@serializable()
|
|
88
|
+
image?: string;
|
|
89
|
+
|
|
90
|
+
@serializable()
|
|
91
|
+
widthInMeters!: number;
|
|
92
|
+
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export class WebXRImageTracking extends Behaviour {
|
|
96
|
+
|
|
97
|
+
@serializable(WebXRImageTrackingModel)
|
|
98
|
+
trackedImages!: WebXRImageTrackingModel[];
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
private readonly trackedImageIndexMap: Map<number, WebXRImageTrackingModel> = new Map();
|
|
104
|
+
|
|
105
|
+
private static _imageElements: Map<string, ImageBitmap | null> = new Map();
|
|
106
|
+
|
|
107
|
+
awake(): void {
|
|
108
|
+
for (const trackedImage of this.trackedImages) {
|
|
109
|
+
if (trackedImage.image) {
|
|
110
|
+
if (WebXRImageTracking._imageElements.has(trackedImage.image)) {
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const url = trackedImage.image;
|
|
114
|
+
WebXRImageTracking._imageElements.set(url, null);
|
|
115
|
+
const imageElement = document.createElement("img") as HTMLImageElement;
|
|
116
|
+
imageElement.src = url;
|
|
117
|
+
imageElement.addEventListener("load", async () => {
|
|
118
|
+
const img = await createImageBitmap(imageElement);
|
|
119
|
+
WebXRImageTracking._imageElements.set(url, img);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
onEnable(): void {
|
|
127
|
+
WebXR.addEventListener("modify-ar-options", this.onModifyAROptions);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
onDisable(): void {
|
|
131
|
+
WebXR.removeEventListener("modify-ar-options", this.onModifyAROptions);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
private onModifyAROptions = (event: any) => {
|
|
136
|
+
const options = event.detail;
|
|
137
|
+
const features = options.optionalFeatures || [];
|
|
138
|
+
features.push("image-tracking");
|
|
139
|
+
options.optionalFeatures = features;
|
|
140
|
+
|
|
141
|
+
options.trackedImages = [];
|
|
142
|
+
for (const trackedImage of this.trackedImages) {
|
|
143
|
+
if (trackedImage.image?.length && trackedImage.widthInMeters > 0) {
|
|
144
|
+
const bitmap = WebXRImageTracking._imageElements.get(trackedImage.image);
|
|
145
|
+
if (bitmap) {
|
|
146
|
+
this.trackedImageIndexMap.set(options.trackedImages.length, trackedImage);
|
|
147
|
+
options.trackedImages.push({
|
|
148
|
+
image: bitmap,
|
|
149
|
+
widthInMeters: trackedImage.widthInMeters
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
onBeforeRender(frame: XRFrame | null): void {
|
|
157
|
+
//@ts-ignore
|
|
158
|
+
if (frame?.session && typeof frame.getImageTrackingResults === "function") {
|
|
159
|
+
//@ts-ignore
|
|
160
|
+
const results = frame.getImageTrackingResults();
|
|
161
|
+
if (results.length) {
|
|
162
|
+
const space = this.context.renderer.xr.getReferenceSpace();
|
|
163
|
+
if (space) {
|
|
164
|
+
const images: WebXRTrackedImage[] = [];
|
|
165
|
+
for (const result of results) {
|
|
166
|
+
const imageIndex = result.index;
|
|
167
|
+
const trackedImage = this.trackedImageIndexMap.get(imageIndex);
|
|
168
|
+
if (trackedImage) {
|
|
169
|
+
const pose = frame.getPose(result.imageSpace, space);
|
|
170
|
+
const state = result.trackingState;
|
|
171
|
+
const imageData = new WebXRTrackedImage(this, trackedImage, result.image, result.measuredSize, state, pose);
|
|
172
|
+
images.push(imageData);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
if (debug) {
|
|
176
|
+
console.warn("No tracked image for index", imageIndex);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (images.length > 0) {
|
|
181
|
+
try {
|
|
182
|
+
this.dispatchEvent(new CustomEvent("image-tracking", { detail: images }));
|
|
183
|
+
}
|
|
184
|
+
catch (e) {
|
|
185
|
+
console.error(e);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -145,6 +145,7 @@ export { TestRunner } from "../TestRunner";
|
|
|
145
145
|
export { TestSimulateUserData } from "../TestRunner";
|
|
146
146
|
export { Text } from "../ui/Text";
|
|
147
147
|
export { TextureSheetAnimationModule } from "../ParticleSystemModules";
|
|
148
|
+
export { TiltShiftEffect } from "../postprocessing/Effects/TiltShiftEffect";
|
|
148
149
|
export { ToneMapping } from "../postprocessing/Effects/Tonemapping";
|
|
149
150
|
export { TrailModule } from "../ParticleSystemModules";
|
|
150
151
|
export { TransformData } from "../export/usdz/extensions/Animation";
|
|
@@ -168,7 +169,10 @@ export { WebARSessionRoot } from "../WebARSessionRoot";
|
|
|
168
169
|
export { WebXR } from "../WebXR";
|
|
169
170
|
export { WebXRAvatar } from "../WebXRAvatar";
|
|
170
171
|
export { WebXRController } from "../WebXRController";
|
|
172
|
+
export { WebXRImageTracking } from "../WebXRImageTracking";
|
|
173
|
+
export { WebXRImageTrackingModel } from "../WebXRImageTracking";
|
|
171
174
|
export { WebXRSync } from "../WebXRSync";
|
|
175
|
+
export { WebXRTrackedImage } from "../WebXRImageTracking";
|
|
172
176
|
export { XRFlag } from "../XRFlag";
|
|
173
177
|
export { XRGrabModel } from "../WebXRGrabRendering";
|
|
174
178
|
export { XRGrabRendering } from "../WebXRGrabRendering";
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { DepthOfFieldEffect } from "postprocessing";
|
|
2
|
-
import { PerspectiveCamera, Vector3 } from "three";
|
|
3
|
-
import { getWorldPosition } from "../../../engine/engine_three_utils";
|
|
4
2
|
import { serializable } from "../../../engine/engine_serialization";
|
|
5
3
|
import { Mathf } from "../../../engine/engine_math";
|
|
6
4
|
import { PostProcessingEffect } from "../PostProcessingEffect";
|
|
7
5
|
import { VolumeParameter } from "../VolumeParameter";
|
|
8
6
|
import { registerCustomEffectType } from "../VolumeProfile";
|
|
7
|
+
import { isMobileDevice } from "../../../engine/engine_utils";
|
|
9
8
|
|
|
10
9
|
export enum DepthOfFieldMode {
|
|
11
10
|
Off = 0,
|
|
@@ -20,7 +19,7 @@ export class DepthOfField extends PostProcessingEffect {
|
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
@serializable()
|
|
23
|
-
mode
|
|
22
|
+
mode!: DepthOfFieldMode;
|
|
24
23
|
|
|
25
24
|
@serializable(VolumeParameter)
|
|
26
25
|
focusDistance!: VolumeParameter;
|
|
@@ -34,13 +33,19 @@ export class DepthOfField extends PostProcessingEffect {
|
|
|
34
33
|
@serializable(VolumeParameter)
|
|
35
34
|
gaussianMaxRadius!: VolumeParameter;
|
|
36
35
|
|
|
36
|
+
@serializable(VolumeParameter)
|
|
37
|
+
resolutionScale?: VolumeParameter;
|
|
38
|
+
|
|
39
|
+
@serializable(VolumeParameter)
|
|
40
|
+
bokehScale?: VolumeParameter;
|
|
41
|
+
|
|
37
42
|
init() {
|
|
38
43
|
this.focalLength.valueProcessor = v => {
|
|
39
44
|
const t = v / 300;
|
|
40
45
|
const max = 2;// this.context.mainCameraComponent?.farClipPlane ?? 10;
|
|
41
46
|
return Mathf.lerp(max, .01, t);
|
|
42
47
|
};
|
|
43
|
-
|
|
48
|
+
|
|
44
49
|
const maxBokehScale = 20;
|
|
45
50
|
this.aperture.valueProcessor = v => {
|
|
46
51
|
const t = 1 - v / 32;
|
|
@@ -49,7 +54,16 @@ export class DepthOfField extends PostProcessingEffect {
|
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
onCreateEffect() {
|
|
52
|
-
if(this.mode === DepthOfFieldMode.Off) return undefined;
|
|
57
|
+
if (this.mode === DepthOfFieldMode.Off) return undefined;
|
|
58
|
+
|
|
59
|
+
const factor = 1 / window.devicePixelRatio;
|
|
60
|
+
|
|
61
|
+
if (this.resolutionScale === undefined) {
|
|
62
|
+
let defaultValue = 1;
|
|
63
|
+
if(isMobileDevice()) defaultValue = .6;
|
|
64
|
+
this.resolutionScale = new VolumeParameter(defaultValue * factor);
|
|
65
|
+
}
|
|
66
|
+
|
|
53
67
|
// console.log(this.focusDistance.overrideState, this.focusDistance.value);
|
|
54
68
|
// const depth = new DepthEffect({
|
|
55
69
|
// inverted: true,
|
|
@@ -59,7 +73,7 @@ export class DepthOfField extends PostProcessingEffect {
|
|
|
59
73
|
worldFocusRange: .2,
|
|
60
74
|
focalLength: 1,
|
|
61
75
|
bokehScale: 20,
|
|
62
|
-
resolutionScale:
|
|
76
|
+
resolutionScale: this.resolutionScale.value,
|
|
63
77
|
});
|
|
64
78
|
|
|
65
79
|
this.focusDistance.onValueChanged = v => {
|
|
@@ -68,6 +82,7 @@ export class DepthOfField extends PostProcessingEffect {
|
|
|
68
82
|
this.focalLength.onValueChanged = v => dof.circleOfConfusionMaterial.worldFocusRange = v;
|
|
69
83
|
this.aperture.onValueChanged = v => dof.bokehScale = v;
|
|
70
84
|
|
|
85
|
+
if (this.resolutionScale) this.resolutionScale.onValueChanged = v => dof.resolution.scale = v;
|
|
71
86
|
|
|
72
87
|
return [dof];
|
|
73
88
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { registerCustomEffectType } from "../VolumeProfile";
|
|
2
|
+
import { EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect";
|
|
3
|
+
import { KernelSize, TiltShiftEffect as TiltShift } from "postprocessing";
|
|
4
|
+
import { VolumeParameter } from "../VolumeParameter";
|
|
5
|
+
import { serializable } from "../../../engine/engine_serialization";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export class TiltShiftEffect extends PostProcessingEffect {
|
|
9
|
+
get typeName(): string {
|
|
10
|
+
return "TiltShiftEffect";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@serializable(VolumeParameter)
|
|
14
|
+
offset!: VolumeParameter;
|
|
15
|
+
@serializable(VolumeParameter)
|
|
16
|
+
rotation!: VolumeParameter;
|
|
17
|
+
@serializable(VolumeParameter)
|
|
18
|
+
focusArea!: VolumeParameter;
|
|
19
|
+
@serializable(VolumeParameter)
|
|
20
|
+
feather!: VolumeParameter
|
|
21
|
+
@serializable(VolumeParameter)
|
|
22
|
+
kernelSize!: VolumeParameter;
|
|
23
|
+
@serializable(VolumeParameter)
|
|
24
|
+
resolutionScale!: VolumeParameter;
|
|
25
|
+
|
|
26
|
+
init(): void {
|
|
27
|
+
this.offset.defaultValue = 0;
|
|
28
|
+
this.rotation.defaultValue = 0;
|
|
29
|
+
this.focusArea.defaultValue = 0.4;
|
|
30
|
+
this.feather.defaultValue = 0.3;
|
|
31
|
+
this.kernelSize.defaultValue = KernelSize.MEDIUM;
|
|
32
|
+
this.resolutionScale.defaultValue = 1 / window.devicePixelRatio;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
onCreateEffect(): EffectProviderResult | undefined {
|
|
37
|
+
|
|
38
|
+
console.log(this);
|
|
39
|
+
|
|
40
|
+
const effect = new TiltShift({
|
|
41
|
+
kernelSize: KernelSize.VERY_LARGE,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
this.offset.onValueChanged = v => effect.offset = v;
|
|
45
|
+
this.rotation.onValueChanged = v => effect.rotation = v;
|
|
46
|
+
this.focusArea.onValueChanged = v => effect.focusArea = v;
|
|
47
|
+
this.feather.onValueChanged = v => effect.feather = v;
|
|
48
|
+
this.kernelSize.onValueChanged = v => effect.blurPass.kernelSize = v;
|
|
49
|
+
this.resolutionScale.onValueChanged = v => effect.resolution.scale = v / window.devicePixelRatio;
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
return effect;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
registerCustomEffectType("TiltShiftEffect", TiltShiftEffect);
|
|
@@ -5,6 +5,11 @@ export declare type VolumeParameterValueProcessor = (value: any) => any;
|
|
|
5
5
|
|
|
6
6
|
export class VolumeParameter {
|
|
7
7
|
|
|
8
|
+
constructor(value?: any) {
|
|
9
|
+
this._value = value;
|
|
10
|
+
this._defaultValue = value;
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
@serializable()
|
|
9
14
|
get overrideState(): boolean {
|
|
10
15
|
return this._active;
|
|
@@ -6,7 +6,7 @@ import { AudioSource } from '../AudioSource';
|
|
|
6
6
|
import { SignalReceiver } from './SignalAsset';
|
|
7
7
|
import * as Models from "./TimelineModels";
|
|
8
8
|
import * as Tracks from "./TimelineTracks";
|
|
9
|
-
import { deepClone, getParam } from '../../engine/engine_utils';
|
|
9
|
+
import { deepClone, delay, getParam } from '../../engine/engine_utils';
|
|
10
10
|
import { GuidsMap } from '../../engine/engine_types';
|
|
11
11
|
import { Object3D } from 'three';
|
|
12
12
|
import { isLocalNetwork } from '../../engine/engine_networking_utils';
|
|
@@ -87,6 +87,8 @@ export class PlayableDirector extends Behaviour {
|
|
|
87
87
|
get speed(): number { return this._speed; }
|
|
88
88
|
set speed(value: number) { this._speed = value; }
|
|
89
89
|
|
|
90
|
+
/** When enabled the timeline will wait for audio tracks to load at the current time before starting to play */
|
|
91
|
+
waitForAudio: boolean = true;
|
|
90
92
|
|
|
91
93
|
private _visibilityChangeEvt?: any;
|
|
92
94
|
private _clonedPlayableAsset: boolean = false;
|
|
@@ -151,13 +153,28 @@ export class PlayableDirector extends Behaviour {
|
|
|
151
153
|
this.setupAndCreateTrackHandlers();
|
|
152
154
|
}
|
|
153
155
|
|
|
154
|
-
play() {
|
|
156
|
+
async play() {
|
|
155
157
|
if (!this.isValid()) return;
|
|
156
158
|
const pauseChanged = this._isPaused == true;
|
|
157
159
|
this._isPaused = false;
|
|
158
160
|
if (pauseChanged) this.invokePauseChangedMethodsOnTracks();
|
|
159
161
|
if (this._isPlaying) return;
|
|
160
162
|
this._isPlaying = true;
|
|
163
|
+
if (this.waitForAudio) {
|
|
164
|
+
// Make sure audio tracks have loaded at the current time
|
|
165
|
+
const promises: Array<Promise<any>> = [];
|
|
166
|
+
for (const track of this._audioTracks) {
|
|
167
|
+
const promise = track.loadAudio(this._time, 1, 0);
|
|
168
|
+
if (promise)
|
|
169
|
+
promises.push(promise);
|
|
170
|
+
}
|
|
171
|
+
if (promises.length > 0) {
|
|
172
|
+
await Promise.all(promises);
|
|
173
|
+
if (!this._isPlaying) return;
|
|
174
|
+
}
|
|
175
|
+
while(this._audioTracks.length > 0 && this._isPlaying && !AudioSource.userInteractionRegistered && this.waitForAudio)
|
|
176
|
+
await delay(200);
|
|
177
|
+
}
|
|
161
178
|
this._internalUpdateRoutine = this.startCoroutine(this.internalUpdate());
|
|
162
179
|
}
|
|
163
180
|
|
|
@@ -363,6 +380,25 @@ export class PlayableDirector extends Behaviour {
|
|
|
363
380
|
console.warn("Missing binding", binding, track.name, track.type, this.name, this.playableAsset.name);
|
|
364
381
|
}
|
|
365
382
|
}
|
|
383
|
+
if (track.type === Models.TrackType.Control) {
|
|
384
|
+
for (let i = 0; i < track.clips.length; i++) {
|
|
385
|
+
const clip = track.clips[i];
|
|
386
|
+
let binding = clip.asset.sourceObject;
|
|
387
|
+
if (typeof binding === "string") {
|
|
388
|
+
if (this._guidsMap && this._guidsMap[binding])
|
|
389
|
+
binding = this._guidsMap[binding];
|
|
390
|
+
const obj = GameObject.findByGuid(binding, root);
|
|
391
|
+
if (obj === null || typeof obj !== "object") {
|
|
392
|
+
console.warn("Failed to resolve sourceObject binding", binding, track.name, clip);
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
if (debug)
|
|
396
|
+
console.log("Resolved binding", binding, "to", obj);
|
|
397
|
+
clip.asset.sourceObject = obj;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
366
402
|
}
|
|
367
403
|
}
|
|
368
404
|
|
|
@@ -5,7 +5,7 @@ import { GameObject } from "../Component";
|
|
|
5
5
|
import { Context } from "../../engine/engine_setup";
|
|
6
6
|
import { SignalReceiver } from "./SignalAsset";
|
|
7
7
|
import { AnimationClip, Quaternion, Vector3 } from "three";
|
|
8
|
-
import { getParam,
|
|
8
|
+
import { getParam, resolveUrl } from "../../engine/engine_utils";
|
|
9
9
|
import { AudioSource } from "../AudioSource";
|
|
10
10
|
import { Animator } from "../Animator"
|
|
11
11
|
|
|
@@ -517,7 +517,7 @@ export class AudioTrackHandler extends TrackHandler {
|
|
|
517
517
|
private getAudioFilePath(path: string) {
|
|
518
518
|
// TODO: this should be the timeline asset location probably which MIGHT be different
|
|
519
519
|
const glbLocation = this.director.sourceId;
|
|
520
|
-
return
|
|
520
|
+
return resolveUrl(glbLocation, path);
|
|
521
521
|
}
|
|
522
522
|
|
|
523
523
|
onAllowAudioChanged(allow: boolean) {
|
|
@@ -657,6 +657,9 @@ export class AudioTrackHandler extends TrackHandler {
|
|
|
657
657
|
}
|
|
658
658
|
|
|
659
659
|
private static _currentlyLoading: Map<string, Promise<AudioBuffer | null>> = new Map();
|
|
660
|
+
public static dispose() {
|
|
661
|
+
AudioTrackHandler._currentlyLoading.clear();
|
|
662
|
+
}
|
|
660
663
|
|
|
661
664
|
private handleAudioLoading(model: Models.ClipModel, audio: THREE.Audio): Promise<AudioBuffer | null> | null {
|
|
662
665
|
if (!this._audioLoader) {
|
|
@@ -665,8 +668,12 @@ export class AudioTrackHandler extends TrackHandler {
|
|
|
665
668
|
// TODO: maybe we should cache the loaders / buffers here by path
|
|
666
669
|
const path = this.getAudioFilePath(model.asset.clip);
|
|
667
670
|
|
|
668
|
-
if(AudioTrackHandler._currentlyLoading.get(path)) {
|
|
669
|
-
|
|
671
|
+
if (AudioTrackHandler._currentlyLoading.get(path)) {
|
|
672
|
+
const promise = AudioTrackHandler._currentlyLoading.get(path)!
|
|
673
|
+
promise.then((buffer) => {
|
|
674
|
+
if (buffer) audio.setBuffer(buffer);
|
|
675
|
+
});
|
|
676
|
+
return promise;
|
|
670
677
|
}
|
|
671
678
|
|
|
672
679
|
if (debug) console.warn("LOAD audio track", path, this.director.sourceId);
|
|
@@ -724,23 +731,13 @@ export class ControlTrackHandler extends TrackHandler {
|
|
|
724
731
|
models: Array<Models.ClipModel> = [];
|
|
725
732
|
timelines: Array<PlayableDirector | null> = [];
|
|
726
733
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
resolveSourceObjects(context: Context) {
|
|
734
|
+
resolveSourceObjects(_context: Context) {
|
|
730
735
|
for (let i = this.models.length - 1; i >= 0; i--) {
|
|
731
736
|
const model = this.models[i];
|
|
732
737
|
const asset = model.asset as Models.ControlClipModel;
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
asset.sourceObject = ControlTrackHandler.resolved[key];
|
|
737
|
-
}
|
|
738
|
-
else {
|
|
739
|
-
asset.sourceObject = GameObject.findByGuid(key, context.scene) as THREE.Object3D
|
|
740
|
-
ControlTrackHandler.resolved[key] = asset.sourceObject;
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
if (!asset.sourceObject) {
|
|
738
|
+
|
|
739
|
+
if (!asset.sourceObject || typeof asset.sourceObject !== "object") {
|
|
740
|
+
console.log("no source object, removing model", i, asset);
|
|
744
741
|
this.models.splice(i, 1);
|
|
745
742
|
continue;
|
|
746
743
|
}
|
|
@@ -7,7 +7,7 @@ import { FrameEvent } from '../../engine/engine_setup';
|
|
|
7
7
|
import { updateRenderSettings } from './Utils';
|
|
8
8
|
import { Canvas } from './Canvas';
|
|
9
9
|
import { serializable } from '../../engine/engine_serialization_decorator';
|
|
10
|
-
import { getParam,
|
|
10
|
+
import { getParam, resolveUrl } from '../../engine/engine_utils';
|
|
11
11
|
|
|
12
12
|
const debug = getParam("debugtext");
|
|
13
13
|
|
|
@@ -176,7 +176,6 @@ export class Text extends Graphic {
|
|
|
176
176
|
fontSize: fontSize,
|
|
177
177
|
fontKerning: "normal",
|
|
178
178
|
};
|
|
179
|
-
this.font = this.font?.toLocaleLowerCase();
|
|
180
179
|
this.setFont(textOpts, this.fontStyle);
|
|
181
180
|
return textOpts;
|
|
182
181
|
}
|
|
@@ -482,24 +481,24 @@ export class Text extends Graphic {
|
|
|
482
481
|
|
|
483
482
|
// if a font path has a known suffix we remove it
|
|
484
483
|
if (fontName.endsWith("-regular")) {
|
|
485
|
-
if (style === FontStyle.Normal) return
|
|
484
|
+
if (style === FontStyle.Normal) return resolveUrl(this.sourceId, fontName);
|
|
486
485
|
fontName = fontName.substring(0, fontName.length - "-regular".length);
|
|
487
486
|
}
|
|
488
487
|
else if (fontName.endsWith("-bold")) {
|
|
489
|
-
if (style === FontStyle.Bold)return
|
|
488
|
+
if (style === FontStyle.Bold)return resolveUrl(this.sourceId, fontName);
|
|
490
489
|
fontName = fontName.substring(0, fontName.length - "-bold".length);
|
|
491
490
|
}
|
|
492
491
|
else if (fontName.endsWith("-italic")) {
|
|
493
|
-
if (style === FontStyle.Italic)return
|
|
492
|
+
if (style === FontStyle.Italic)return resolveUrl(this.sourceId, fontName);
|
|
494
493
|
fontName = fontName.substring(0, fontName.length - "-italic".length);
|
|
495
494
|
}
|
|
496
495
|
else if (fontName.endsWith("-bolditalic")) {
|
|
497
|
-
if (style === FontStyle.BoldAndItalic)return
|
|
496
|
+
if (style === FontStyle.BoldAndItalic)return resolveUrl(this.sourceId, fontName);
|
|
498
497
|
fontName = fontName.substring(0, fontName.length - "-bolditalic".length);
|
|
499
498
|
}
|
|
500
499
|
else
|
|
501
500
|
// If a font does not have a specific style suffic we dont support getting the correct font style
|
|
502
|
-
return
|
|
501
|
+
return resolveUrl(this.sourceId, fontName);
|
|
503
502
|
|
|
504
503
|
switch (style) {
|
|
505
504
|
case FontStyle.Normal:
|
|
@@ -516,7 +515,7 @@ export class Text extends Graphic {
|
|
|
516
515
|
break;
|
|
517
516
|
}
|
|
518
517
|
|
|
519
|
-
return
|
|
518
|
+
return resolveUrl(this.sourceId, fontName);
|
|
520
519
|
}
|
|
521
520
|
}
|
|
522
521
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
class ARButton {
|
|
2
2
|
|
|
3
|
-
static createButton( renderer, options = {} ) {
|
|
3
|
+
static createButton( renderer, options = {}, beforeRequestSession ) {
|
|
4
4
|
|
|
5
5
|
const button = document.createElement( 'button' );
|
|
6
6
|
let ARButtonControlsDomOverlay = false;
|
|
@@ -126,7 +126,7 @@ class ARButton {
|
|
|
126
126
|
button.onclick = function () {
|
|
127
127
|
|
|
128
128
|
if ( currentSession === null ) {
|
|
129
|
-
|
|
129
|
+
beforeRequestSession?.call(this, options);
|
|
130
130
|
navigator.xr.requestSession( 'immersive-ar', options ).then( onSessionStarted );
|
|
131
131
|
|
|
132
132
|
} else {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
package/license-2447137e.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|