@needle-tools/engine 4.9.0 → 4.9.2
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 +4 -0
- package/dist/{needle-engine.bundle-B1gr_nQ0.min.js → needle-engine.bundle-DwspSk2O.min.js} +95 -95
- package/dist/{needle-engine.bundle-DrlDKOar.umd.cjs → needle-engine.bundle-WLYWw5OF.umd.cjs} +89 -89
- package/dist/{needle-engine.bundle-BikYBC35.js → needle-engine.bundle-XBRfMDwo.js} +1992 -1952
- package/dist/needle-engine.js +2 -2
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{vendor-8le8g4MS.umd.cjs → vendor-BtJpSuCj.umd.cjs} +1 -1
- package/dist/{vendor-yDFiCnCw.min.js → vendor-XJ9xiwrv.min.js} +1 -1
- package/dist/{vendor-Msb9AgYE.js → vendor-k9i6CeGi.js} +871 -870
- package/lib/engine/engine_gameobject.d.ts +7 -7
- package/lib/engine/engine_gameobject.js +88 -27
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_networking_instantiate.js +23 -6
- package/lib/engine/engine_networking_instantiate.js.map +1 -1
- package/lib/engine/engine_serialization_core.d.ts +2 -2
- package/lib/engine/engine_serialization_core.js +7 -7
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_serialization_decorator.js +2 -1
- package/lib/engine/engine_serialization_decorator.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/Renderer.d.ts +7 -6
- package/lib/engine-components/Renderer.js +3 -0
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/web/ScrollFollow.d.ts +19 -1
- package/lib/engine-components/web/ScrollFollow.js +20 -1
- package/lib/engine-components/web/ScrollFollow.js.map +1 -1
- package/package.json +2 -2
- package/plugins/vite/build.js +3 -0
- package/src/engine/engine_gameobject.ts +105 -38
- package/src/engine/engine_networking_instantiate.ts +21 -6
- package/src/engine/engine_serialization_core.ts +9 -9
- package/src/engine/engine_serialization_decorator.ts +2 -1
- package/src/engine-components/Animation.ts +1 -1
- package/src/engine-components/Renderer.ts +16 -10
- package/src/engine-components/web/ScrollFollow.ts +20 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Object3D, Quaternion, Vector3 } from "three";
|
|
1
|
+
import { Euler, Object3D, Quaternion, Vector3 } from "three";
|
|
2
2
|
// https://github.com/uuidjs/uuid
|
|
3
3
|
// v5 takes string and namespace
|
|
4
4
|
import { v5 } from 'uuid';
|
|
@@ -254,12 +254,27 @@ export function syncInstantiate(object: GameObject | Object3D, opts: SyncInstant
|
|
|
254
254
|
if (opts.deleteOnDisconnect === true)
|
|
255
255
|
model.deleteStateOnDisconnect = true;
|
|
256
256
|
if (originalOpts) {
|
|
257
|
-
if (originalOpts.position)
|
|
258
|
-
|
|
259
|
-
|
|
257
|
+
if (originalOpts.position) {
|
|
258
|
+
if (Array.isArray(originalOpts.position)) {
|
|
259
|
+
model.position = { x: originalOpts.position[0], y: originalOpts.position[1], z: originalOpts.position[2] };
|
|
260
|
+
}
|
|
261
|
+
else model.position = { x: originalOpts.position.x, y: originalOpts.position.y, z: originalOpts.position.z };
|
|
262
|
+
}
|
|
263
|
+
if (originalOpts.rotation) {
|
|
264
|
+
if (originalOpts.rotation instanceof Euler) {
|
|
265
|
+
originalOpts.rotation = new Quaternion().setFromEuler(originalOpts.rotation);
|
|
266
|
+
}
|
|
267
|
+
else if (originalOpts.rotation instanceof Array) {
|
|
268
|
+
originalOpts.rotation = new Quaternion().fromArray(originalOpts.rotation);
|
|
269
|
+
}
|
|
260
270
|
model.rotation = { x: originalOpts.rotation.x, y: originalOpts.rotation.y, z: originalOpts.rotation.z, w: originalOpts.rotation.w };
|
|
261
|
-
|
|
262
|
-
|
|
271
|
+
}
|
|
272
|
+
if (originalOpts.scale) {
|
|
273
|
+
if (Array.isArray(originalOpts.scale)) {
|
|
274
|
+
model.scale = { x: originalOpts.scale[0], y: originalOpts.scale[1], z: originalOpts.scale[2] };
|
|
275
|
+
}
|
|
276
|
+
else model.scale = { x: originalOpts.scale.x, y: originalOpts.scale.y, z: originalOpts.scale.z };
|
|
277
|
+
}
|
|
263
278
|
}
|
|
264
279
|
if (!model.position)
|
|
265
280
|
model.position = { x: go.position.x, y: go.position.y, z: go.position.z };
|
|
@@ -658,10 +658,10 @@ export const $isAssigningProperties = Symbol("assigned component properties");
|
|
|
658
658
|
* @param key the key that is being assigned
|
|
659
659
|
* @param value the value that is being assigned
|
|
660
660
|
*/
|
|
661
|
-
type
|
|
661
|
+
type AssignedCallback = (source: object, key: string, oldValue: any, newValue: any) => any;
|
|
662
662
|
|
|
663
663
|
/** Object.assign behaviour but check if property is writeable (e.g. getter only properties are skipped) */
|
|
664
|
-
export function assign(target: any, source: any, info?: ImplementationInformation, opts?: {
|
|
664
|
+
export function assign(target: any, source: any, info?: ImplementationInformation, opts?: { onAssigned?: AssignedCallback }) {
|
|
665
665
|
if (source === undefined || source === null) return;
|
|
666
666
|
if (target === undefined || target === null) return;
|
|
667
667
|
|
|
@@ -699,13 +699,13 @@ export function assign(target: any, source: any, info?: ImplementationInformatio
|
|
|
699
699
|
// arrow functions are defined as properties on the object
|
|
700
700
|
continue;
|
|
701
701
|
}
|
|
702
|
-
if (!desc || desc.writable === true) {
|
|
703
|
-
const
|
|
704
|
-
target[key]
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
702
|
+
if (!desc || desc.writable === true || desc.set !== undefined) {
|
|
703
|
+
const newValue = source[key];
|
|
704
|
+
const oldValue = target[key];
|
|
705
|
+
target[key] = newValue;
|
|
706
|
+
if (opts?.onAssigned) {
|
|
707
|
+
opts.onAssigned(target, key, oldValue, newValue);
|
|
708
|
+
}
|
|
709
709
|
}
|
|
710
710
|
}
|
|
711
711
|
delete target[$isAssigningProperties];
|
|
@@ -27,7 +27,8 @@ export const serializable = function <T>(type?: Constructor<T> | null | Array<Co
|
|
|
27
27
|
|
|
28
28
|
return function (_target: any, _propertyKey: string | { name: string }) {
|
|
29
29
|
if (!_target) {
|
|
30
|
-
|
|
30
|
+
const propertyName = typeof _propertyKey === 'string' ? _propertyKey : _propertyKey.name;
|
|
31
|
+
console.warn(`@serializable without a target at '${propertyName}'.`);
|
|
31
32
|
return;
|
|
32
33
|
}
|
|
33
34
|
// The _propertyKey parameter is a string in TS4 with experimentalDecorators
|
|
@@ -181,7 +181,7 @@ export class Animation extends Behaviour implements IAnimationComponent {
|
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
get animations(): AnimationClip[] {
|
|
184
|
-
return this.gameObject
|
|
184
|
+
return this.gameObject?.animations || this._tempAnimationsArray || [];
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
private mixer: AnimationMixer | undefined = undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getRaycastMesh } from "@needle-tools/gltf-progressive";
|
|
2
|
-
import { AxesHelper, Material, Mesh, Object3D, SkinnedMesh, Texture, Vector4 } from "three";
|
|
2
|
+
import { AxesHelper, Material, Mesh, MeshBasicMaterial, MeshPhysicalMaterial, MeshStandardMaterial, Object3D, RawShaderMaterial, ShaderMaterial, SkinnedMesh, Texture, Vector4 } from "three";
|
|
3
3
|
|
|
4
4
|
import { showBalloonWarning } from "../engine/debug/index.js";
|
|
5
5
|
import { getComponent, getOrAddComponent } from "../engine/engine_components.js";
|
|
@@ -48,6 +48,8 @@ export enum RenderState {
|
|
|
48
48
|
Front = 2,
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
type SharedMaterial = (Material & Partial<MeshStandardMaterial> & Partial<MeshPhysicalMaterial> & Partial<ShaderMaterial> & Partial<RawShaderMaterial>);
|
|
52
|
+
|
|
51
53
|
|
|
52
54
|
// support sharedMaterials[index] assigning materials directly to the objects
|
|
53
55
|
class SharedMaterialArray implements ISharedMaterials {
|
|
@@ -185,7 +187,7 @@ class SharedMaterialArray implements ISharedMaterials {
|
|
|
185
187
|
this.changed = true;
|
|
186
188
|
}
|
|
187
189
|
|
|
188
|
-
private getMaterial(index: number):
|
|
190
|
+
private getMaterial(index: number): SharedMaterial | null {
|
|
189
191
|
index = this.resolveIndex(index);
|
|
190
192
|
if (index < 0) return null;
|
|
191
193
|
const obj = this._targets;
|
|
@@ -302,11 +304,11 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
302
304
|
return this._sharedMeshes;
|
|
303
305
|
}
|
|
304
306
|
|
|
305
|
-
get sharedMaterial():
|
|
306
|
-
return this.sharedMaterials[0];
|
|
307
|
+
get sharedMaterial(): SharedMaterial {
|
|
308
|
+
return this.sharedMaterials[0] as SharedMaterial;
|
|
307
309
|
}
|
|
308
310
|
|
|
309
|
-
set sharedMaterial(mat:
|
|
311
|
+
set sharedMaterial(mat: SharedMaterial) {
|
|
310
312
|
const cur = this.sharedMaterials[0];
|
|
311
313
|
if (cur === mat) return;
|
|
312
314
|
this.sharedMaterials[0] = mat;
|
|
@@ -314,12 +316,12 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
314
316
|
}
|
|
315
317
|
|
|
316
318
|
/**@deprecated please use sharedMaterial */
|
|
317
|
-
get material():
|
|
318
|
-
return this.sharedMaterials[0];
|
|
319
|
+
get material(): SharedMaterial {
|
|
320
|
+
return this.sharedMaterials[0] as SharedMaterial;
|
|
319
321
|
}
|
|
320
322
|
|
|
321
323
|
/**@deprecated please use sharedMaterial */
|
|
322
|
-
set material(mat:
|
|
324
|
+
set material(mat: SharedMaterial) {
|
|
323
325
|
this.sharedMaterial = mat;
|
|
324
326
|
}
|
|
325
327
|
|
|
@@ -329,10 +331,10 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
329
331
|
private _probeAnchorLastFrame?: Object3D;
|
|
330
332
|
|
|
331
333
|
// this is just available during deserialization
|
|
332
|
-
private set sharedMaterials(_val: Array<
|
|
334
|
+
private set sharedMaterials(_val: Array<SharedMaterial | null>) {
|
|
333
335
|
// TODO: elements in the array might be missing at the moment which leads to problems if an index is serialized
|
|
334
336
|
if (!this._originalMaterials) {
|
|
335
|
-
this._originalMaterials = _val as
|
|
337
|
+
this._originalMaterials = _val as SharedMaterial[];
|
|
336
338
|
}
|
|
337
339
|
else if (_val) {
|
|
338
340
|
let didWarn = false;
|
|
@@ -353,6 +355,10 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
353
355
|
|
|
354
356
|
//@ts-ignore
|
|
355
357
|
get sharedMaterials(): SharedMaterialArray {
|
|
358
|
+
|
|
359
|
+
// @ts-ignore during deserialization code might access this property *before* the setter and then create an empty array
|
|
360
|
+
if(!this.__didAwake) return null;
|
|
361
|
+
|
|
356
362
|
if (!this._sharedMaterials || !this._sharedMaterials.is(this)) {
|
|
357
363
|
if (!this._originalMaterials) this._originalMaterials = [];
|
|
358
364
|
this._sharedMaterials = new SharedMaterialArray(this, this._originalMaterials);
|
|
@@ -28,18 +28,36 @@ type ScrollFollowEvent = {
|
|
|
28
28
|
* The ScrollFollow component allows you to link the scroll position of the page (or a specific element) to one or more target objects.
|
|
29
29
|
* This can be used to create scroll-based animations, audio playback, or other effects. For example you can link the scroll position to a timeline (PlayableDirector) to create scroll-based storytelling effects or to an Animator component to change the animation state based on scroll.
|
|
30
30
|
*
|
|
31
|
+
* Assign {@link target} objects to the component to have them updated based on the current scroll position (check the 'target' property for supported types).
|
|
32
|
+
*
|
|
31
33
|
* @link Example at https://scrollytelling-2-z23hmxby7c6x-u30ld.needle.run/
|
|
34
|
+
* @link Template at https://github.com/needle-engine/scrollytelling-template
|
|
35
|
+
*
|
|
36
|
+
* ## How to use with an Animator
|
|
37
|
+
* 1. Create an Animator component and set up a float parameter named "scroll".
|
|
38
|
+
* 2. Create transitions between animation states based on the "scroll" parameter (e.g. from 0 to 1).
|
|
39
|
+
* 3. Add a ScrollFollow component to the same GameObject or another GameObject in the scene.
|
|
40
|
+
* 4. Assign the Animator component to the ScrollFollow's target property.
|
|
41
|
+
*
|
|
42
|
+
* ## How to use with a PlayableDirector (timeline)
|
|
43
|
+
* 1. Create a PlayableDirector component and set up a timeline asset.
|
|
44
|
+
* 2. Add a ScrollFollow component to the same GameObject or another GameObject in the scene.
|
|
45
|
+
* 3. Assign the PlayableDirector component to the ScrollFollow's target property.
|
|
46
|
+
* 4. The timeline will now scrub based on the scroll position of the page.
|
|
32
47
|
*/
|
|
33
48
|
export class ScrollFollow extends Behaviour {
|
|
34
49
|
|
|
35
50
|
/**
|
|
36
|
-
* Target object(s) to follow the scroll position of the page.
|
|
51
|
+
* Target object(s) to follow the scroll position of the page.
|
|
37
52
|
*
|
|
38
53
|
* Supported target types:
|
|
39
54
|
* - PlayableDirector (timeline), the scroll position will be mapped to the timeline time
|
|
40
55
|
* - Animator, the scroll position will be set to a float parameter named "scroll"
|
|
41
56
|
* - Animation, the scroll position will be mapped to the animation time
|
|
42
57
|
* - AudioSource, the scroll position will be mapped to the audio time
|
|
58
|
+
* - SplineWalker, the scroll position will be mapped to the position01 property
|
|
59
|
+
* - Light, the scroll position will be mapped to the intensity property
|
|
60
|
+
* - Object3D, the object will move vertically based on the scroll position
|
|
43
61
|
* - Any object with a `scroll` property (number or function)
|
|
44
62
|
*/
|
|
45
63
|
@serializable([Behaviour, Object3D])
|
|
@@ -204,6 +222,7 @@ export class ScrollFollow extends Behaviour {
|
|
|
204
222
|
}
|
|
205
223
|
const bounds = target["needle:scrollbounds"] as Box3;
|
|
206
224
|
if (bounds) {
|
|
225
|
+
// TODO: remap position to use upper screen edge and lower edge instead of center
|
|
207
226
|
target.position.y = -bounds.min.y - value * (bounds.max.y - bounds.min.y);
|
|
208
227
|
}
|
|
209
228
|
}
|