@needle-tools/engine 4.9.0-alpha.4 → 4.9.0-beta

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.
Files changed (48) hide show
  1. package/components.needle.json +1 -1
  2. package/dist/{needle-engine.bundle-HZA484FG.js → needle-engine.bundle-BYCLCf3u.js} +5290 -5097
  3. package/dist/{needle-engine.bundle-Bs7Jz8Xi.min.js → needle-engine.bundle-D5_A77oU.min.js} +131 -131
  4. package/dist/{needle-engine.bundle-Bi2IbHHS.umd.cjs → needle-engine.bundle-YbxLeXEH.umd.cjs} +132 -132
  5. package/dist/needle-engine.js +556 -552
  6. package/dist/needle-engine.min.js +1 -1
  7. package/dist/needle-engine.umd.cjs +1 -1
  8. package/lib/engine/codegen/register_types.js +8 -0
  9. package/lib/engine/codegen/register_types.js.map +1 -1
  10. package/lib/engine/engine_physics_rapier.js +8 -8
  11. package/lib/engine/engine_physics_rapier.js.map +1 -1
  12. package/lib/engine-components/Animation.d.ts +1 -0
  13. package/lib/engine-components/Animation.js +9 -0
  14. package/lib/engine-components/Animation.js.map +1 -1
  15. package/lib/engine-components/EventTrigger.js.map +1 -1
  16. package/lib/engine-components/api.d.ts +1 -0
  17. package/lib/engine-components/api.js +1 -0
  18. package/lib/engine-components/api.js.map +1 -1
  19. package/lib/engine-components/codegen/components.d.ts +4 -0
  20. package/lib/engine-components/codegen/components.js +4 -0
  21. package/lib/engine-components/codegen/components.js.map +1 -1
  22. package/lib/engine-components/physics/Attractor.d.ts +8 -0
  23. package/lib/engine-components/physics/Attractor.js +42 -0
  24. package/lib/engine-components/physics/Attractor.js.map +1 -0
  25. package/lib/engine-components/web/Clickthrough.d.ts +20 -0
  26. package/lib/engine-components/web/Clickthrough.js +59 -0
  27. package/lib/engine-components/web/Clickthrough.js.map +1 -0
  28. package/lib/engine-components/web/CursorFollow.d.ts +12 -0
  29. package/lib/engine-components/web/CursorFollow.js +46 -0
  30. package/lib/engine-components/web/CursorFollow.js.map +1 -0
  31. package/lib/engine-components/web/ScrollFollow.d.ts +52 -0
  32. package/lib/engine-components/web/ScrollFollow.js +157 -0
  33. package/lib/engine-components/web/ScrollFollow.js.map +1 -0
  34. package/lib/engine-components/web/index.d.ts +3 -0
  35. package/lib/engine-components/web/index.js +4 -0
  36. package/lib/engine-components/web/index.js.map +1 -0
  37. package/package.json +2 -2
  38. package/src/engine/codegen/register_types.ts +8 -0
  39. package/src/engine/engine_physics_rapier.ts +11 -11
  40. package/src/engine-components/Animation.ts +9 -0
  41. package/src/engine-components/EventTrigger.ts +0 -1
  42. package/src/engine-components/api.ts +1 -0
  43. package/src/engine-components/codegen/components.ts +4 -0
  44. package/src/engine-components/physics/Attractor.ts +35 -0
  45. package/src/engine-components/web/Clickthrough.ts +64 -0
  46. package/src/engine-components/web/CursorFollow.ts +49 -0
  47. package/src/engine-components/web/ScrollFollow.ts +173 -0
  48. package/src/engine-components/web/index.ts +3 -0
