@needle-tools/engine 3.1.0-alpha.2 → 3.2.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 +14 -0
- package/dist/needle-engine.js +9024 -8814
- package/dist/needle-engine.min.js +264 -264
- package/dist/needle-engine.umd.cjs +266 -266
- package/lib/engine/codegen/register_types.js +2 -0
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/debug/debug_overlay.js +2 -0
- package/lib/engine/debug/debug_overlay.js.map +1 -1
- package/lib/engine/engine_context_registry.d.ts +2 -0
- package/lib/engine/engine_context_registry.js +3 -0
- package/lib/engine/engine_context_registry.js.map +1 -1
- package/lib/engine/engine_gltf_builtin_components.js +2 -0
- package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
- package/lib/engine/engine_license.js +1 -1
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_lightdata.js +1 -1
- package/lib/engine/engine_lightdata.js.map +1 -1
- package/lib/engine/engine_networking_auto.d.ts +3 -3
- package/lib/engine/engine_networking_auto.js +7 -3
- package/lib/engine/engine_networking_auto.js.map +1 -1
- package/lib/engine/engine_rendererdata.d.ts +1 -0
- package/lib/engine/engine_rendererdata.js +39 -15
- package/lib/engine/engine_rendererdata.js.map +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.js +10 -1
- package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_lighting_settings.js +14 -11
- package/lib/engine/extensions/NEEDLE_lighting_settings.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_lightmaps.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_progressive.js +11 -4
- package/lib/engine/extensions/NEEDLE_progressive.js.map +1 -1
- package/lib/engine/extensions/extensions.js +4 -0
- package/lib/engine/extensions/extensions.js.map +1 -1
- package/lib/engine-components/AudioSource.d.ts +1 -0
- package/lib/engine-components/AudioSource.js +6 -3
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/Camera.js +1 -1
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/Renderer.d.ts +5 -0
- package/lib/engine-components/Renderer.js +64 -17
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/RendererLightmap.d.ts +1 -2
- package/lib/engine-components/RendererLightmap.js +8 -10
- package/lib/engine-components/RendererLightmap.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.d.ts +32 -0
- package/lib/engine-components/SceneSwitcher.js +228 -0
- package/lib/engine-components/SceneSwitcher.js.map +1 -0
- package/lib/engine-components/ScreenCapture.js +1 -0
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +2 -0
- package/lib/engine-components/VideoPlayer.js +7 -3
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/XRFlag.js +3 -0
- package/lib/engine-components/XRFlag.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +1 -0
- package/lib/engine-components/codegen/components.js +1 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/timeline/PlayableDirector.js +0 -2
- package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
- package/lib/engine-components/timeline/TimelineTracks.js +9 -3
- package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/engine/codegen/register_types.js +2 -0
- package/src/engine/debug/debug_overlay.ts +1 -0
- package/src/engine/engine_context_registry.ts +3 -0
- package/src/engine/engine_gltf_builtin_components.ts +3 -0
- package/src/engine/engine_license.ts +1 -1
- package/src/engine/engine_lightdata.ts +1 -1
- package/src/engine/engine_networking_auto.ts +13 -6
- package/src/engine/engine_rendererdata.ts +35 -16
- package/src/engine/engine_serialization_builtin_serializer.ts +10 -1
- package/src/engine/extensions/NEEDLE_lighting_settings.ts +15 -13
- package/src/engine/extensions/NEEDLE_lightmaps.ts +3 -2
- package/src/engine/extensions/NEEDLE_progressive.ts +9 -3
- package/src/engine/extensions/extensions.ts +6 -0
- package/src/engine-components/AudioSource.ts +6 -3
- package/src/engine-components/Camera.ts +1 -1
- package/src/engine-components/Component.ts +0 -1
- package/src/engine-components/Renderer.ts +69 -20
- package/src/engine-components/RendererLightmap.ts +7 -11
- package/src/engine-components/SceneSwitcher.ts +224 -0
- package/src/engine-components/ScreenCapture.ts +1 -0
- package/src/engine-components/VideoPlayer.ts +16 -11
- package/src/engine-components/XRFlag.ts +3 -0
- package/src/engine-components/codegen/components.ts +1 -0
- package/src/engine-components/timeline/PlayableDirector.ts +0 -1
- package/src/engine-components/timeline/TimelineTracks.ts +9 -3
|
@@ -14,7 +14,7 @@ export class RendererLightmap {
|
|
|
14
14
|
set lightmap(tex: Texture | null) {
|
|
15
15
|
if (tex !== this.lightmapTexture) {
|
|
16
16
|
this.lightmapTexture = tex;
|
|
17
|
-
this.
|
|
17
|
+
this.applyLightmap();
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -27,8 +27,6 @@ export class RendererLightmap {
|
|
|
27
27
|
private lightmapScaleOffsetUniform = { value: new THREE.Vector4(1, 1, 0, 0) };
|
|
28
28
|
private lightmapUniform: { value: THREE.Texture | null } = { value: null };
|
|
29
29
|
|
|
30
|
-
private beforeRenderCallback?: OnBeforeRenderCallback;
|
|
31
|
-
|
|
32
30
|
constructor(gameObject: GameObject, context: Context) {
|
|
33
31
|
this.gameObject = gameObject;
|
|
34
32
|
this.context = context;
|
|
@@ -44,20 +42,19 @@ export class RendererLightmap {
|
|
|
44
42
|
|
|
45
43
|
const debugLightmaps = debug;
|
|
46
44
|
if (debugLightmaps) this.setLightmapDebugMaterial();
|
|
47
|
-
this.
|
|
45
|
+
this.applyLightmap();
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
bindOnBeforeRender() {
|
|
51
|
-
this.
|
|
52
|
-
this.context.addBeforeRenderListener(this.gameObject, this.
|
|
53
|
-
// this.gameObject.onBeforeRender = this.onBeforeRenderThreeComplete.bind(this);
|
|
49
|
+
this.context.removeBeforeRenderListener(this.gameObject, this.onBeforeRenderThreeComplete);
|
|
50
|
+
this.context.addBeforeRenderListener(this.gameObject, this.onBeforeRenderThreeComplete);
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
private onBeforeRenderThreeComplete(_renderer, _scene, _camera, _geometry, material, _group) {
|
|
53
|
+
private onBeforeRenderThreeComplete = (_renderer, _scene, _camera, _geometry, material, _group) => {
|
|
57
54
|
this.onBeforeRenderThree(material);
|
|
58
55
|
}
|
|
59
56
|
|
|
60
|
-
private
|
|
57
|
+
private applyLightmap() {
|
|
61
58
|
|
|
62
59
|
if (this.gameObject.type === "Object3D") {
|
|
63
60
|
// console.warn("Can not add lightmap. Is this object missing a renderer?");
|
|
@@ -65,13 +62,12 @@ export class RendererLightmap {
|
|
|
65
62
|
}
|
|
66
63
|
|
|
67
64
|
if (this.gameObject.type === "Group") {
|
|
68
|
-
console.warn("Lightmap on multimaterial object is not supported yet... please
|
|
65
|
+
console.warn("Lightmap on multimaterial object is not supported yet... please open a feature request on https://github.com/needle-tools/needle-engine-support if your project requires it");
|
|
69
66
|
return;
|
|
70
67
|
}
|
|
71
68
|
|
|
72
69
|
console.assert(this.gameObject.type === "Mesh", "Lightmap only works on meshes", this);
|
|
73
70
|
|
|
74
|
-
|
|
75
71
|
const mesh = this.gameObject as unknown as THREE.Mesh;
|
|
76
72
|
// TODO: ensure uv2 exists
|
|
77
73
|
if (!mesh.geometry.getAttribute("uv2"))
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { AssetReference } from "../engine/engine_addressables";
|
|
2
|
+
import { NeedleEngineHTMLElement } from "../engine/engine_element";
|
|
3
|
+
import { InputEvents } from "../engine/engine_input";
|
|
4
|
+
import { isLocalNetwork } from "../engine/engine_networking_utils";
|
|
5
|
+
import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry";
|
|
6
|
+
import { getParam, isMobileDevice, setParamWithoutReload } from "../engine/engine_utils";
|
|
7
|
+
import { serializable } from "../engine/engine_serialization";
|
|
8
|
+
import { Behaviour, GameObject } from "./Component";
|
|
9
|
+
|
|
10
|
+
const ENGINE_ELEMENT_SCENE_ATTRIBUTE_NAME = "scene";
|
|
11
|
+
|
|
12
|
+
ContextRegistry.registerCallback(ContextEvent.ContextRegistered, _ => {
|
|
13
|
+
if (!NeedleEngineHTMLElement.observedAttributes.includes(ENGINE_ELEMENT_SCENE_ATTRIBUTE_NAME))
|
|
14
|
+
NeedleEngineHTMLElement.observedAttributes.push(ENGINE_ELEMENT_SCENE_ATTRIBUTE_NAME);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const couldNotLoadScenePromise = Promise.resolve(false);
|
|
18
|
+
|
|
19
|
+
export class SceneSwitcher extends Behaviour {
|
|
20
|
+
|
|
21
|
+
@serializable(AssetReference)
|
|
22
|
+
scenes!: AssetReference[];
|
|
23
|
+
|
|
24
|
+
/** the url parameter that is set/used to store the currently loaded scene in, set to "" to disable */
|
|
25
|
+
@serializable()
|
|
26
|
+
queryParameterName: string = "scene";
|
|
27
|
+
|
|
28
|
+
/** when enabled the new scene is pushed to the browser navigation history, only works with a valid query parameter set */
|
|
29
|
+
@serializable()
|
|
30
|
+
useHistory: boolean = true;
|
|
31
|
+
|
|
32
|
+
/** when enabled you can switch between scenes using keyboard left, right, A and D or number keys */
|
|
33
|
+
@serializable()
|
|
34
|
+
useKeyboard: boolean = true;
|
|
35
|
+
|
|
36
|
+
/** when enabled you can switch between scenes using swipe (mobile only) */
|
|
37
|
+
@serializable()
|
|
38
|
+
useSwipe: boolean = true;
|
|
39
|
+
|
|
40
|
+
private _currentIndex: number = -1;
|
|
41
|
+
private _currentScene: AssetReference | undefined = undefined;
|
|
42
|
+
private _engineElementOverserver: MutationObserver | undefined = undefined;
|
|
43
|
+
|
|
44
|
+
start() {
|
|
45
|
+
if (!this.tryLoadFromQueryParam()) {
|
|
46
|
+
const value = this.context.domElement.getAttribute(ENGINE_ELEMENT_SCENE_ATTRIBUTE_NAME);
|
|
47
|
+
// let locked = this.lock;
|
|
48
|
+
try {
|
|
49
|
+
// this.lock = false;
|
|
50
|
+
if (value === null || !this.trySelectSceneFromValue(value))
|
|
51
|
+
this.select(0);
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
// this.lock = locked;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
onEnable(): void {
|
|
60
|
+
globalThis.addEventListener("popstate", this.onPopState);
|
|
61
|
+
this.context.input.addEventListener(InputEvents.KeyDown, this.onKeyDown);
|
|
62
|
+
this.context.input.addEventListener(InputEvents.PointerMove, this.onPointerMove);
|
|
63
|
+
this.context.input.addEventListener(InputEvents.PointerUp, this.onPointerUp);
|
|
64
|
+
|
|
65
|
+
if (!this._engineElementOverserver) {
|
|
66
|
+
this._engineElementOverserver = new MutationObserver((mutations) => {
|
|
67
|
+
for (const mut of mutations) {
|
|
68
|
+
if (mut.type === "attributes" && mut.attributeName === ENGINE_ELEMENT_SCENE_ATTRIBUTE_NAME) {
|
|
69
|
+
const value = this.context.domElement.getAttribute(ENGINE_ELEMENT_SCENE_ATTRIBUTE_NAME);
|
|
70
|
+
if (value !== null) {
|
|
71
|
+
this.trySelectSceneFromValue(value);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this._engineElementOverserver.observe(this.context.domElement, {
|
|
79
|
+
attributes: true
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
onDisable(): void {
|
|
84
|
+
globalThis.removeEventListener("popstate", this.onPopState);
|
|
85
|
+
this.context.input.removeEventListener(InputEvents.KeyDown, this.onKeyDown);
|
|
86
|
+
this.context.input.removeEventListener(InputEvents.PointerMove, this.onPointerMove);
|
|
87
|
+
this.context.input.removeEventListener(InputEvents.PointerUp, this.onPointerUp);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private onPopState = async (_state: PopStateEvent) => {
|
|
91
|
+
if (!this.useHistory) return;
|
|
92
|
+
let wasUsingHistory = this.useHistory;
|
|
93
|
+
try {
|
|
94
|
+
this.useHistory = false;
|
|
95
|
+
await this.tryLoadFromQueryParam();
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
this.useHistory = wasUsingHistory;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private normalizedSwipeThresholdX = 0.1;
|
|
103
|
+
private _didSwipe: boolean = false;
|
|
104
|
+
private onPointerMove = (e: any) => {
|
|
105
|
+
if (!this._didSwipe && e.button === 0 && e.pointerType === "touch" && this.context.input.getPointerPressedCount() === 1) {
|
|
106
|
+
const delta = this.context.input.getPointerPositionDelta(e.button);
|
|
107
|
+
if (delta) {
|
|
108
|
+
const normalizedX = delta.x / this.context.domWidth;
|
|
109
|
+
if (normalizedX >= this.normalizedSwipeThresholdX) {
|
|
110
|
+
this._didSwipe = true;
|
|
111
|
+
this.selectPrev();
|
|
112
|
+
}
|
|
113
|
+
else if (normalizedX <= -this.normalizedSwipeThresholdX) {
|
|
114
|
+
this._didSwipe = true;
|
|
115
|
+
this.selectNext();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private onPointerUp = (e: any) => {
|
|
122
|
+
if (e.button === 0) {
|
|
123
|
+
this._didSwipe = false;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
private onKeyDown = (e: any) => {
|
|
128
|
+
if (!this.useKeyboard) return;
|
|
129
|
+
if (!this.scenes) return;
|
|
130
|
+
const key = e.key.toLowerCase();
|
|
131
|
+
if (!key) return;
|
|
132
|
+
const index = parseInt(key) - 1;
|
|
133
|
+
if (index >= 0) {
|
|
134
|
+
this.trySelectSceneFromValue(index);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
switch (key) {
|
|
138
|
+
case "arrowright":
|
|
139
|
+
case "d":
|
|
140
|
+
this.selectNext();
|
|
141
|
+
break;
|
|
142
|
+
case "arrowleft":
|
|
143
|
+
case "a":
|
|
144
|
+
this.selectPrev();
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
selectNext() {
|
|
150
|
+
return this.select(this._currentIndex + 1);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
selectPrev() {
|
|
154
|
+
return this.select(this._currentIndex - 1);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
select(index: number) {
|
|
158
|
+
if (!this.scenes?.length) return couldNotLoadScenePromise;
|
|
159
|
+
if (index < 0) index = this.scenes.length - 1;
|
|
160
|
+
if (index >= this.scenes.length) index = 0;
|
|
161
|
+
const scene = this.scenes[index];
|
|
162
|
+
return this.switchScene(scene);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async switchScene(scene: AssetReference): Promise<boolean> {
|
|
166
|
+
if (scene === this._currentScene) return true;
|
|
167
|
+
if (this._currentScene)
|
|
168
|
+
GameObject.remove(this._currentScene.asset);
|
|
169
|
+
const index = this._currentIndex = this.scenes?.indexOf(scene) ?? -1;
|
|
170
|
+
this._currentScene = scene;
|
|
171
|
+
try {
|
|
172
|
+
await scene.loadAssetAsync();
|
|
173
|
+
if (!scene.asset) return false;
|
|
174
|
+
if (this._currentIndex === index) {
|
|
175
|
+
GameObject.add(scene.asset, this.gameObject);
|
|
176
|
+
// save the loaded scene as an url parameter
|
|
177
|
+
if (this.queryParameterName?.length)
|
|
178
|
+
setParamWithoutReload(this.queryParameterName, index.toString(), this.useHistory);
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
console.error(err);
|
|
184
|
+
}
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
private tryLoadFromQueryParam() {
|
|
189
|
+
if (!this.queryParameterName?.length) return false;
|
|
190
|
+
// try restore the scene from the url
|
|
191
|
+
const value = getParam(this.queryParameterName);
|
|
192
|
+
if (typeof value === "boolean") return false;
|
|
193
|
+
return this.trySelectSceneFromValue(value);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** try to select a scene from a string or index */
|
|
197
|
+
private trySelectSceneFromValue(value: string | number) {
|
|
198
|
+
|
|
199
|
+
if (typeof value === "string") {
|
|
200
|
+
const index = parseInt(value as string);
|
|
201
|
+
if (index >= 0 && index < this.scenes.length) {
|
|
202
|
+
return this.select(index);;
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
// Try to find a scene with a matching name
|
|
206
|
+
for (let i = 0; i < this.scenes.length; i++) {
|
|
207
|
+
const scene = this.scenes[i];
|
|
208
|
+
if (scene.uri.toLowerCase().includes(value)) {
|
|
209
|
+
return this.select(i);;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
else if (typeof value === "number") {
|
|
215
|
+
if (value >= 0 && value < this.scenes.length) {
|
|
216
|
+
return this.select(value);;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (isLocalNetwork()) console.warn("Unknown scene value or index: \"" + value + "\"", this)
|
|
221
|
+
|
|
222
|
+
return couldNotLoadScenePromise;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -96,6 +96,7 @@ export class ScreenCapture extends Behaviour implements IPointerClickHandler {
|
|
|
96
96
|
console.log("Screensharing", this.name, this);
|
|
97
97
|
AudioSource.registerWaitForAllowAudio(() => {
|
|
98
98
|
if (this.videoPlayer && this._currentStream && this._currentMode === ScreenCaptureMode.Receiving) {
|
|
99
|
+
this.videoPlayer.playInBackground = true;
|
|
99
100
|
this.videoPlayer.setVideo(this._currentStream);
|
|
100
101
|
}
|
|
101
102
|
});
|
|
@@ -52,7 +52,7 @@ export class VideoPlayer extends Behaviour {
|
|
|
52
52
|
|
|
53
53
|
@serializable()
|
|
54
54
|
aspectMode: AspectMode = AspectMode.None;
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
@serializable(URL)
|
|
57
57
|
private clip?: string | MediaStream | null = null;
|
|
58
58
|
|
|
@@ -106,12 +106,12 @@ export class VideoPlayer extends Behaviour {
|
|
|
106
106
|
get isPlaying(): boolean {
|
|
107
107
|
const video = this._videoElement;
|
|
108
108
|
if (video) {
|
|
109
|
-
if(video.currentTime > 0 && !video.paused && !video.ended
|
|
109
|
+
if (video.currentTime > 0 && !video.paused && !video.ended
|
|
110
110
|
&& video.readyState > video.HAVE_CURRENT_DATA)
|
|
111
111
|
return true;
|
|
112
|
-
else if(video.srcObject){
|
|
112
|
+
else if (video.srcObject) {
|
|
113
113
|
const stream = video.srcObject as MediaStream;
|
|
114
|
-
if(stream.active) return true;
|
|
114
|
+
if (stream.active) return true;
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
return false;
|
|
@@ -149,6 +149,9 @@ export class VideoPlayer extends Behaviour {
|
|
|
149
149
|
}
|
|
150
150
|
private _muted: boolean = false;
|
|
151
151
|
|
|
152
|
+
/** Set this to false to pause video playback while the tab is not active */
|
|
153
|
+
playInBackground: boolean = true;
|
|
154
|
+
|
|
152
155
|
private _crossOrigin: string | null = "anonymous";
|
|
153
156
|
|
|
154
157
|
private audioOutputMode: VideoAudioOutputMode = VideoAudioOutputMode.AudioSource;
|
|
@@ -198,11 +201,13 @@ export class VideoPlayer extends Behaviour {
|
|
|
198
201
|
window.addEventListener('visibilitychange', _evt => {
|
|
199
202
|
switch (document.visibilityState) {
|
|
200
203
|
case "hidden":
|
|
201
|
-
this.
|
|
202
|
-
|
|
204
|
+
if(!this.playInBackground){
|
|
205
|
+
this.wasPlaying = this._isPlaying;
|
|
206
|
+
this.pause();
|
|
207
|
+
}
|
|
203
208
|
break;
|
|
204
209
|
case "visible":
|
|
205
|
-
if (this.wasPlaying) this.play();
|
|
210
|
+
if (this.wasPlaying && !this._isPlaying) this.play();
|
|
206
211
|
break;
|
|
207
212
|
}
|
|
208
213
|
});
|
|
@@ -260,7 +265,7 @@ export class VideoPlayer extends Behaviour {
|
|
|
260
265
|
this.updateVideoElementSettings();
|
|
261
266
|
this._videoElement?.play().catch(err => {
|
|
262
267
|
// https://developer.chrome.com/blog/play-request-was-interrupted/
|
|
263
|
-
if(debug)
|
|
268
|
+
if (debug)
|
|
264
269
|
console.error("Error playing video", err, "CODE=" + err.code, this.videoElement?.src, this);
|
|
265
270
|
setTimeout(() => {
|
|
266
271
|
if (this._isPlaying && !this.destroyed && this.activeAndEnabled)
|
|
@@ -318,7 +323,7 @@ export class VideoPlayer extends Behaviour {
|
|
|
318
323
|
this._videoTexture.flipY = false;
|
|
319
324
|
this._videoTexture.encoding = THREE.sRGBEncoding;
|
|
320
325
|
this.handleBeginPlaying(playAutomatically);
|
|
321
|
-
if(debug)
|
|
326
|
+
if (debug)
|
|
322
327
|
console.log(this);
|
|
323
328
|
}
|
|
324
329
|
|
|
@@ -420,7 +425,7 @@ export class VideoPlayer extends Behaviour {
|
|
|
420
425
|
// dont open in fullscreen on ios
|
|
421
426
|
this._videoElement.playsInline = true;
|
|
422
427
|
let muted = !this._receivedInput && this.audioOutputMode !== VideoAudioOutputMode.None;
|
|
423
|
-
if(!muted && this._muted) muted = true;
|
|
428
|
+
if (!muted && this._muted) muted = true;
|
|
424
429
|
this._videoElement.muted = muted;
|
|
425
430
|
if (this.playOnAwake)
|
|
426
431
|
this._videoElement.autoplay = true;
|
|
@@ -540,7 +545,7 @@ class VideoOverlay {
|
|
|
540
545
|
if (!this._screenspaceModeQuad) return;
|
|
541
546
|
this._screenspaceModeQuad.geometry.scale(2, 2, 2);
|
|
542
547
|
}
|
|
543
|
-
|
|
548
|
+
|
|
544
549
|
const quad = this._screenspaceModeQuad;
|
|
545
550
|
this.context.scene.add(quad);
|
|
546
551
|
this.updateScreenspaceMaterialUniforms();
|
|
@@ -114,6 +114,7 @@ export { RGBAColor } from "../js-extensions/RGBAColor";
|
|
|
114
114
|
export { Rigidbody } from "../RigidBody";
|
|
115
115
|
export { RotationBySpeedModule } from "../ParticleSystemModules";
|
|
116
116
|
export { RotationOverLifetimeModule } from "../ParticleSystemModules";
|
|
117
|
+
export { SceneSwitcher } from "../SceneSwitcher";
|
|
117
118
|
export { ScreenCapture } from "../ScreenCapture";
|
|
118
119
|
export { ScreenSpaceAmbientOcclusion } from "../postprocessing/Effects/ScreenspaceAmbientOcclusion";
|
|
119
120
|
export { ShadowCatcher } from "../ShadowCatcher";
|
|
@@ -452,7 +452,6 @@ export class PlayableDirector extends Behaviour {
|
|
|
452
452
|
const anim = GameObject.getOrAddComponent(binding, Animator);
|
|
453
453
|
if(anim) binding = anim;
|
|
454
454
|
}
|
|
455
|
-
if (typeof binding.enabled === "boolean") binding.enabled = false;
|
|
456
455
|
const animationClips = binding?.gameObject?.animations;
|
|
457
456
|
if (animationClips) {
|
|
458
457
|
const handler = new Tracks.AnimationTrackHandler();
|
|
@@ -145,7 +145,7 @@ export class AnimationTrackHandler extends TrackHandler {
|
|
|
145
145
|
onPauseChanged() {
|
|
146
146
|
// When the timeline is paused the original animator will be enabled again if it was before
|
|
147
147
|
if (this._animator && this._animatorWasEnabled !== undefined) {
|
|
148
|
-
this._animator.enabled = this.director.
|
|
148
|
+
this._animator.enabled = this.director.isPlaying === false ? this._animatorWasEnabled : false;
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
|
|
@@ -225,7 +225,12 @@ export class AnimationTrackHandler extends TrackHandler {
|
|
|
225
225
|
// We need to disable the animator component in case it also animates
|
|
226
226
|
// which overrides the timeline
|
|
227
227
|
this._animator = GameObject.getComponent(this.target, Animator) ?? null;
|
|
228
|
-
|
|
228
|
+
if (this._animator)
|
|
229
|
+
{
|
|
230
|
+
this._animatorWasEnabled = this._animator.enabled;
|
|
231
|
+
this._animator.enabled = false;
|
|
232
|
+
}
|
|
233
|
+
else this._animatorWasEnabled = false;
|
|
229
234
|
}
|
|
230
235
|
|
|
231
236
|
// Clip Offsets
|
|
@@ -323,6 +328,7 @@ export class AnimationTrackHandler extends TrackHandler {
|
|
|
323
328
|
// const clip = this.clips[i];
|
|
324
329
|
let weight = 1;
|
|
325
330
|
weight *= this.evaluateWeight(time, i, this.models, isActive);
|
|
331
|
+
weight *= this.director.weight;
|
|
326
332
|
|
|
327
333
|
let handleLoop = isInTimeRange;
|
|
328
334
|
if(doPreExtrapolate){
|
|
@@ -370,7 +376,7 @@ export class AnimationTrackHandler extends TrackHandler {
|
|
|
370
376
|
else action.time = t;
|
|
371
377
|
|
|
372
378
|
action.timeScale = 0;
|
|
373
|
-
const effectiveWeight = weight
|
|
379
|
+
const effectiveWeight = weight;
|
|
374
380
|
action.weight = effectiveWeight;
|
|
375
381
|
action.clampWhenFinished = true;
|
|
376
382
|
if (!action.isRunning())
|