@needle-tools/engine 2.32.0-pre → 2.34.0-pre
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 +15 -0
- package/dist/needle-engine.d.ts +195 -164
- package/dist/needle-engine.js +394 -344
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +70 -20
- package/dist/needle-engine.min.js.map +4 -4
- package/lib/engine/engine_create_objects.d.ts +11 -0
- package/lib/engine/engine_create_objects.js +20 -0
- package/lib/engine/engine_create_objects.js.map +1 -0
- package/lib/engine/engine_instancing.d.ts +5 -0
- package/lib/engine/engine_instancing.js +22 -0
- package/lib/engine/engine_instancing.js.map +1 -0
- package/lib/engine/engine_physics.d.ts +2 -0
- package/lib/engine/engine_physics.js +7 -1
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_components.js +2 -0
- package/lib/engine/extensions/NEEDLE_components.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_techniques_webgl.d.ts +1 -0
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +26 -0
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
- package/lib/engine-components/Animation.js +1 -1
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/Collider.d.ts +1 -0
- package/lib/engine-components/Collider.js +6 -2
- package/lib/engine-components/Collider.js.map +1 -1
- package/lib/engine-components/Component.js +4 -51
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/DragControls.js +1 -1
- package/lib/engine-components/DragControls.js.map +1 -1
- package/lib/engine-components/Renderer.d.ts +0 -3
- package/lib/engine-components/Renderer.js +1 -20
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/ScreenCapture.d.ts +8 -14
- package/lib/engine-components/ScreenCapture.js +62 -74
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/SyncedCamera.js +1 -1
- package/lib/engine-components/SyncedCamera.js.map +1 -1
- package/lib/engine-components/SyncedTransform.js +1 -1
- package/lib/engine-components/SyncedTransform.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +14 -3
- package/lib/engine-components/VideoPlayer.js +390 -47
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/WebARSessionRoot.js +1 -1
- package/lib/engine-components/WebARSessionRoot.js.map +1 -1
- package/lib/engine-components/WebXRAvatar.js +1 -1
- package/lib/engine-components/WebXRAvatar.js.map +1 -1
- package/lib/engine-components/WebXRController.d.ts +1 -0
- package/lib/engine-components/WebXRController.js +12 -1
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/codegen/{exports.d.ts → components.d.ts} +2 -2
- package/{src/engine-components/codegen/exports.ts → lib/engine-components/codegen/components.js} +3 -2
- package/lib/engine-components/codegen/components.js.map +1 -0
- package/lib/engine-components/js-extensions/Object3D.d.ts +2 -0
- package/lib/engine-components/js-extensions/Object3D.js +75 -0
- package/lib/engine-components/js-extensions/Object3D.js.map +1 -0
- package/lib/engine-components/ui/EventSystem.d.ts +3 -0
- package/lib/engine-components/ui/EventSystem.js +17 -8
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/lib/needle-engine.d.ts +2 -1
- package/lib/needle-engine.js +3 -2
- package/lib/needle-engine.js.map +1 -1
- package/package.json +2 -2
- package/src/engine/codegen/register_types.js +2 -4
- package/src/engine/engine_create_objects.ts +27 -0
- package/src/engine/engine_instancing.ts +25 -0
- package/src/engine/engine_physics.ts +9 -1
- package/src/engine/extensions/NEEDLE_components.ts +3 -0
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +34 -2
- package/src/engine-components/Animation.ts +1 -1
- package/src/engine-components/Collider.ts +7 -2
- package/src/engine-components/Component.ts +4 -64
- package/src/engine-components/DragControls.ts +1 -1
- package/src/engine-components/Renderer.ts +2 -20
- package/src/engine-components/ScreenCapture.ts +62 -75
- package/src/engine-components/SyncedCamera.ts +1 -1
- package/src/engine-components/SyncedTransform.ts +1 -1
- package/src/engine-components/VideoPlayer.ts +401 -48
- package/src/engine-components/WebARSessionRoot.ts +1 -1
- package/src/engine-components/WebXRAvatar.ts +1 -1
- package/src/engine-components/WebXRController.ts +11 -1
- package/{lib/engine-components/codegen/exports.js → src/engine-components/codegen/components.ts} +1 -3
- package/src/engine-components/js-extensions/Object3D.ts +91 -0
- package/src/engine-components/ui/EventSystem.ts +19 -10
- package/src/needle-engine.ts +3 -3
- package/lib/engine-components/ComponentExtensions.d.ts +0 -2
- package/lib/engine-components/ComponentExtensions.js +0 -3
- package/lib/engine-components/ComponentExtensions.js.map +0 -1
- package/lib/engine-components/codegen/exports.js.map +0 -1
- package/src/engine-components/ComponentExtensions.ts +0 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/engine",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.34.0-pre",
|
|
4
4
|
"description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development, and can be deployed anywhere. It is flexible, extensible, and collaboration and XR come naturally.",
|
|
5
5
|
"main": "dist/needle-engine.js",
|
|
6
6
|
"module": "lib/needle-engine.js",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"md5": "^2.3.0",
|
|
49
49
|
"peerjs": "1.3.2",
|
|
50
50
|
"stats.js": "^0.17.0",
|
|
51
|
-
"three": "
|
|
51
|
+
"three": "npm:@needle-tools/three@^0.145.0",
|
|
52
52
|
"three-mesh-ui": "^6.4.5",
|
|
53
53
|
"three.meshline": "^1.4.0",
|
|
54
54
|
"uuid": "^9.0.0",
|
|
@@ -18,7 +18,6 @@ import { Collider } from "../../engine-components/Collider.ts";
|
|
|
18
18
|
import { SphereCollider } from "../../engine-components/Collider.ts";
|
|
19
19
|
import { BoxCollider } from "../../engine-components/Collider.ts";
|
|
20
20
|
import { InstantiateOptions } from "../../engine-components/Component.ts";
|
|
21
|
-
import { UnityObject } from "../../engine-components/ComponentExtensions.ts";
|
|
22
21
|
import { DeleteBox } from "../../engine-components/DeleteBox.ts";
|
|
23
22
|
import { Deletable } from "../../engine-components/DeleteBox.ts";
|
|
24
23
|
import { DeviceFlag } from "../../engine-components/DeviceFlag.ts";
|
|
@@ -57,7 +56,6 @@ import { FieldWithDefault } from "../../engine-components/Renderer.ts";
|
|
|
57
56
|
import { Renderer } from "../../engine-components/Renderer.ts";
|
|
58
57
|
import { MeshRenderer } from "../../engine-components/Renderer.ts";
|
|
59
58
|
import { SkinnedMeshRenderer } from "../../engine-components/Renderer.ts";
|
|
60
|
-
import { InstancingUtil } from "../../engine-components/Renderer.ts";
|
|
61
59
|
import { RendererLightmap } from "../../engine-components/RendererLightmap.ts";
|
|
62
60
|
import { Rigidbody } from "../../engine-components/RigidBody.ts";
|
|
63
61
|
import { ScreenCapture } from "../../engine-components/ScreenCapture.ts";
|
|
@@ -105,6 +103,7 @@ import { Avatar_POI } from "../../engine-components/avatar/Avatar_Brain_LookAt.t
|
|
|
105
103
|
import { Avatar_Brain_LookAt } from "../../engine-components/avatar/Avatar_Brain_LookAt.ts";
|
|
106
104
|
import { Avatar_MouthShapes } from "../../engine-components/avatar/Avatar_MouthShapes.ts";
|
|
107
105
|
import { Avatar_MustacheShake } from "../../engine-components/avatar/Avatar_MustacheShake.ts";
|
|
106
|
+
import { __Ignore } from "../../engine-components/codegen/components.ts";
|
|
108
107
|
import { LogStats } from "../../engine-components/debug/LogStats.ts";
|
|
109
108
|
import { RGBAColor } from "../../engine-components/js-extensions/RGBAColor.ts";
|
|
110
109
|
import { PlayableDirector } from "../../engine-components/timeline/PlayableDirector.ts";
|
|
@@ -165,7 +164,6 @@ TypeStore.add("Collider", Collider);
|
|
|
165
164
|
TypeStore.add("SphereCollider", SphereCollider);
|
|
166
165
|
TypeStore.add("BoxCollider", BoxCollider);
|
|
167
166
|
TypeStore.add("InstantiateOptions", InstantiateOptions);
|
|
168
|
-
TypeStore.add("UnityObject", UnityObject);
|
|
169
167
|
TypeStore.add("DeleteBox", DeleteBox);
|
|
170
168
|
TypeStore.add("Deletable", Deletable);
|
|
171
169
|
TypeStore.add("DeviceFlag", DeviceFlag);
|
|
@@ -204,7 +202,6 @@ TypeStore.add("FieldWithDefault", FieldWithDefault);
|
|
|
204
202
|
TypeStore.add("Renderer", Renderer);
|
|
205
203
|
TypeStore.add("MeshRenderer", MeshRenderer);
|
|
206
204
|
TypeStore.add("SkinnedMeshRenderer", SkinnedMeshRenderer);
|
|
207
|
-
TypeStore.add("InstancingUtil", InstancingUtil);
|
|
208
205
|
TypeStore.add("RendererLightmap", RendererLightmap);
|
|
209
206
|
TypeStore.add("Rigidbody", Rigidbody);
|
|
210
207
|
TypeStore.add("ScreenCapture", ScreenCapture);
|
|
@@ -252,6 +249,7 @@ TypeStore.add("Avatar_POI", Avatar_POI);
|
|
|
252
249
|
TypeStore.add("Avatar_Brain_LookAt", Avatar_Brain_LookAt);
|
|
253
250
|
TypeStore.add("Avatar_MouthShapes", Avatar_MouthShapes);
|
|
254
251
|
TypeStore.add("Avatar_MustacheShake", Avatar_MustacheShake);
|
|
252
|
+
TypeStore.add("__Ignore", __Ignore);
|
|
255
253
|
TypeStore.add("LogStats", LogStats);
|
|
256
254
|
TypeStore.add("RGBAColor", RGBAColor);
|
|
257
255
|
TypeStore.add("PlayableDirector", PlayableDirector);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PlaneGeometry, MeshBasicMaterial, DoubleSide, Mesh, Material } from "three"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export enum PrimitiveType {
|
|
5
|
+
Quad = 0
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type ObjectOptions = {
|
|
9
|
+
name?: string,
|
|
10
|
+
material?: Material,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class ObjectUtils {
|
|
14
|
+
|
|
15
|
+
static createPrimitive(type: PrimitiveType, opts?: ObjectOptions): Mesh {
|
|
16
|
+
let obj: Mesh;
|
|
17
|
+
switch (type) {
|
|
18
|
+
case PrimitiveType.Quad:
|
|
19
|
+
const geometry = new PlaneGeometry(1, 1, 1, 1);
|
|
20
|
+
const material = opts?.material ?? new MeshBasicMaterial({ color: 0xffffff });
|
|
21
|
+
obj = new Mesh(geometry, material);
|
|
22
|
+
}
|
|
23
|
+
if (opts?.name)
|
|
24
|
+
obj.name = opts.name;
|
|
25
|
+
return obj;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const NEED_UPDATE_INSTANCE_KEY = Symbol("NEEDLE_NEED_UPDATE_INSTANCE");
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export class InstancingUtil {
|
|
6
|
+
|
|
7
|
+
static isUsingInstancing(instance: THREE.Object3D): boolean { return instance["__isUsingInstancing"] === true; }
|
|
8
|
+
|
|
9
|
+
// TODO: change this so it does not set matrix world directly but some flag that is only used by instancing
|
|
10
|
+
static markDirty(go: THREE.Object3D | null, recursive: boolean = true) {
|
|
11
|
+
if (!go) return;
|
|
12
|
+
// potential optimization:
|
|
13
|
+
// if(go.matrixWorldNeedsUpdate) return;
|
|
14
|
+
// console.trace(go, GameObject.isUsingInstancing(go));
|
|
15
|
+
if (this.isUsingInstancing(go)) {
|
|
16
|
+
go[NEED_UPDATE_INSTANCE_KEY] = true;
|
|
17
|
+
go.matrixWorldNeedsUpdate = true;
|
|
18
|
+
}
|
|
19
|
+
if (recursive) {
|
|
20
|
+
for (const child of go.children) {
|
|
21
|
+
InstancingUtil.markDirty(child, true);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -5,11 +5,11 @@ import cannonDebugger from 'cannon-es-debugger'
|
|
|
5
5
|
import { Rigidbody } from '../engine-components/Rigidbody';
|
|
6
6
|
import * as utils from "./engine_utils"
|
|
7
7
|
import * as threeutils from "./engine_three_utils"
|
|
8
|
-
import { InstancingUtil } from '../engine-components/Renderer';
|
|
9
8
|
import { Behaviour, Component, GameObject } from '../engine-components/Component';
|
|
10
9
|
import { Body, RigidVehicle, Shape, Vec3 } from 'cannon-es';
|
|
11
10
|
import { Matrix4, Object3D, RGBA_BPTC_Format, Vector3, Wrapping } from 'three';
|
|
12
11
|
import { Collider } from '../engine-components/Collider';
|
|
12
|
+
import { InstancingUtil } from './engine_instancing';
|
|
13
13
|
|
|
14
14
|
const debugPhysics = utils.getParam("debugphysics");
|
|
15
15
|
const debugCollisions = utils.getParam("debugcollisions");
|
|
@@ -686,6 +686,14 @@ export class Physics {
|
|
|
686
686
|
|
|
687
687
|
export class Collision {
|
|
688
688
|
|
|
689
|
+
get __internalCollision(): CannonCollision {
|
|
690
|
+
return this.collision;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
get __internalInvertedSourceReceiver(): boolean {
|
|
694
|
+
return this.invert;
|
|
695
|
+
}
|
|
696
|
+
|
|
689
697
|
private readonly invert: boolean;
|
|
690
698
|
private readonly collision: CannonCollision;
|
|
691
699
|
private readonly targetBody: CANNON.Body;
|
|
@@ -5,6 +5,7 @@ import { writeBuiltinComponentData } from "../engine_gltf_builtin_components";
|
|
|
5
5
|
import { debugExtension } from "../engine_default_parameters";
|
|
6
6
|
import { builtinComponentKeyName } from "../engine_constants";
|
|
7
7
|
import { resolveReferences } from "./extension_utils";
|
|
8
|
+
import { apply } from "../../engine-components/js-extensions/Object3D";
|
|
8
9
|
|
|
9
10
|
export const debug = debugExtension
|
|
10
11
|
const componentsArrayExportKey = "$___Export_Components";
|
|
@@ -185,6 +186,8 @@ export class NEEDLE_components implements GLTFLoaderPlugin {
|
|
|
185
186
|
continue;
|
|
186
187
|
}
|
|
187
188
|
|
|
189
|
+
apply(obj);
|
|
190
|
+
|
|
188
191
|
loadComponents.push(this.createComponents(obj, data));
|
|
189
192
|
}
|
|
190
193
|
}
|
|
@@ -62,6 +62,12 @@ export class CustomShader extends RawShaderMaterial {
|
|
|
62
62
|
private identifier: SourceIdentifier;
|
|
63
63
|
private onBeforeRenderSceneCallback = this.onBeforeRenderScene.bind(this);
|
|
64
64
|
|
|
65
|
+
clone() {
|
|
66
|
+
const clone = super.clone();
|
|
67
|
+
createUniformProperties(clone);
|
|
68
|
+
return clone;
|
|
69
|
+
}
|
|
70
|
+
|
|
65
71
|
constructor(identifier: SourceIdentifier, ...args) {
|
|
66
72
|
super(...args);
|
|
67
73
|
|
|
@@ -179,12 +185,12 @@ export class CustomShader extends RawShaderMaterial {
|
|
|
179
185
|
CustomShader.viewProjection.copy(camera.projectionMatrix).multiply(camera.matrixWorldInverse);
|
|
180
186
|
ToUnityMatrixArray(CustomShader.viewProjection, CustomShader._viewProjectionValues)
|
|
181
187
|
}
|
|
182
|
-
|
|
188
|
+
|
|
183
189
|
if (CustomShader.viewMatrix && this.uniforms[this._viewMatrixName]) {
|
|
184
190
|
CustomShader.viewMatrix.copy(camera.matrixWorldInverse);
|
|
185
191
|
ToUnityMatrixArray(CustomShader.viewMatrix, CustomShader._viewMatrixValues)
|
|
186
192
|
}
|
|
187
|
-
|
|
193
|
+
|
|
188
194
|
if (this.uniforms[CustomShader._worldSpaceCameraPosName]) {
|
|
189
195
|
CustomShader._worldSpaceCameraPos.setFromMatrixPosition(camera.matrixWorld);
|
|
190
196
|
}
|
|
@@ -475,8 +481,34 @@ export class NEEDLE_techniques_webgl implements GLTFLoaderPlugin {
|
|
|
475
481
|
}
|
|
476
482
|
if (debug)
|
|
477
483
|
console.log(material.uuid, uniforms);
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
createUniformProperties(material);
|
|
487
|
+
|
|
478
488
|
resolve(material);
|
|
479
489
|
});
|
|
480
490
|
}
|
|
481
491
|
|
|
482
492
|
}
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
// when animating custom material properties (uniforms) the path resolver tries to access them via material._MyProperty.
|
|
496
|
+
// That doesnt exist by default for custom properties
|
|
497
|
+
// We could re-write the path in the khr path resolver but that would require it to know beforehand
|
|
498
|
+
// if the material uses as custom shader or not
|
|
499
|
+
// this way all properties of custom shaders are also accessible via material._MyProperty
|
|
500
|
+
function createUniformProperties(material: CustomShader) {
|
|
501
|
+
if (material.uniforms) {
|
|
502
|
+
for (const key in material.uniforms) {
|
|
503
|
+
if (!Object.getOwnPropertyDescriptor(material, key)) {
|
|
504
|
+
Object.defineProperty(material, key, {
|
|
505
|
+
get: () => material.uniforms[key].value,
|
|
506
|
+
set: (value) => {
|
|
507
|
+
material.uniforms[key].value = value
|
|
508
|
+
material.needsUpdate = true;
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
@@ -2,8 +2,8 @@ import { Behaviour } from "./Component";
|
|
|
2
2
|
import * as THREE from 'three'
|
|
3
3
|
import { AnimationAction, AnimationClip } from "three";
|
|
4
4
|
import { MixerEvent } from "./Animator";
|
|
5
|
-
import { InstancingUtil } from "./Renderer";
|
|
6
5
|
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
6
|
+
import { InstancingUtil } from "../engine/engine_instancing";
|
|
7
7
|
|
|
8
8
|
export declare class PlayOptions {
|
|
9
9
|
fadeDuration?: number;
|
|
@@ -17,6 +17,11 @@ export class Collider extends Behaviour {
|
|
|
17
17
|
this._shape = null;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
start(){
|
|
21
|
+
if (!this.attachedRigidbody)
|
|
22
|
+
this.attachedRigidbody = this.gameObject.getComponentInParent(Rigidbody);
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
onEnable() {
|
|
21
26
|
// a rigidbody is not assigned if we export an asset
|
|
22
27
|
if (!this.attachedRigidbody)
|
|
@@ -54,9 +59,9 @@ export class SphereCollider extends Collider {
|
|
|
54
59
|
export class BoxCollider extends Collider {
|
|
55
60
|
|
|
56
61
|
@serializeable(Vector3)
|
|
57
|
-
size
|
|
62
|
+
size: THREE.Vector3 = new Vector3(1, 1, 1);
|
|
58
63
|
@serializeable(Vector3)
|
|
59
|
-
center
|
|
64
|
+
center: THREE.Vector3 = new Vector3(0, 0, 0);
|
|
60
65
|
|
|
61
66
|
onEnable() {
|
|
62
67
|
super.onEnable();
|
|
@@ -10,6 +10,8 @@ import { Object3D } from "three";
|
|
|
10
10
|
import { InstantiateIdProvider, syncDestroy, syncInstantiate } from "../engine/engine_networking_instantiate";
|
|
11
11
|
import { SourceIdentifier } from "../engine/engine_gltf";
|
|
12
12
|
import { Collision } from "../engine/engine_physics";
|
|
13
|
+
import * as Object3DExtensions from "./js-extensions/Object3D";
|
|
14
|
+
import { InstancingUtil } from "../engine/engine_instancing";
|
|
13
15
|
|
|
14
16
|
export interface UIDProvider {
|
|
15
17
|
seed: number;
|
|
@@ -70,10 +72,6 @@ declare class NewGameObjectReferenceInfo {
|
|
|
70
72
|
clone: THREE.Object3D;
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
THREE.Object3D.prototype["SetActive"] = function (active: boolean) {
|
|
74
|
-
this.visible = active;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
75
|
|
|
78
76
|
abstract class GameObject extends THREE.Object3D implements THREE.Object3D {
|
|
79
77
|
|
|
@@ -99,7 +97,7 @@ abstract class GameObject extends THREE.Object3D implements THREE.Object3D {
|
|
|
99
97
|
go["__isUsingInstancing"] = instanced;
|
|
100
98
|
}
|
|
101
99
|
|
|
102
|
-
public static isUsingInstancing(instance: THREE.Object3D): boolean { return instance
|
|
100
|
+
public static isUsingInstancing(instance: THREE.Object3D): boolean { return InstancingUtil.isUsingInstancing(instance); }
|
|
103
101
|
|
|
104
102
|
public static foreachComponent(instance: THREE.Object3D, cb: (comp: Component) => any, recursive: boolean = true): any {
|
|
105
103
|
if (!instance) return;
|
|
@@ -217,6 +215,7 @@ abstract class GameObject extends THREE.Object3D implements THREE.Object3D {
|
|
|
217
215
|
instance.children = [];
|
|
218
216
|
let clone: THREE.Object3D | GameObject;
|
|
219
217
|
clone = instance.clone(false);
|
|
218
|
+
Object3DExtensions.apply(clone);
|
|
220
219
|
instance.userData = userData;
|
|
221
220
|
instance.children = children;
|
|
222
221
|
|
|
@@ -684,65 +683,6 @@ abstract class GameObject extends THREE.Object3D implements THREE.Object3D {
|
|
|
684
683
|
}
|
|
685
684
|
|
|
686
685
|
|
|
687
|
-
// this is a fix to allow gameObject active animation be applied to a three object
|
|
688
|
-
Object.defineProperty(THREE.Object3D.prototype, "activeSelf", {
|
|
689
|
-
get: function () {
|
|
690
|
-
return this.visible;
|
|
691
|
-
},
|
|
692
|
-
set: function (val: boolean | number) {
|
|
693
|
-
const state = typeof val === "number" ? val > 0.5 : val;
|
|
694
|
-
this.visible = state;
|
|
695
|
-
}
|
|
696
|
-
});
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
THREE.Object3D.prototype["addNewComponent"] = function <T extends Behaviour>(type: ConstructorConcrete<T>) {
|
|
700
|
-
return GameObject.addNewComponent(this, type);
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
THREE.Object3D.prototype["removeComponent"] = function (inst: Component) {
|
|
704
|
-
return GameObject.removeComponent(inst);
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
THREE.Object3D.prototype["getOrAddComponent"] = function <T>(typeName: Constructor<T> | null): T {
|
|
708
|
-
return GameObject.getOrAddComponent(this, typeName);
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
THREE.Object3D.prototype["getComponent"] = function <T>(type: Constructor<T>) {
|
|
712
|
-
return GameObject.getComponent(this, type);
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
THREE.Object3D.prototype["getComponents"] = function <T>(type: Constructor<T>, arr?: []) {
|
|
716
|
-
return GameObject.getComponents(this, type, arr);
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
THREE.Object3D.prototype["getComponentInChildren"] = function <T>(type: Constructor<T>) {
|
|
720
|
-
return GameObject.getComponentInChildren(this, type);
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
THREE.Object3D.prototype["getComponentsInChildren"] = function <T>(type: Constructor<T>, arr?: []) {
|
|
724
|
-
return GameObject.getComponentsInChildren(this, type, arr);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
THREE.Object3D.prototype["getComponentInParent"] = function <T>(type: Constructor<T>) {
|
|
728
|
-
return GameObject.getComponentInParent(this, type);
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
THREE.Object3D.prototype["getComponentsInParent"] = function <T>(type: Constructor<T>, arr?: []) {
|
|
732
|
-
return GameObject.getComponentsInParent(this, type, arr);
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
// function patch_THREEObject3D() {
|
|
736
|
-
// const props = Object.getOwnPropertyNames(GameObject.prototype);
|
|
737
|
-
// for (const propName in props) {
|
|
738
|
-
// const prop = props[propName];
|
|
739
|
-
// if (prop === "constructor") continue;
|
|
740
|
-
// const fn = GameObject.prototype[prop];
|
|
741
|
-
// THREE.Object3D.prototype[prop] = fn;
|
|
742
|
-
// }
|
|
743
|
-
// }
|
|
744
|
-
// patch_THREEObject3D();
|
|
745
|
-
|
|
746
686
|
|
|
747
687
|
class Component implements EventTarget {
|
|
748
688
|
|
|
@@ -7,12 +7,12 @@ import { Context } from "../engine/engine_setup";
|
|
|
7
7
|
import { Interactable, UsageMarker } from "./Interactable";
|
|
8
8
|
import { Rigidbody } from "./RigidBody";
|
|
9
9
|
import { WebXR } from "./WebXR";
|
|
10
|
-
import { InstancingUtil } from "./Renderer";
|
|
11
10
|
import { Avatar_POI } from "./avatar/Avatar_Brain_LookAt";
|
|
12
11
|
import { RaycastOptions } from "../engine/engine_physics";
|
|
13
12
|
import { getWorldPosition, getWorldQuaternion, setWorldPosition } from "../engine/engine_three_utils";
|
|
14
13
|
import { KeyCode } from "../engine/engine_input";
|
|
15
14
|
import { nameofFactory } from "../engine/engine_utils";
|
|
15
|
+
import { InstancingUtil } from "../engine/engine_instancing";
|
|
16
16
|
|
|
17
17
|
const debug = false;
|
|
18
18
|
|
|
@@ -8,6 +8,7 @@ import { serializeable } from "../engine/engine_serialization_decorator";
|
|
|
8
8
|
import { Material, Texture, Vector4 } from "three";
|
|
9
9
|
import { NEEDLE_render_objects } from "../engine/extensions/NEEDLE_render_objects";
|
|
10
10
|
import { NEEDLE_deferred_texture } from "../engine/extensions/NEEDLE_deferred_texture";
|
|
11
|
+
import { NEED_UPDATE_INSTANCE_KEY } from "../engine/engine_instancing";
|
|
11
12
|
|
|
12
13
|
const suppressInstancing = getParam("noInstancing");
|
|
13
14
|
const debugLightmap = getParam("debuglightmaps") ? true : false;
|
|
@@ -491,26 +492,7 @@ export enum ShadowCastingMode {
|
|
|
491
492
|
ShadowsOnly,
|
|
492
493
|
}
|
|
493
494
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
export class InstancingUtil {
|
|
497
|
-
// TODO: change this so it does not set matrix world directly but some flag that is only used by instancing
|
|
498
|
-
static markDirty(go: THREE.Object3D | null, recursive: boolean = true) {
|
|
499
|
-
if (!go) return;
|
|
500
|
-
// potential optimization:
|
|
501
|
-
// if(go.matrixWorldNeedsUpdate) return;
|
|
502
|
-
// console.trace(go, GameObject.isUsingInstancing(go));
|
|
503
|
-
if (GameObject.isUsingInstancing(go)) {
|
|
504
|
-
go[NEED_UPDATE_INSTANCE_KEY] = true;
|
|
505
|
-
go.matrixWorldNeedsUpdate = true;
|
|
506
|
-
}
|
|
507
|
-
if (recursive) {
|
|
508
|
-
for (const child of go.children) {
|
|
509
|
-
InstancingUtil.markDirty(child, true);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
}
|
|
495
|
+
|
|
514
496
|
|
|
515
497
|
declare class InstancingSetupArgs { rend: Renderer; foundMeshes: number };
|
|
516
498
|
|
|
@@ -9,12 +9,14 @@ import { IModel } from "../engine/engine_networking";
|
|
|
9
9
|
import { IPointerClickHandler } from "./ui/PointerEvents";
|
|
10
10
|
import { EventDispatcher } from "three";
|
|
11
11
|
import { AudioSource } from "./AudioSource";
|
|
12
|
-
import {
|
|
12
|
+
import { getParam } from "../engine/engine_utils";
|
|
13
13
|
|
|
14
|
+
const debug = getParam("debugscreenshare");
|
|
14
15
|
|
|
15
16
|
export enum ScreenCaptureDevice {
|
|
16
17
|
Screen = 0,
|
|
17
|
-
Camera = 1
|
|
18
|
+
Camera = 1,
|
|
19
|
+
Canvas = 2
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
export enum ScreenCaptureMode {
|
|
@@ -23,12 +25,6 @@ export enum ScreenCaptureMode {
|
|
|
23
25
|
Receiving = 2
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
export enum AspectMode {
|
|
27
|
-
None = 0,
|
|
28
|
-
AdjustHeight = 1,
|
|
29
|
-
AdjustWidth = 2,
|
|
30
|
-
}
|
|
31
|
-
|
|
32
28
|
function disposeStream(str: MediaStream | null | undefined) {
|
|
33
29
|
if (!str) return;
|
|
34
30
|
for (const cap of str.getTracks())
|
|
@@ -38,6 +34,11 @@ function disposeStream(str: MediaStream | null | undefined) {
|
|
|
38
34
|
export class ScreenCapture extends Behaviour implements IPointerClickHandler {
|
|
39
35
|
|
|
40
36
|
onPointerClick() {
|
|
37
|
+
if (this.isReceiving) {
|
|
38
|
+
if (this.videoPlayer)
|
|
39
|
+
this.videoPlayer.screenspace = !this.videoPlayer.screenspace;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
41
42
|
if (this.isSending) {
|
|
42
43
|
this.close();
|
|
43
44
|
return;
|
|
@@ -46,40 +47,55 @@ export class ScreenCapture extends Behaviour implements IPointerClickHandler {
|
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
@serializeable(VideoPlayer)
|
|
51
|
+
videoPlayer?: VideoPlayer;
|
|
50
52
|
|
|
51
53
|
@serializeable()
|
|
52
54
|
device: ScreenCaptureDevice = ScreenCaptureDevice.Screen;
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
get currentScream(): MediaStream | null {
|
|
57
|
+
return this._currentStream;
|
|
58
|
+
}
|
|
56
59
|
|
|
60
|
+
get currentMode(): ScreenCaptureMode {
|
|
61
|
+
return this._currentMode;
|
|
62
|
+
}
|
|
57
63
|
|
|
58
64
|
get isSending() {
|
|
59
|
-
return this._currentStream && this._currentMode === ScreenCaptureMode.Sending;
|
|
65
|
+
return this._currentStream?.active && this._currentMode === ScreenCaptureMode.Sending;
|
|
60
66
|
}
|
|
61
67
|
get isReceiving() {
|
|
62
|
-
|
|
68
|
+
if (this._currentMode === ScreenCaptureMode.Receiving) {
|
|
69
|
+
if (!this._currentStream || this._currentStream.active === false) return false;
|
|
70
|
+
// if any track is still live consider it active
|
|
71
|
+
const tracks = this._currentStream.getTracks();
|
|
72
|
+
for (const track of tracks) {
|
|
73
|
+
if (track.readyState === "live") return true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
63
77
|
}
|
|
64
78
|
|
|
65
79
|
private _net?: NetworkedVideo;
|
|
66
|
-
private _video?: VideoPlayer;
|
|
67
80
|
private _requestOpen: boolean = false;
|
|
68
81
|
private _currentStream: MediaStream | null = null;
|
|
69
82
|
private _currentMode: ScreenCaptureMode = ScreenCaptureMode.Idle;
|
|
70
83
|
|
|
71
84
|
awake() {
|
|
85
|
+
console.log(this);
|
|
72
86
|
AudioSource.registerWaitForAllowAudio(() => {
|
|
73
|
-
if (this.
|
|
74
|
-
this.
|
|
87
|
+
if (this.videoPlayer && this._currentStream && this._currentMode === ScreenCaptureMode.Receiving) {
|
|
88
|
+
this.videoPlayer.setVideo(this._currentStream);
|
|
75
89
|
}
|
|
76
90
|
});
|
|
77
91
|
}
|
|
78
92
|
|
|
79
93
|
start() {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
94
|
+
if (!this.videoPlayer) {
|
|
95
|
+
this.videoPlayer = GameObject.getComponent(this.gameObject, VideoPlayer) ?? undefined;
|
|
96
|
+
}
|
|
97
|
+
if (!this.videoPlayer) {
|
|
98
|
+
console.error("Screencapture did not find a VideoPlayer component");
|
|
83
99
|
return;
|
|
84
100
|
}
|
|
85
101
|
const handle = PeerHandle.getOrCreate(this.context, this.guid);
|
|
@@ -92,7 +108,7 @@ export class ScreenCapture extends Behaviour implements IPointerClickHandler {
|
|
|
92
108
|
async share() {
|
|
93
109
|
this._requestOpen = true;
|
|
94
110
|
try {
|
|
95
|
-
if (this.
|
|
111
|
+
if (this.videoPlayer) {
|
|
96
112
|
|
|
97
113
|
const settings: MediaTrackConstraints = {
|
|
98
114
|
echoCancellation: true,
|
|
@@ -104,10 +120,12 @@ export class ScreenCapture extends Behaviour implements IPointerClickHandler {
|
|
|
104
120
|
};
|
|
105
121
|
|
|
106
122
|
switch (this.device) {
|
|
123
|
+
// Capture a connected camera
|
|
107
124
|
case ScreenCaptureDevice.Camera:
|
|
108
125
|
this.tryShareUserCamera(displayMediaOptions);
|
|
109
126
|
break;
|
|
110
127
|
|
|
128
|
+
// capture any screen, will show a popup
|
|
111
129
|
case ScreenCaptureDevice.Screen:
|
|
112
130
|
if (!navigator.mediaDevices.getDisplayMedia) {
|
|
113
131
|
console.error("No getDisplayMedia support");
|
|
@@ -119,6 +137,16 @@ export class ScreenCapture extends Behaviour implements IPointerClickHandler {
|
|
|
119
137
|
}
|
|
120
138
|
else disposeStream(myVideo);
|
|
121
139
|
break;
|
|
140
|
+
|
|
141
|
+
// capture the canvas meaning the threejs view
|
|
142
|
+
case ScreenCaptureDevice.Canvas:
|
|
143
|
+
// looks like this doesnt work reliably on chrome https://stackoverflow.com/a/66848674
|
|
144
|
+
// firefox updates fine
|
|
145
|
+
// https://bugs.chromium.org/p/chromium/issues/detail?id=1156408
|
|
146
|
+
const fps = 0;
|
|
147
|
+
const stream = this.context.renderer.domElement.captureStream(fps);
|
|
148
|
+
this.setVideo(stream, ScreenCaptureMode.Sending);
|
|
149
|
+
break;
|
|
122
150
|
}
|
|
123
151
|
}
|
|
124
152
|
} catch (err: any) {
|
|
@@ -136,8 +164,8 @@ export class ScreenCapture extends Behaviour implements IPointerClickHandler {
|
|
|
136
164
|
this._requestOpen = false;
|
|
137
165
|
if (this._currentStream) {
|
|
138
166
|
console.warn("Close current stream / disposing resources");
|
|
139
|
-
disposeStream(this._currentStream);
|
|
140
167
|
this._net?.stopSendingVideo(this._currentStream);
|
|
168
|
+
disposeStream(this._currentStream);
|
|
141
169
|
this._currentMode = ScreenCaptureMode.Idle;
|
|
142
170
|
this._currentStream = null;
|
|
143
171
|
}
|
|
@@ -146,16 +174,21 @@ export class ScreenCapture extends Behaviour implements IPointerClickHandler {
|
|
|
146
174
|
private setVideo(stream: MediaStream, mode: ScreenCaptureMode) {
|
|
147
175
|
if (stream === this._currentStream) return;
|
|
148
176
|
this.close();
|
|
149
|
-
if (!stream || !this.
|
|
177
|
+
if (!stream || !this.videoPlayer) return;
|
|
150
178
|
this._currentStream = stream;
|
|
151
179
|
this._requestOpen = true;
|
|
152
180
|
this._currentMode = mode;
|
|
153
|
-
this.
|
|
154
|
-
|
|
181
|
+
this.videoPlayer.setVideo(stream);
|
|
182
|
+
|
|
183
|
+
const isSending = mode === ScreenCaptureMode.Sending;
|
|
184
|
+
if (isSending) {
|
|
155
185
|
this._net?.startSendingVideo(stream);
|
|
156
186
|
|
|
157
|
-
|
|
158
|
-
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
stream.addEventListener("ended", () => {
|
|
190
|
+
this.close();
|
|
191
|
+
});
|
|
159
192
|
}
|
|
160
193
|
|
|
161
194
|
private onReceiveVideo(evt: ReceiveVideoEvent) {
|
|
@@ -164,7 +197,6 @@ export class ScreenCapture extends Behaviour implements IPointerClickHandler {
|
|
|
164
197
|
|
|
165
198
|
|
|
166
199
|
|
|
167
|
-
|
|
168
200
|
private async tryShareUserCamera(opts: DisplayMediaStreamConstraints) {
|
|
169
201
|
|
|
170
202
|
// let newWindow = open('', 'example', 'width=300,height=300');
|
|
@@ -203,53 +235,6 @@ export class ScreenCapture extends Behaviour implements IPointerClickHandler {
|
|
|
203
235
|
// private openWindowToSelectCamera(){
|
|
204
236
|
|
|
205
237
|
// }
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
private _targetObjects?: Array<THREE.Object3D>;
|
|
211
|
-
|
|
212
|
-
private updateAspect() {
|
|
213
|
-
this.startCoroutine(this.updateAspectImpl());
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
private _updateAspectRoutineId: number = -1;
|
|
217
|
-
private *updateAspectImpl() {
|
|
218
|
-
const id = ++this._updateAspectRoutineId;
|
|
219
|
-
while (this.aspectMode !== AspectMode.None && this._currentStream && id === this._updateAspectRoutineId) {
|
|
220
|
-
const video = this._video;
|
|
221
|
-
const stream = this._currentStream;
|
|
222
|
-
if (!video) return;
|
|
223
|
-
if (!stream) return;
|
|
224
|
-
let aspect: number | undefined = undefined;
|
|
225
|
-
for (const track of stream.getVideoTracks()) {
|
|
226
|
-
const settings = track.getSettings();
|
|
227
|
-
if (settings.width && settings.height) {
|
|
228
|
-
aspect = settings.width / settings.height;
|
|
229
|
-
break;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
if (aspect === undefined) return;
|
|
233
|
-
if (!this._targetObjects)
|
|
234
|
-
this._targetObjects = video.getTargetObjects();
|
|
235
|
-
for (const obj of this._targetObjects) {
|
|
236
|
-
let worldAspect = 1;
|
|
237
|
-
if (obj.parent) {
|
|
238
|
-
const parentScale = getWorldScale(obj.parent);
|
|
239
|
-
worldAspect = parentScale.x / parentScale.y;
|
|
240
|
-
}
|
|
241
|
-
switch (this.aspectMode) {
|
|
242
|
-
case AspectMode.AdjustHeight:
|
|
243
|
-
obj.scale.y = 1 / aspect * obj.scale.x * worldAspect;
|
|
244
|
-
break;
|
|
245
|
-
case AspectMode.AdjustWidth:
|
|
246
|
-
obj.scale.x = aspect * obj.scale.y * worldAspect;
|
|
247
|
-
break;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
yield;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
238
|
}
|
|
254
239
|
|
|
255
240
|
|
|
@@ -444,7 +429,8 @@ class PeerHandle extends EventDispatcher {
|
|
|
444
429
|
}
|
|
445
430
|
|
|
446
431
|
private onPeerConnect(id): void {
|
|
447
|
-
|
|
432
|
+
if (debug)
|
|
433
|
+
console.log("Peer connected as", id);
|
|
448
434
|
this.context.connection.send(PeerEvent.Connected, new PeerUserConnectedModel(this, id));
|
|
449
435
|
}
|
|
450
436
|
|
|
@@ -539,6 +525,7 @@ class NetworkedVideo extends EventDispatcher {
|
|
|
539
525
|
if (_steam) {
|
|
540
526
|
const calls = this._sendingVideoStreams.get(_steam);
|
|
541
527
|
if (calls) {
|
|
528
|
+
console.log("Closing calls", calls);
|
|
542
529
|
for (const call of calls) {
|
|
543
530
|
call.close();
|
|
544
531
|
}
|