@@ -0,0 +1,173 @@
1
+ import { Object3D } from "three";
2
+ import { serializable } from "../../engine/engine_serialization.js";
3
+ import { Mathf } from "../../engine/engine_math.js";
4
+ import { Behaviour } from "../Component.js";
5
+ import { PlayableDirector } from "../timeline/PlayableDirector.js";
6
+ import { EventList } from "../EventList.js";
7
+ import { Animation } from "../Animation.js";
8
+ import { AudioSource } from "../AudioSource.js";
9
+
10
+ type ScrollFollowEvent = {
11
+ /** Event type */
12
+ type: "change",
13
+ /** Current scroll value */
14
+ value: number,
15
+ /** ScrollFollow component that raised the event */
16
+ component: ScrollFollow,
17
+ /** Call to prevent invocation of default (e.g. updating targets) */
18
+ preventDefault: () => void,
19
+ defaultPrevented: boolean,
20
+ }
21
+
22
+ export class ScrollFollow extends Behaviour {
23
+
24
+ /**
25
+ * Target object(s) to follow the scroll position of the page. If null, the main camera is used.
26
+ */
27
+ @serializable([Behaviour, Object3D])
28
+ target: object[] | object | null = null;
29
+
30
+ /**
31
+ * Damping for the movement, set to 0 for instant movement
32
+ * @default 0
33
+ */
34
+ @serializable()
35
+ damping: number = 0;
36
+
37
+ /**
38
+ * If set, the scroll position will be read from the specified element instead of the window.
39
+ * Use a CSS selector to specify the element, e.g. `#my-scrollable-div` or `.scroll-container`.
40
+ */
41
+ @serializable()
42
+ htmlSelector: string | null = null;
43
+
44
+ @serializable()
45
+ private mode: "window" = "window";
46
+
47
+ /**
48
+ * Event fired when the scroll position changes
49
+ */
50
+ @serializable(EventList)
51
+ changed: EventList<ScrollFollowEvent> = new EventList<ScrollFollowEvent>();
52
+
53
+ /**
54
+ * Current scroll value in "pages" (0 = top of page, 1 = bottom of page)
55
+ */
56
+ get currentValue() {
57
+ return this.current_value;
58
+ }
59
+
60
+ private current_value: number = 0;
61
+ private target_value: number = 0;
62
+ private applied_value: number = -1;
63
+
64
+ /** @internal */
65
+ onEnable() {
66
+ window.addEventListener("wheel", this.updateCurrentScrollValue, { passive: true });
67
+ this.applied_value = -1;
68
+ }
69
+
70
+ /** @internal */
71
+ onDisable() {
72
+ window.removeEventListener("wheel", this.updateCurrentScrollValue);
73
+ }
74
+
75
+ /** @internal */
76
+ lateUpdate() {
77
+
78
+ this.updateCurrentScrollValue();
79
+
80
+ // apply damping if any
81
+ if (this.damping > 0) {
82
+ this.current_value = Mathf.lerp(this.current_value, this.target_value, this.context.time.deltaTime / this.damping);
83
+ }
84
+ else {
85
+ this.current_value = this.target_value;
86
+ }
87
+
88
+ if (this.current_value !== this.applied_value) {
89
+ this.applied_value = this.current_value;
90
+
91
+ let defaultPrevented = false;
92
+ if (this.changed.listenerCount > 0) {
93
+ // fire change event
94
+ const event: ScrollFollowEvent = {
95
+ type: "change",
96
+ value: this.current_value,
97
+ component: this,
98
+ preventDefault: () => { event.defaultPrevented = true; },
99
+ defaultPrevented: false,
100
+ };
101
+ this.changed.invoke(event);
102
+ defaultPrevented = event.defaultPrevented;
103
+ }
104
+
105
+ // if not prevented apply scroll
106
+ if (!defaultPrevented) {
107
+
108
+ // apply scroll to target(s)
109
+ if (Array.isArray(this.target)) {
110
+ this.target.forEach(t => t && this.applyScroll(t));
111
+ }
112
+ else if (this.target) {
113
+ this.applyScroll(this.target);
114
+ }
115
+ }
116
+ }
117
+ }
118
+
119
+ private _lastSelectorValue: string | null = null;
120
+ private _lastSelectorElement: Element | null = null;
121
+
122
+ private updateCurrentScrollValue = () => {
123
+
124
+ switch (this.mode) {
125
+ case "window":
126
+ if (this.htmlSelector?.length) {
127
+ if (this.htmlSelector !== this._lastSelectorValue) {
128
+ this._lastSelectorElement = document.querySelector(this.htmlSelector);
129
+ this._lastSelectorValue = this.htmlSelector;
130
+ }
131
+ if (this._lastSelectorElement) {
132
+ const rect = this._lastSelectorElement.getBoundingClientRect();
133
+ this.target_value = -rect.top / (rect.height - window.innerHeight);
134
+ if (isNaN(this.target_value) || !isFinite(this.target_value)) this.target_value = 0;
135
+ break;
136
+ }
137
+ }
138
+ else {
139
+ this.target_value = window.scrollY / (document.body.scrollHeight - window.innerHeight);
140
+ }
141
+ if (isNaN(this.target_value) || !isFinite(this.target_value)) this.target_value = 0;
142
+ break;
143
+ }
144
+
145
+ }
146
+
147
+
148
+ private applyScroll(target: object) {
149
+
150
+ if (!target) return;
151
+
152
+ if (target instanceof PlayableDirector) {
153
+ target.time = this.current_value * target.duration;
154
+ if (!target.isPlaying) target.evaluate();
155
+ }
156
+ else if (target instanceof Animation) {
157
+ target.time = this.current_value * target.duration;
158
+ }
159
+ else if (target instanceof AudioSource) {
160
+ if (!target.duration) return;
161
+ target.time = this.current_value * target.duration;
162
+ }
163
+ else if ("scroll" in target) {
164
+ if (typeof target.scroll === "number") {
165
+ target.scroll = this.current_value;
166
+ }
167
+ else if (typeof target.scroll === "function") {
168
+ target.scroll(this.current_value);
169
+ }
170
+ }
171
+ }
172
+
173
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./Clickthrough.js";
2
+ export * from "./CursorFollow.js";
3
+ export * from "./ScrollFollow.js";