@needle-tools/engine 2.65.1-pre → 2.66.1-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 +27 -0
- package/dist/needle-engine.js +7945 -7782
- package/dist/needle-engine.umd.cjs +223 -223
- package/lib/engine/debug/debug_overlay.js +4 -1
- package/lib/engine/debug/debug_overlay.js.map +1 -1
- package/lib/engine/engine_addressables.js +2 -2
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_element.d.ts +1 -0
- package/lib/engine/engine_element.js +4 -1
- package/lib/engine/engine_element.js.map +1 -1
- package/lib/engine/engine_element_loading.d.ts +3 -2
- package/lib/engine/engine_element_loading.js +18 -14
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_gameobject.js +6 -3
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_gizmos.js +3 -1
- package/lib/engine/engine_gizmos.js.map +1 -1
- package/lib/engine/engine_networking.d.ts +3 -1
- package/lib/engine/engine_networking.js +10 -8
- package/lib/engine/engine_networking.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +29 -1
- package/lib/engine/engine_physics.js +99 -10
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_setup.js +3 -0
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_render_objects.js +9 -0
- package/lib/engine/extensions/NEEDLE_render_objects.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +5 -2
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
- package/lib/engine-components/Animator.d.ts +25 -1
- package/lib/engine-components/Animator.js +63 -37
- package/lib/engine-components/Animator.js.map +1 -1
- package/lib/engine-components/AnimatorController.d.ts +14 -12
- package/lib/engine-components/AnimatorController.js +15 -13
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/CharacterController.d.ts +1 -0
- package/lib/engine-components/CharacterController.js +14 -9
- package/lib/engine-components/CharacterController.js.map +1 -1
- package/lib/engine-components/Collider.js +14 -1
- package/lib/engine-components/Collider.js.map +1 -1
- package/lib/engine-components/ParticleSystem.d.ts +5 -1
- package/lib/engine-components/ParticleSystem.js +41 -6
- package/lib/engine-components/ParticleSystem.js.map +1 -1
- package/lib/engine-components/ParticleSystemModules.d.ts +2 -0
- package/lib/engine-components/ParticleSystemModules.js +26 -0
- package/lib/engine-components/ParticleSystemModules.js.map +1 -1
- package/lib/engine-components/ParticleSystemSubEmitter.js +5 -2
- package/lib/engine-components/ParticleSystemSubEmitter.js.map +1 -1
- package/lib/engine-components/Renderer.js +9 -5
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/ScreenCapture.js +3 -3
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/SpectatorCamera.js +3 -3
- package/lib/engine-components/SpectatorCamera.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 +2 -2
- package/lib/engine-components/SyncedTransform.js.map +1 -1
- package/lib/engine-components/TestRunner.js +1 -1
- package/lib/engine-components/TestRunner.js.map +1 -1
- package/lib/engine-components/WebARSessionRoot.js +3 -2
- package/lib/engine-components/WebARSessionRoot.js.map +1 -1
- package/lib/engine-components/WebXRAvatar.js.map +1 -1
- package/lib/engine-components/WebXRGrabRendering.js +2 -2
- package/lib/engine-components/WebXRGrabRendering.js.map +1 -1
- package/lib/engine-components/WebXRSync.js +2 -2
- package/lib/engine-components/WebXRSync.js.map +1 -1
- package/lib/engine-components-experimental/networking/PlayerSync.js +1 -1
- package/lib/engine-components-experimental/networking/PlayerSync.js.map +1 -1
- package/package.json +1 -1
- package/plugins/vite/meta.js +3 -0
- package/plugins/vite/poster-client.js +6 -4
- package/src/engine/debug/debug_overlay.ts +4 -1
- package/src/engine/engine_addressables.ts +2 -2
- package/src/engine/engine_element.ts +8 -1
- package/src/engine/engine_element_loading.ts +18 -14
- package/src/engine/engine_gameobject.ts +584 -583
- package/src/engine/engine_gizmos.ts +3 -2
- package/src/engine/engine_networking.ts +10 -8
- package/src/engine/engine_physics.ts +113 -10
- package/src/engine/engine_setup.ts +4 -0
- package/src/engine/extensions/NEEDLE_render_objects.ts +10 -1
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +5 -2
- package/src/engine-components/Animator.ts +53 -27
- package/src/engine-components/AnimatorController.ts +15 -13
- package/src/engine-components/CharacterController.ts +12 -9
- package/src/engine-components/Collider.ts +16 -2
- package/src/engine-components/ParticleSystem.ts +45 -9
- package/src/engine-components/ParticleSystemModules.ts +28 -1
- package/src/engine-components/ParticleSystemSubEmitter.ts +5 -3
- package/src/engine-components/Renderer.ts +14 -11
- package/src/engine-components/ScreenCapture.ts +3 -3
- package/src/engine-components/SpectatorCamera.ts +3 -3
- package/src/engine-components/SyncedCamera.ts +1 -1
- package/src/engine-components/SyncedTransform.ts +2 -2
- package/src/engine-components/TestRunner.ts +1 -1
- package/src/engine-components/WebARSessionRoot.ts +3 -2
- package/src/engine-components/WebXRAvatar.ts +0 -1
- package/src/engine-components/WebXRGrabRendering.ts +2 -2
- package/src/engine-components/WebXRSync.ts +2 -2
- package/src/engine-components-experimental/networking/PlayerSync.ts +1 -1
|
@@ -145,10 +145,9 @@ class Internal {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
static getSphere(radius: number, duration: number, wireframe: boolean): Mesh {
|
|
148
|
-
|
|
149
148
|
let sphere = this.spheresCache.pop();
|
|
150
149
|
if (!sphere) {
|
|
151
|
-
sphere = new Mesh(new SphereGeometry(
|
|
150
|
+
sphere = new Mesh(new SphereGeometry(1, 8, 8));
|
|
152
151
|
}
|
|
153
152
|
sphere.scale.set(radius, radius, radius);
|
|
154
153
|
sphere.material["wireframe"] = wireframe;
|
|
@@ -176,6 +175,8 @@ class Internal {
|
|
|
176
175
|
this.contextPostRenderCallbacks.set(context, cb);
|
|
177
176
|
context.post_render_callbacks.push(cb);
|
|
178
177
|
}
|
|
178
|
+
object.layers.disableAll();
|
|
179
|
+
object.layers.enable(2);
|
|
179
180
|
object[$cacheSymbol] = cache;
|
|
180
181
|
this.timedObjectsBuffer.push(object);
|
|
181
182
|
this.timesBuffer.push(Context.Current.time.time + duration);
|
|
@@ -147,7 +147,7 @@ export class OwnershipModel {
|
|
|
147
147
|
// console.log(res);
|
|
148
148
|
if (res.guid === this.guid) {
|
|
149
149
|
if (this._isWaitingForOwnershipResponseCallback) {
|
|
150
|
-
this.connection.
|
|
150
|
+
this.connection.stopListen(OwnershipEvent.ResponseHasOwner, this._isWaitingForOwnershipResponseCallback);
|
|
151
151
|
this._isWaitingForOwnershipResponseCallback = null;
|
|
152
152
|
}
|
|
153
153
|
this._isOwned = res.value;
|
|
@@ -185,18 +185,18 @@ export class OwnershipModel {
|
|
|
185
185
|
// TODO: abort "requestOwnershipIfNotOwned"
|
|
186
186
|
this.connection.send(OwnershipEvent.RemoveOwnership, { guid: this.guid });
|
|
187
187
|
if (this._isWaitingForOwnershipResponseCallback) {
|
|
188
|
-
this.connection.
|
|
188
|
+
this.connection.stopListen(OwnershipEvent.ResponseHasOwner, this._isWaitingForOwnershipResponseCallback);
|
|
189
189
|
this._isWaitingForOwnershipResponseCallback = null;
|
|
190
190
|
}
|
|
191
191
|
return this;
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
public destroy() {
|
|
195
|
-
this.connection.
|
|
196
|
-
this.connection.
|
|
197
|
-
this.connection.
|
|
195
|
+
this.connection.stopListen(OwnershipEvent.GainedOwnership, this._gainSubscription);
|
|
196
|
+
this.connection.stopListen(OwnershipEvent.LostOwnership, this._lostSubscription);
|
|
197
|
+
this.connection.stopListen(OwnershipEvent.ResponseHasOwner, this._hasOwnerResponse);
|
|
198
198
|
if (this._isWaitingForOwnershipResponseCallback) {
|
|
199
|
-
this.connection.
|
|
199
|
+
this.connection.stopListen(OwnershipEvent.ResponseHasOwner, this._isWaitingForOwnershipResponseCallback);
|
|
200
200
|
this._isWaitingForOwnershipResponseCallback = null;
|
|
201
201
|
}
|
|
202
202
|
}
|
|
@@ -368,7 +368,9 @@ export class NetworkConnection implements INetworkConnection {
|
|
|
368
368
|
return callback;
|
|
369
369
|
}
|
|
370
370
|
|
|
371
|
-
|
|
371
|
+
/**@deprecated please use stopListen instead (2.65.2-pre) */
|
|
372
|
+
public stopListening(key: string | OwnershipEvent, callback: Function | null) { return this.stopListen(key, callback); }
|
|
373
|
+
public stopListen(key: string | OwnershipEvent, callback: Function | null) {
|
|
372
374
|
if (!callback) return;
|
|
373
375
|
if (!this._listeners[key]) return;
|
|
374
376
|
const index = this._listeners[key].indexOf(callback);
|
|
@@ -377,7 +379,7 @@ export class NetworkConnection implements INetworkConnection {
|
|
|
377
379
|
}
|
|
378
380
|
}
|
|
379
381
|
|
|
380
|
-
public
|
|
382
|
+
public beginListenBinary(identifier: string, callback: BinaryCallback): BinaryCallback {
|
|
381
383
|
if (!this._listenersBinary[identifier])
|
|
382
384
|
this._listenersBinary[identifier] = [];
|
|
383
385
|
this._listenersBinary[identifier].push(callback);
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import { InstancingUtil } from './engine_instancing';
|
|
16
16
|
import { foreachComponent } from './engine_gameobject';
|
|
17
17
|
|
|
18
|
-
import RAPIER, { ActiveEvents, CoefficientCombineRule, Collider, ColliderDesc, EventQueue, JointData, RigidBody, RigidBodyType, World } from '@dimforge/rapier3d-compat';
|
|
18
|
+
import RAPIER, { ActiveEvents, CoefficientCombineRule, Collider, ColliderDesc, EventQueue, JointData, QueryFilterFlags, RigidBody, RigidBodyType, ShapeColliderTOI, World } from '@dimforge/rapier3d-compat';
|
|
19
19
|
import { CollisionDetectionMode, PhysicsMaterialCombine } from '../engine/engine_physics.types';
|
|
20
20
|
import { Gizmos } from './engine_gizmos';
|
|
21
21
|
import { Mathf } from './engine_math';
|
|
@@ -83,12 +83,22 @@ export class SphereIntersection implements Intersection {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
export class SphereOverlapResult {
|
|
87
|
+
object: Object3D;
|
|
88
|
+
collider: ICollider;
|
|
89
|
+
constructor(object: Object3D, collider: ICollider) {
|
|
90
|
+
this.object = object;
|
|
91
|
+
this.collider = collider;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
86
95
|
declare type PhysicsRaycastResult = {
|
|
87
96
|
point: Vector3,
|
|
88
97
|
normal?: Vector3,
|
|
89
98
|
collider?: ICollider
|
|
90
99
|
}
|
|
91
100
|
|
|
101
|
+
|
|
92
102
|
export class Physics {
|
|
93
103
|
|
|
94
104
|
// raycasting
|
|
@@ -107,6 +117,12 @@ export class Physics {
|
|
|
107
117
|
|
|
108
118
|
private sphereResults: Array<Intersection> = new Array<Intersection>();
|
|
109
119
|
private sphereMask: Layers = new Layers();
|
|
120
|
+
/** Test overlapping of a sphere with the threejs geometry. This does not use colliders. This does not return an exact intersection point (intersections returned contain the object and the world position of the object that is being hit)
|
|
121
|
+
* For a more accurate test use the physics engine's collider overlap test (see sphereOverlapPhysics)
|
|
122
|
+
* @param spherePos the center of the sphere in world space
|
|
123
|
+
* @param radius the radius of the sphere
|
|
124
|
+
* @param traverseChildsAfterHit if false it will stop after the first hit. If true it will continue to traverse and add all hits to the result array
|
|
125
|
+
*/
|
|
110
126
|
public sphereOverlap(spherePos: Vector3, radius: number, traverseChildsAfterHit: boolean = true): Array<Intersection> {
|
|
111
127
|
this.sphereResults.length = 0;
|
|
112
128
|
if (!this.context.scene) return this.sphereResults;
|
|
@@ -130,10 +146,9 @@ export class Physics {
|
|
|
130
146
|
if (mesh.matrixWorldNeedsUpdate) mesh.updateMatrixWorld();
|
|
131
147
|
const test = this.tempBoundingBox.copy(geo.boundingBox).applyMatrix4(mesh.matrixWorld);
|
|
132
148
|
if (sp.intersectsBox(test)) {
|
|
133
|
-
// console.log(obj, obj.layers.test(mask), obj.layers.mask, mask.mask);
|
|
134
149
|
const wp = getWorldPosition(obj);
|
|
135
150
|
const dist = wp.distanceTo(sp.center);
|
|
136
|
-
const int = new SphereIntersection(obj, dist,
|
|
151
|
+
const int = new SphereIntersection(obj, dist, wp);
|
|
137
152
|
results.push(int);
|
|
138
153
|
if (!traverseChildsAfterHit) return;
|
|
139
154
|
}
|
|
@@ -157,6 +172,8 @@ export class Physics {
|
|
|
157
172
|
/** raycast against rendered three objects. This might be very slow depending on your scene complexity.
|
|
158
173
|
* We recommend setting objects to IgnoreRaycast layer (2) when you don't need them to be raycasted.
|
|
159
174
|
* Raycasting SkinnedMeshes is specially expensive.
|
|
175
|
+
* Use raycastPhysics for raycasting against physic colliders only. Depending on your scenario this might be faster.
|
|
176
|
+
* @param options raycast options. If null, default options will be used.
|
|
160
177
|
*/
|
|
161
178
|
public raycast(options: RaycastOptions | null = null): Array<Intersection> {
|
|
162
179
|
if (!options) options = this.defaultRaycastOptions;
|
|
@@ -222,8 +239,12 @@ export class Physics {
|
|
|
222
239
|
|
|
223
240
|
private rapierRay = new RAPIER.Ray({ x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 1 });
|
|
224
241
|
private raycastVectorsBuffer = new CircularBuffer(() => new Vector3(), 10);
|
|
225
|
-
|
|
226
|
-
|
|
242
|
+
/** Fast raycast against physics colliders
|
|
243
|
+
* @param origin ray origin in screen or worldspace
|
|
244
|
+
* @param direction ray direction in worldspace
|
|
245
|
+
* @param maxDistance max distance to raycast
|
|
246
|
+
* @param solid if true it will also hit the collider if origin is already inside it
|
|
247
|
+
*/
|
|
227
248
|
public raycastPhysicsFast(origin: Vec2 | Vec3, direction: Vec3 | undefined = undefined, maxDistance: number = Infinity, solid: boolean = true)
|
|
228
249
|
: null | { point: Vector3, collider: ICollider } {
|
|
229
250
|
|
|
@@ -285,6 +306,72 @@ export class Physics {
|
|
|
285
306
|
return ray;
|
|
286
307
|
}
|
|
287
308
|
|
|
309
|
+
|
|
310
|
+
private rapierSphere: RAPIER.Ball | null = null;
|
|
311
|
+
private rapierColliderArray: Array<SphereOverlapResult> = [];
|
|
312
|
+
private readonly rapierIdentityRotation = { x: 0, y: 0, z: 0, w: 1 };
|
|
313
|
+
private readonly rapierForwardVector = { x: 0, y: 0, z: 1 };
|
|
314
|
+
/** Precice sphere overlap detection using rapier against colliders
|
|
315
|
+
* @param point center of the sphere in worldspace
|
|
316
|
+
* @param radius radius of the sphere
|
|
317
|
+
* @returns array of colliders that overlap with the sphere. Note: they currently only contain the collider and the gameobject
|
|
318
|
+
*/
|
|
319
|
+
public sphereOverlapPhysics(point: Vector3, radius: number): Array<SphereOverlapResult> {
|
|
320
|
+
this.rapierColliderArray.length = 0;
|
|
321
|
+
if (!this.world) return this.rapierColliderArray;
|
|
322
|
+
if (!this.rapierSphere)
|
|
323
|
+
this.rapierSphere = new RAPIER.Ball(radius);
|
|
324
|
+
this.rapierSphere.radius = radius;
|
|
325
|
+
|
|
326
|
+
this.world.intersectionsWithShape(point, this.rapierIdentityRotation, this.rapierSphere, col => {
|
|
327
|
+
const collider = col[$componentKey] as ICollider
|
|
328
|
+
// if (collider.gameObject.layers.isEnabled(2)) return true;
|
|
329
|
+
const intersection = new SphereOverlapResult(collider.gameObject, collider);
|
|
330
|
+
this.rapierColliderArray.push(intersection);
|
|
331
|
+
return true; // Return `false` instead if we want to stop searching for other colliders that contain this point.
|
|
332
|
+
}, QueryFilterFlags.EXCLUDE_SENSORS, undefined, undefined, undefined,
|
|
333
|
+
col => {
|
|
334
|
+
const collider = col[$componentKey] as ICollider
|
|
335
|
+
return collider.gameObject.layers.isEnabled(2) == false
|
|
336
|
+
}
|
|
337
|
+
);
|
|
338
|
+
return this.rapierColliderArray;
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
// TODO: this only returns one hit
|
|
342
|
+
// let filterGroups = 0xffffffff;
|
|
343
|
+
// filterGroups &= ~(1 << 2);
|
|
344
|
+
// const hit: ShapeColliderTOI | null = this.world.castShape(point,
|
|
345
|
+
// this.rapierIdentityRotation,
|
|
346
|
+
// this.rapierForwardVector,
|
|
347
|
+
// this.rapierSphere,
|
|
348
|
+
// 0,
|
|
349
|
+
// QueryFilterFlags.EXCLUDE_SENSORS,
|
|
350
|
+
// // filterGroups,
|
|
351
|
+
// );
|
|
352
|
+
// // console.log(hit);
|
|
353
|
+
// if (hit) {
|
|
354
|
+
// const collider = hit.collider[$componentKey] as ICollider
|
|
355
|
+
// const intersection = new SphereOverlapResult(collider.gameObject);
|
|
356
|
+
// this.rapierColliderArray.push(intersection);
|
|
357
|
+
// // const localpt = hit.witness2;
|
|
358
|
+
// // // const normal = hit.normal2;
|
|
359
|
+
// // const hitPoint = new Vector3(localpt.x, localpt.y, localpt.z);
|
|
360
|
+
// // // collider.gameObject.localToWorld(hitPoint);
|
|
361
|
+
// // // const normalPt = new Vector3(normal.x, normal.y, normal.z);
|
|
362
|
+
// // // const mat = new Matrix4().setPosition(point).scale(new Vector3(radius, radius, radius));
|
|
363
|
+
// // // hitPoint.applyMatrix4(mat);
|
|
364
|
+
// // console.log(hit.witness2)
|
|
365
|
+
// // // hitPoint.add(point);
|
|
366
|
+
// // const dist = hitPoint.distanceTo(point);
|
|
367
|
+
// }
|
|
368
|
+
|
|
369
|
+
// return this.rapierColliderArray;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
288
375
|
// physics simulation
|
|
289
376
|
|
|
290
377
|
enabled: boolean = true;
|
|
@@ -352,42 +439,58 @@ export class Physics {
|
|
|
352
439
|
|
|
353
440
|
addBoxCollider(collider: ICollider, center: Vector3, size: Vector3) {
|
|
354
441
|
if (!this.enabled) {
|
|
355
|
-
if(debugPhysics) console.warn("Physics
|
|
442
|
+
if (debugPhysics) console.warn("Physics are disabled");
|
|
356
443
|
return;
|
|
357
444
|
}
|
|
358
445
|
const obj = collider.gameObject;
|
|
359
446
|
const scale = getWorldScale(obj, this._tempPosition).multiply(size);
|
|
360
447
|
scale.multiplyScalar(0.5);
|
|
448
|
+
|
|
449
|
+
// prevent negative scale
|
|
450
|
+
if (scale.x < 0)
|
|
451
|
+
scale.x = Math.abs(scale.x);
|
|
452
|
+
if (scale.y < 0)
|
|
453
|
+
scale.y = Math.abs(scale.y);
|
|
454
|
+
if (scale.z < 0)
|
|
455
|
+
scale.z = Math.abs(scale.z);
|
|
456
|
+
|
|
361
457
|
const desc = ColliderDesc.cuboid(scale.x, scale.y, scale.z);
|
|
458
|
+
// const objectLayerMask = collider.gameObject.layers.mask;
|
|
459
|
+
// const mask = objectLayerMask & ~2;
|
|
460
|
+
// desc.setCollisionGroups(objectLayerMask);
|
|
362
461
|
this.createCollider(collider, desc, center);
|
|
363
462
|
}
|
|
364
463
|
|
|
365
464
|
addSphereCollider(collider: ICollider, center: Vector3, radius: number) {
|
|
366
465
|
if (!this.enabled) {
|
|
367
|
-
if(debugPhysics) console.warn("Physics
|
|
466
|
+
if (debugPhysics) console.warn("Physics are disabled");
|
|
368
467
|
return;
|
|
369
468
|
}
|
|
370
469
|
const obj = collider.gameObject;
|
|
371
470
|
const scale = getWorldScale(obj, this._tempPosition).multiplyScalar(radius);
|
|
471
|
+
// Prevent negative scales
|
|
472
|
+
scale.x = Math.abs(scale.x);
|
|
372
473
|
const desc = ColliderDesc.ball(scale.x);
|
|
373
474
|
this.createCollider(collider, desc, center);
|
|
374
475
|
}
|
|
375
476
|
|
|
376
477
|
addCapsuleCollider(collider: ICollider, center: Vector3, height: number, radius: number) {
|
|
377
478
|
if (!this.enabled) {
|
|
378
|
-
if(debugPhysics) console.warn("Physics
|
|
479
|
+
if (debugPhysics) console.warn("Physics are disabled");
|
|
379
480
|
return;
|
|
380
481
|
}
|
|
381
482
|
const obj = collider.gameObject;
|
|
382
483
|
const scale = getWorldScale(obj, this._tempPosition);
|
|
383
|
-
|
|
484
|
+
// Prevent negative scales
|
|
485
|
+
scale.x = Math.abs(scale.x);
|
|
486
|
+
scale.y = Math.abs(scale.y);
|
|
384
487
|
const desc = ColliderDesc.capsule(height * .5 * scale.y - radius, radius * scale.x);
|
|
385
488
|
this.createCollider(collider, desc, center);
|
|
386
489
|
}
|
|
387
490
|
|
|
388
491
|
addMeshCollider(collider: ICollider, mesh: Mesh, convex: boolean, scale: Vector3) {
|
|
389
492
|
if (!this.enabled) {
|
|
390
|
-
if(debugPhysics) console.warn("Physics
|
|
493
|
+
if (debugPhysics) console.warn("Physics are disabled");
|
|
391
494
|
return;
|
|
392
495
|
}
|
|
393
496
|
const geo = mesh.geometry;
|
|
@@ -744,6 +744,10 @@ export class Context implements IContext {
|
|
|
744
744
|
this.connection.sendBufferedMessagesNow();
|
|
745
745
|
|
|
746
746
|
this._stats?.end();
|
|
747
|
+
|
|
748
|
+
if (this.time.frame === 1) {
|
|
749
|
+
this.domElement.dispatchEvent(new CustomEvent("ready"));
|
|
750
|
+
}
|
|
747
751
|
}
|
|
748
752
|
|
|
749
753
|
renderNow(camera?: Camera) {
|
|
@@ -23,7 +23,10 @@ import {
|
|
|
23
23
|
DecrementWrapStencilOp,
|
|
24
24
|
InvertStencilOp,
|
|
25
25
|
} from "three";
|
|
26
|
-
import { getParam } from "../engine_utils";
|
|
26
|
+
import { getParam, isDebugMode } from "../engine_utils";
|
|
27
|
+
import { showBalloonWarning } from "../debug";
|
|
28
|
+
import { isUsingInstancing } from "../engine_gameobject";
|
|
29
|
+
import { isLocalNetwork } from "../engine_networking_utils";
|
|
27
30
|
|
|
28
31
|
const debug = getParam("debugstencil");
|
|
29
32
|
|
|
@@ -62,6 +65,12 @@ export class NEEDLE_render_objects implements GLTFLoaderPlugin {
|
|
|
62
65
|
const stencil: StencilSettingsModel = settings[i];
|
|
63
66
|
if (matchesLayer(stencil.layer, obj)) {
|
|
64
67
|
if (debug) console.log(stencil);
|
|
68
|
+
setTimeout(() => {
|
|
69
|
+
if (isLocalNetwork() && isUsingInstancing(obj.gameObject)) {
|
|
70
|
+
showBalloonWarning("Stencil not supported on instanced objects");
|
|
71
|
+
console.warn("Stencil not supported on instanced objects", obj);
|
|
72
|
+
}
|
|
73
|
+
}, 500)
|
|
65
74
|
for (let i = 0; i < obj.sharedMaterials.length; i++) {
|
|
66
75
|
let mat = obj.sharedMaterials[i];
|
|
67
76
|
if (mat) {
|
|
@@ -9,7 +9,7 @@ import { SourceIdentifier } from "../engine_types";
|
|
|
9
9
|
import { ILight } from "../engine_types";
|
|
10
10
|
import { getWorldPosition } from "../engine_three_utils";
|
|
11
11
|
|
|
12
|
-
const debug = getParam("
|
|
12
|
+
const debug = getParam("debugcustomshader");
|
|
13
13
|
|
|
14
14
|
export const NEEDLE_TECHNIQUES_WEBGL_NAME = "NEEDLE_techniques_webgl";
|
|
15
15
|
|
|
@@ -524,8 +524,11 @@ export class NEEDLE_techniques_webgl implements GLTFLoaderPlugin {
|
|
|
524
524
|
console.warn("Missing/unassigned texture, fallback to white: " + uniformName)
|
|
525
525
|
break;
|
|
526
526
|
default:
|
|
527
|
+
if (uniformName === "unity_OrthoParams") {
|
|
527
528
|
|
|
528
|
-
|
|
529
|
+
}
|
|
530
|
+
else
|
|
531
|
+
console.warn("TODO: EXPECTED UNIFORM / fallback NOT SET: " + uniformName, techniqueUniforms[u]);
|
|
529
532
|
break;
|
|
530
533
|
}
|
|
531
534
|
}
|
|
@@ -50,55 +50,81 @@ export class Animator extends Behaviour {
|
|
|
50
50
|
return this._animatorController;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
this.runtimeAnimatorController?.Play(name, layer, normalizedTime, transitionDurationInSec);
|
|
55
|
-
}
|
|
53
|
+
// NOTE: the uppercase events have been deprecated because UnityEvent methods are all exported with lowercase first letter
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
/**@deprecated use play */
|
|
56
|
+
Play(name: string | number, layer: number = -1, normalizedTime: number = Number.NEGATIVE_INFINITY, transitionDurationInSec: number = 0) { this.play(name, layer, normalizedTime, transitionDurationInSec); }
|
|
57
|
+
play(name: string | number, layer: number = -1, normalizedTime: number = Number.NEGATIVE_INFINITY, transitionDurationInSec: number = 0) {
|
|
58
|
+
this.runtimeAnimatorController?.play(name, layer, normalizedTime, transitionDurationInSec);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
/**@deprecated use reset */
|
|
62
|
+
Reset() { this.reset(); }
|
|
63
|
+
reset() {
|
|
64
|
+
this._animatorController?.reset();
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
/**@deprecated use setBool */
|
|
68
|
+
SetBool(name: string | number, val: boolean) { this.setBool(name, val); }
|
|
69
|
+
setBool(name: string | number, value: boolean) {
|
|
70
|
+
this.runtimeAnimatorController?.setBool(name, value);
|
|
67
71
|
}
|
|
68
72
|
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
/**@deprecated use getBool */
|
|
74
|
+
GetBool(name: string | number) { return this.getBool(name); }
|
|
75
|
+
getBool(name: string | number): boolean {
|
|
76
|
+
return this.runtimeAnimatorController?.getBool(name) ?? false;
|
|
71
77
|
}
|
|
72
78
|
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
/**@deprecated use setFloat */
|
|
80
|
+
SetFloat(name: string | number, val: number) { this.setFloat(name, val); }
|
|
81
|
+
setFloat(name: string | number, val: number) {
|
|
82
|
+
this.runtimeAnimatorController?.setFloat(name, val);
|
|
75
83
|
}
|
|
76
84
|
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
/**@deprecated use getFloat */
|
|
86
|
+
GetFloat(name: string | number) { return this.getFloat(name); }
|
|
87
|
+
getFloat(name: string | number): number {
|
|
88
|
+
return this.runtimeAnimatorController?.getFloat(name) ?? -1;
|
|
79
89
|
}
|
|
80
90
|
|
|
81
|
-
|
|
82
|
-
|
|
91
|
+
/**@deprecated use setInteger */
|
|
92
|
+
SetInteger(name: string | number, val: number) { this.setInteger(name, val); }
|
|
93
|
+
setInteger(name: string | number, val: number) {
|
|
94
|
+
this.runtimeAnimatorController?.setInteger(name, val);
|
|
83
95
|
}
|
|
84
96
|
|
|
85
|
-
|
|
86
|
-
|
|
97
|
+
/**@deprecated use getInteger */
|
|
98
|
+
GetInteger(name: string | number) { return this.getInteger(name); }
|
|
99
|
+
getInteger(name: string | number): number {
|
|
100
|
+
return this.runtimeAnimatorController?.getInteger(name) ?? -1;
|
|
87
101
|
}
|
|
88
102
|
|
|
89
|
-
|
|
90
|
-
|
|
103
|
+
/**@deprecated use setTrigger */
|
|
104
|
+
SetTrigger(name: string | number) { this.setTrigger(name); }
|
|
105
|
+
setTrigger(name: string | number) {
|
|
106
|
+
console.log("name", name);
|
|
107
|
+
this.runtimeAnimatorController?.setTrigger(name);
|
|
91
108
|
}
|
|
92
109
|
|
|
93
|
-
|
|
94
|
-
|
|
110
|
+
/**@deprecated use resetTrigger */
|
|
111
|
+
ResetTrigger(name: string | number) { this.resetTrigger(name); }
|
|
112
|
+
resetTrigger(name: string | number) {
|
|
113
|
+
this.runtimeAnimatorController?.resetTrigger(name);
|
|
95
114
|
}
|
|
96
115
|
|
|
116
|
+
/**@deprecated use isInTransition */
|
|
117
|
+
IsInTransition() { return this.isInTransition(); }
|
|
118
|
+
isInTransition(): boolean {
|
|
119
|
+
return this.runtimeAnimatorController?.isInTransition() ?? false;
|
|
120
|
+
}
|
|
97
121
|
|
|
98
|
-
|
|
122
|
+
/**@deprecated use setSpeed */
|
|
123
|
+
SetSpeed(speed: number) { return this.setSpeed(speed); }
|
|
124
|
+
setSpeed(speed: number) {
|
|
99
125
|
if (speed === this.speed) return;
|
|
100
126
|
this.speed = speed;
|
|
101
|
-
this._animatorController?.
|
|
127
|
+
this._animatorController?.setSpeed(speed);
|
|
102
128
|
}
|
|
103
129
|
|
|
104
130
|
set minMaxSpeed(minMax: { x: number, y: number }) {
|
|
@@ -130,7 +156,7 @@ export class Animator extends Behaviour {
|
|
|
130
156
|
this.runtimeAnimatorController = clone;
|
|
131
157
|
console.assert(this.runtimeAnimatorController === clone);
|
|
132
158
|
this.runtimeAnimatorController.bind(this);
|
|
133
|
-
this.runtimeAnimatorController.
|
|
159
|
+
this.runtimeAnimatorController.setSpeed(this.speed);
|
|
134
160
|
this.runtimeAnimatorController.normalizedStartOffset = this.normalizedStartOffset;
|
|
135
161
|
}
|
|
136
162
|
else console.warn("Could not clone animator controller", this.runtimeAnimatorController);
|
|
@@ -139,7 +165,7 @@ export class Animator extends Behaviour {
|
|
|
139
165
|
|
|
140
166
|
onDisable() {
|
|
141
167
|
if (!this.keepAnimatorControllerStateOnDisable)
|
|
142
|
-
this._animatorController?.
|
|
168
|
+
this._animatorController?.reset();
|
|
143
169
|
}
|
|
144
170
|
|
|
145
171
|
onBeforeRender() {
|
|
@@ -14,7 +14,7 @@ const debugRootMotion = getParam("debugrootmotion");
|
|
|
14
14
|
|
|
15
15
|
export class AnimatorController {
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
play(name: string | number, layerIndex: number = -1, normalizedTime: number = Number.NEGATIVE_INFINITY, durationInSec: number = 0) {
|
|
18
18
|
if (layerIndex < 0) layerIndex = 0;
|
|
19
19
|
else if (layerIndex >= this.model.layers.length) {
|
|
20
20
|
console.warn("invalid layer");
|
|
@@ -33,61 +33,63 @@ export class AnimatorController {
|
|
|
33
33
|
console.warn("Could not find " + name + " to play");
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
reset() {
|
|
37
37
|
this.setStartTransition();
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
setBool(name: string | number, value: boolean) {
|
|
41
41
|
const key = typeof name === "string" ? "name" : "hash";
|
|
42
42
|
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = value);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
getBool(name: string | number): boolean {
|
|
46
46
|
const key = typeof name === "string" ? "name" : "hash";
|
|
47
47
|
return this.model?.parameters?.find(p => p[key] === name)?.value as boolean ?? false;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
setFloat(name: string | number, val: number) {
|
|
51
51
|
const key = typeof name === "string" ? "name" : "hash";
|
|
52
52
|
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = val);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
getFloat(name: string | number): number {
|
|
56
56
|
const key = typeof name === "string" ? "name" : "hash";
|
|
57
57
|
return this.model?.parameters?.find(p => p[key] === name)?.value as number ?? 0;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
setInteger(name: string | number, val: number) {
|
|
61
61
|
const key = typeof name === "string" ? "name" : "hash";
|
|
62
62
|
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = val);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
getInteger(name: string | number): number {
|
|
66
66
|
const key = typeof name === "string" ? "name" : "hash";
|
|
67
67
|
return this.model?.parameters?.find(p => p[key] === name)?.value as number ?? 0;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
setTrigger(name: string | number) {
|
|
71
71
|
if (debug)
|
|
72
72
|
console.log("SET TRIGGER", name);
|
|
73
73
|
const key = typeof name === "string" ? "name" : "hash";
|
|
74
74
|
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = true);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
resetTrigger(name: string | number) {
|
|
78
78
|
const key = typeof name === "string" ? "name" : "hash";
|
|
79
79
|
return this.model?.parameters?.filter(p => p[key] === name).forEach(p => p.value = false);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
isInTransition(): boolean {
|
|
83
83
|
return this._activeStates.length > 1;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
setSpeed(speed: number) {
|
|
87
87
|
this._speed = speed;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
/**@deprecated use findState */
|
|
91
|
+
FindState(name: string | undefined | null): State | null { return this.findState(name); }
|
|
92
|
+
findState(name: string | undefined | null): State | null {
|
|
91
93
|
if (!name) return null;
|
|
92
94
|
if (Array.isArray(this.model.layers)) {
|
|
93
95
|
for (const layer of this.model.layers) {
|
|
@@ -86,6 +86,9 @@ export class CharacterControllerInput extends Behaviour {
|
|
|
86
86
|
@serializable()
|
|
87
87
|
jumpForce: number = 1;
|
|
88
88
|
|
|
89
|
+
@serializable()
|
|
90
|
+
doubleJumpForce: number = 2;
|
|
91
|
+
|
|
89
92
|
@serializable(Animator)
|
|
90
93
|
animator?: Animator;
|
|
91
94
|
|
|
@@ -106,7 +109,7 @@ export class CharacterControllerInput extends Behaviour {
|
|
|
106
109
|
|
|
107
110
|
if (this.controller?.isGrounded) {
|
|
108
111
|
this._jumpCount = 0;
|
|
109
|
-
this.animator?.
|
|
112
|
+
if (this.doubleJumpForce > 0) this.animator?.setBool("doubleJump", false);
|
|
110
113
|
}
|
|
111
114
|
|
|
112
115
|
const forward = this.context.input.isKeyPressed("w");
|
|
@@ -121,8 +124,8 @@ export class CharacterControllerInput extends Behaviour {
|
|
|
121
124
|
this._currentSpeed.z += step * this.movementSpeed * this.context.time.deltaTime;
|
|
122
125
|
|
|
123
126
|
// if (!this.controller || this.controller.isGrounded)
|
|
124
|
-
this.animator?.
|
|
125
|
-
this.animator?.
|
|
127
|
+
this.animator?.setBool("running", step != 0);
|
|
128
|
+
this.animator?.setBool("jumping", this.controller?.isGrounded === true && jump);
|
|
126
129
|
|
|
127
130
|
this._temp.copy(this._currentSpeed);
|
|
128
131
|
this._temp.applyQuaternion(this.gameObject.quaternion);
|
|
@@ -146,9 +149,9 @@ export class CharacterControllerInput extends Behaviour {
|
|
|
146
149
|
|
|
147
150
|
if (this.controller && jump && this.jumpForce > 0) {
|
|
148
151
|
let canJump = this.controller?.isGrounded;
|
|
149
|
-
if (!this.controller?.isGrounded && this._jumpCount === 1) {
|
|
152
|
+
if (this.doubleJumpForce > 0 && !this.controller?.isGrounded && this._jumpCount === 1) {
|
|
150
153
|
canJump = true;
|
|
151
|
-
this.animator?.
|
|
154
|
+
this.animator?.setBool("doubleJump", true);
|
|
152
155
|
}
|
|
153
156
|
|
|
154
157
|
if (canJump) {
|
|
@@ -156,8 +159,8 @@ export class CharacterControllerInput extends Behaviour {
|
|
|
156
159
|
// TODO: factor in mass
|
|
157
160
|
const rb = this.controller.rigidbody;
|
|
158
161
|
// const fullJumpHoldLength = .1;
|
|
159
|
-
const factor = this._jumpCount === 2 ?
|
|
160
|
-
rb.applyImpulse(new Vector3(0, 1, 0).multiplyScalar(
|
|
162
|
+
const factor = this._jumpCount === 2 ? this.doubleJumpForce : this.jumpForce;// Mathf.clamp((this.context.time.time - this._jumpDownTime), 0, fullJumpHoldLength) / fullJumpHoldLength;
|
|
163
|
+
rb.applyImpulse(new Vector3(0, 1, 0).multiplyScalar(factor));
|
|
161
164
|
}
|
|
162
165
|
}
|
|
163
166
|
|
|
@@ -174,10 +177,10 @@ export class CharacterControllerInput extends Behaviour {
|
|
|
174
177
|
const hits = this.context.physics.raycast(this._raycastOptions);
|
|
175
178
|
this.gameObject.layers.set(currentLayer);
|
|
176
179
|
if ((hits.length && hits[0].distance > 2 || verticalSpeed < -10)) {
|
|
177
|
-
this.animator?.
|
|
180
|
+
this.animator?.setBool("falling", true);
|
|
178
181
|
}
|
|
179
182
|
}
|
|
180
|
-
else this.animator?.
|
|
183
|
+
else this.animator?.setBool("falling", false);
|
|
181
184
|
}
|
|
182
185
|
}
|
|
183
186
|
|