@zylem/behaviors 0.2.0
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/README.md +26 -0
- package/dist/behavior-system-DYbx-x_-.d.ts +307 -0
- package/dist/chunk-2C3Z5GE7.js +176 -0
- package/dist/chunk-2C3Z5GE7.js.map +1 -0
- package/dist/chunk-2CLT36VB.js +241 -0
- package/dist/chunk-2CLT36VB.js.map +1 -0
- package/dist/chunk-3PYGRHAL.js +35 -0
- package/dist/chunk-3PYGRHAL.js.map +1 -0
- package/dist/chunk-4I6E6DGV.js +212 -0
- package/dist/chunk-4I6E6DGV.js.map +1 -0
- package/dist/chunk-4URF65BR.js +44 -0
- package/dist/chunk-4URF65BR.js.map +1 -0
- package/dist/chunk-6C6NXNEW.js +38 -0
- package/dist/chunk-6C6NXNEW.js.map +1 -0
- package/dist/chunk-ARJWUNRE.js +431 -0
- package/dist/chunk-ARJWUNRE.js.map +1 -0
- package/dist/chunk-BXP4K7RF.js +1205 -0
- package/dist/chunk-BXP4K7RF.js.map +1 -0
- package/dist/chunk-DYLH6K7B.js +44 -0
- package/dist/chunk-DYLH6K7B.js.map +1 -0
- package/dist/chunk-EIWQM6U3.js +27 -0
- package/dist/chunk-EIWQM6U3.js.map +1 -0
- package/dist/chunk-EZNCCO4L.js +14 -0
- package/dist/chunk-EZNCCO4L.js.map +1 -0
- package/dist/chunk-F3KRX2V4.js +457 -0
- package/dist/chunk-F3KRX2V4.js.map +1 -0
- package/dist/chunk-FPTWVCPN.js +53 -0
- package/dist/chunk-FPTWVCPN.js.map +1 -0
- package/dist/chunk-GCNRXAKH.js +37 -0
- package/dist/chunk-GCNRXAKH.js.map +1 -0
- package/dist/chunk-GYURWCIQ.js +1985 -0
- package/dist/chunk-GYURWCIQ.js.map +1 -0
- package/dist/chunk-HZMY3TT4.js +244 -0
- package/dist/chunk-HZMY3TT4.js.map +1 -0
- package/dist/chunk-ID5QJYF5.js +50 -0
- package/dist/chunk-ID5QJYF5.js.map +1 -0
- package/dist/chunk-JAN34G6S.js +552 -0
- package/dist/chunk-JAN34G6S.js.map +1 -0
- package/dist/chunk-K3UNLQ7W.js +118 -0
- package/dist/chunk-K3UNLQ7W.js.map +1 -0
- package/dist/chunk-KDY5N6J4.js +82 -0
- package/dist/chunk-KDY5N6J4.js.map +1 -0
- package/dist/chunk-KOZUNIIE.js +413 -0
- package/dist/chunk-KOZUNIIE.js.map +1 -0
- package/dist/chunk-KS72RZHX.js +30 -0
- package/dist/chunk-KS72RZHX.js.map +1 -0
- package/dist/chunk-LD5SMIB3.js +32 -0
- package/dist/chunk-LD5SMIB3.js.map +1 -0
- package/dist/chunk-OHCPV2NT.js +86 -0
- package/dist/chunk-OHCPV2NT.js.map +1 -0
- package/dist/chunk-OYWFPIHF.js +115 -0
- package/dist/chunk-OYWFPIHF.js.map +1 -0
- package/dist/chunk-POZER3MQ.js +407 -0
- package/dist/chunk-POZER3MQ.js.map +1 -0
- package/dist/chunk-RTRVBEIB.js +56 -0
- package/dist/chunk-RTRVBEIB.js.map +1 -0
- package/dist/chunk-RTVRUNYR.js +29 -0
- package/dist/chunk-RTVRUNYR.js.map +1 -0
- package/dist/chunk-SS7ELMJ7.js +406 -0
- package/dist/chunk-SS7ELMJ7.js.map +1 -0
- package/dist/chunk-STCCNLPC.js +160 -0
- package/dist/chunk-STCCNLPC.js.map +1 -0
- package/dist/chunk-SVLNF434.js +261 -0
- package/dist/chunk-SVLNF434.js.map +1 -0
- package/dist/chunk-UYFOLI2X.js +24 -0
- package/dist/chunk-UYFOLI2X.js.map +1 -0
- package/dist/chunk-VAN4WW3F.js +67 -0
- package/dist/chunk-VAN4WW3F.js.map +1 -0
- package/dist/chunk-WOMHL23C.js +369 -0
- package/dist/chunk-WOMHL23C.js.map +1 -0
- package/dist/chunk-WWVD5DR5.js +120 -0
- package/dist/chunk-WWVD5DR5.js.map +1 -0
- package/dist/chunk-XG2YMCJW.js +201 -0
- package/dist/chunk-XG2YMCJW.js.map +1 -0
- package/dist/chunk-XIJNE67Y.js +210 -0
- package/dist/chunk-XIJNE67Y.js.map +1 -0
- package/dist/chunk-Y6UJOUE5.js +44 -0
- package/dist/chunk-Y6UJOUE5.js.map +1 -0
- package/dist/chunk-YUO6SKJD.js +348 -0
- package/dist/chunk-YUO6SKJD.js.map +1 -0
- package/dist/components--hjBMTnz.d.ts +120 -0
- package/dist/components-B29WHGQN.d.ts +39 -0
- package/dist/components-BWG1GkZA.d.ts +20 -0
- package/dist/components-XCpL6IYt.d.ts +18 -0
- package/dist/components-qWwOsvwh.d.ts +43 -0
- package/dist/cooldown.d.ts +116 -0
- package/dist/cooldown.js +20 -0
- package/dist/cooldown.js.map +1 -0
- package/dist/coordinators/boundary-ricochet-3d.d.ts +19 -0
- package/dist/coordinators/boundary-ricochet-3d.js +8 -0
- package/dist/coordinators/boundary-ricochet-3d.js.map +1 -0
- package/dist/coordinators/boundary-ricochet.d.ts +34 -0
- package/dist/coordinators/boundary-ricochet.js +8 -0
- package/dist/coordinators/boundary-ricochet.js.map +1 -0
- package/dist/coordinators/first-person-shooter.d.ts +35 -0
- package/dist/coordinators/first-person-shooter.js +9 -0
- package/dist/coordinators/first-person-shooter.js.map +1 -0
- package/dist/coordinators/multidirectional-space-shooter.d.ts +27 -0
- package/dist/coordinators/multidirectional-space-shooter.js +10 -0
- package/dist/coordinators/multidirectional-space-shooter.js.map +1 -0
- package/dist/coordinators/top-down-shooter.d.ts +27 -0
- package/dist/coordinators/top-down-shooter.js +10 -0
- package/dist/coordinators/top-down-shooter.js.map +1 -0
- package/dist/core.d.ts +25 -0
- package/dist/core.js +327 -0
- package/dist/core.js.map +1 -0
- package/dist/destructible-3d.d.ts +42 -0
- package/dist/destructible-3d.js +13 -0
- package/dist/destructible-3d.js.map +1 -0
- package/dist/destructible-prebake.d.ts +28 -0
- package/dist/destructible-prebake.js +23 -0
- package/dist/destructible-prebake.js.map +1 -0
- package/dist/entity-types-CmtQ-IBp.d.ts +15 -0
- package/dist/first-person-perspective-C9Mptl0-.d.ts +23 -0
- package/dist/first-person.d.ts +204 -0
- package/dist/first-person.js +27 -0
- package/dist/first-person.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +263 -0
- package/dist/index.js.map +1 -0
- package/dist/jumper-2d.d.ts +113 -0
- package/dist/jumper-2d.js +27 -0
- package/dist/jumper-2d.js.map +1 -0
- package/dist/jumper-3d.d.ts +164 -0
- package/dist/jumper-3d.js +29 -0
- package/dist/jumper-3d.js.map +1 -0
- package/dist/moveable-BCRpjAQb.d.ts +176 -0
- package/dist/particle-emitter/presets.d.ts +46 -0
- package/dist/particle-emitter/presets.js +15 -0
- package/dist/particle-emitter/presets.js.map +1 -0
- package/dist/particle-emitter.d.ts +78 -0
- package/dist/particle-emitter.js +15 -0
- package/dist/particle-emitter.js.map +1 -0
- package/dist/payload-BQzu-oY_.d.ts +89 -0
- package/dist/platformer-3d.d.ts +347 -0
- package/dist/platformer-3d.js +23 -0
- package/dist/platformer-3d.js.map +1 -0
- package/dist/ricochet-2d.d.ts +274 -0
- package/dist/ricochet-2d.js +16 -0
- package/dist/ricochet-2d.js.map +1 -0
- package/dist/ricochet-3d.d.ts +116 -0
- package/dist/ricochet-3d.js +16 -0
- package/dist/ricochet-3d.js.map +1 -0
- package/dist/runtime-2d.d.ts +2 -0
- package/dist/runtime-2d.js +32 -0
- package/dist/runtime-2d.js.map +1 -0
- package/dist/runtime-pong.d.ts +92 -0
- package/dist/runtime-pong.js +38 -0
- package/dist/runtime-pong.js.map +1 -0
- package/dist/screen-visibility.d.ts +74 -0
- package/dist/screen-visibility.js +10 -0
- package/dist/screen-visibility.js.map +1 -0
- package/dist/screen-wrap.d.ts +86 -0
- package/dist/screen-wrap.js +16 -0
- package/dist/screen-wrap.js.map +1 -0
- package/dist/shooter-2d.d.ts +77 -0
- package/dist/shooter-2d.js +12 -0
- package/dist/shooter-2d.js.map +1 -0
- package/dist/spark-DDlIg1nM.d.ts +148 -0
- package/dist/sync-state-machine-CZyspBpj.d.ts +16 -0
- package/dist/thruster.d.ts +132 -0
- package/dist/thruster.js +26 -0
- package/dist/thruster.js.map +1 -0
- package/dist/top-down-movement.d.ts +40 -0
- package/dist/top-down-movement.js +20 -0
- package/dist/top-down-movement.js.map +1 -0
- package/dist/use-behavior-D_82jAL3.d.ts +13 -0
- package/dist/vector-Bm65-FOG.d.ts +45 -0
- package/dist/world-boundary-2d.d.ts +141 -0
- package/dist/world-boundary-2d.js +21 -0
- package/dist/world-boundary-2d.js.map +1 -0
- package/dist/world-boundary-3d.d.ts +75 -0
- package/dist/world-boundary-3d.js +21 -0
- package/dist/world-boundary-3d.js.map +1 -0
- package/package.json +161 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineBehavior
|
|
3
|
+
} from "./chunk-EZNCCO4L.js";
|
|
4
|
+
|
|
5
|
+
// src/lib/behaviors/screen-visibility/screen-visibility.descriptor.ts
|
|
6
|
+
import {
|
|
7
|
+
Box3,
|
|
8
|
+
Frustum,
|
|
9
|
+
Matrix4,
|
|
10
|
+
Quaternion,
|
|
11
|
+
Vector3
|
|
12
|
+
} from "three";
|
|
13
|
+
|
|
14
|
+
// src/lib/behaviors/screen-visibility/screen-visibility-fsm.ts
|
|
15
|
+
var ScreenVisibilityFSM = class {
|
|
16
|
+
initialized = false;
|
|
17
|
+
visible = false;
|
|
18
|
+
justEntered = false;
|
|
19
|
+
justExited = false;
|
|
20
|
+
visibleCameraNames = [];
|
|
21
|
+
update(visible, visibleCameraNames) {
|
|
22
|
+
const wasVisible = this.visible;
|
|
23
|
+
this.justEntered = !wasVisible && visible;
|
|
24
|
+
this.justExited = wasVisible && !visible;
|
|
25
|
+
if (!this.initialized) {
|
|
26
|
+
this.justEntered = visible;
|
|
27
|
+
this.justExited = false;
|
|
28
|
+
}
|
|
29
|
+
this.initialized = true;
|
|
30
|
+
this.visible = visible;
|
|
31
|
+
this.visibleCameraNames = [...visibleCameraNames];
|
|
32
|
+
}
|
|
33
|
+
isInitialized() {
|
|
34
|
+
return this.initialized;
|
|
35
|
+
}
|
|
36
|
+
isVisible() {
|
|
37
|
+
return this.visible;
|
|
38
|
+
}
|
|
39
|
+
wasJustEntered() {
|
|
40
|
+
return this.justEntered;
|
|
41
|
+
}
|
|
42
|
+
wasJustExited() {
|
|
43
|
+
return this.justExited;
|
|
44
|
+
}
|
|
45
|
+
getVisibleCameraNames() {
|
|
46
|
+
return [...this.visibleCameraNames];
|
|
47
|
+
}
|
|
48
|
+
getState() {
|
|
49
|
+
return {
|
|
50
|
+
initialized: this.initialized,
|
|
51
|
+
visible: this.visible,
|
|
52
|
+
justEntered: this.justEntered,
|
|
53
|
+
justExited: this.justExited,
|
|
54
|
+
visibleCameraNames: this.getVisibleCameraNames()
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/lib/behaviors/screen-visibility/screen-visibility.descriptor.ts
|
|
60
|
+
var defaultOptions = {
|
|
61
|
+
cameraName: null,
|
|
62
|
+
requireFullyVisible: false,
|
|
63
|
+
padding: 0,
|
|
64
|
+
fallbackSize: null,
|
|
65
|
+
onChange: void 0,
|
|
66
|
+
onEnter: void 0,
|
|
67
|
+
onExit: void 0
|
|
68
|
+
};
|
|
69
|
+
var SCREEN_VISIBILITY_BEHAVIOR_KEY = /* @__PURE__ */ Symbol.for(
|
|
70
|
+
"zylem:behavior:screen-visibility"
|
|
71
|
+
);
|
|
72
|
+
var ScreenVisibilitySystem = class {
|
|
73
|
+
constructor(scene, getBehaviorLinks) {
|
|
74
|
+
this.scene = scene;
|
|
75
|
+
this.getBehaviorLinks = getBehaviorLinks;
|
|
76
|
+
}
|
|
77
|
+
scene;
|
|
78
|
+
getBehaviorLinks;
|
|
79
|
+
worldBounds = new Box3();
|
|
80
|
+
projectionMatrix = new Matrix4();
|
|
81
|
+
frustum = new Frustum();
|
|
82
|
+
savedPosition = new Vector3();
|
|
83
|
+
savedQuaternion = new Quaternion();
|
|
84
|
+
worldPosition = new Vector3();
|
|
85
|
+
fallbackMin = new Vector3();
|
|
86
|
+
fallbackMax = new Vector3();
|
|
87
|
+
corners = Array.from({ length: 8 }, () => new Vector3());
|
|
88
|
+
boundsCache = /* @__PURE__ */ new Map();
|
|
89
|
+
update(_ecs, _delta) {
|
|
90
|
+
const links = this.getBehaviorLinks?.(SCREEN_VISIBILITY_BEHAVIOR_KEY);
|
|
91
|
+
if (!links) return;
|
|
92
|
+
for (const link of links) {
|
|
93
|
+
const entity = link.entity;
|
|
94
|
+
const visibilityRef = link.ref;
|
|
95
|
+
const options = visibilityRef.options;
|
|
96
|
+
if (!visibilityRef.fsm) {
|
|
97
|
+
visibilityRef.fsm = new ScreenVisibilityFSM();
|
|
98
|
+
}
|
|
99
|
+
const fsm = visibilityRef.fsm;
|
|
100
|
+
const previousState = fsm.getState();
|
|
101
|
+
const cameras = this.resolveActiveCameras(options.cameraName);
|
|
102
|
+
const visibleCameraNames = [];
|
|
103
|
+
const bounds = this.computeWorldBounds(entity, visibilityRef, options);
|
|
104
|
+
if (bounds) {
|
|
105
|
+
for (let index = 0; index < cameras.length; index++) {
|
|
106
|
+
const cameraRef = cameras[index];
|
|
107
|
+
if (this.isBoundsVisible(bounds, cameraRef, options.requireFullyVisible)) {
|
|
108
|
+
visibleCameraNames.push(this.getCameraLabel(cameraRef, index));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
fsm.update(visibleCameraNames.length > 0, visibleCameraNames);
|
|
113
|
+
this.notifyVisibilityChange(entity, options, previousState, fsm.getState());
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
resolveActiveCameras(cameraName) {
|
|
117
|
+
const activeCameras = this.scene?.cameraManager?.activeCameras?.length ? [...this.scene.cameraManager.activeCameras] : this.scene?.zylemCamera ? [this.scene.zylemCamera] : [];
|
|
118
|
+
if (!cameraName) {
|
|
119
|
+
return activeCameras;
|
|
120
|
+
}
|
|
121
|
+
return activeCameras.filter((camera) => camera.name === cameraName);
|
|
122
|
+
}
|
|
123
|
+
computeWorldBounds(entity, ref, options) {
|
|
124
|
+
const cacheKey = this.getBoundsCacheKey(entity, options);
|
|
125
|
+
const cached = this.boundsCache.get(entity.uuid);
|
|
126
|
+
if (cached && cached.key === cacheKey) {
|
|
127
|
+
return cached.bounds;
|
|
128
|
+
}
|
|
129
|
+
const target = entity.group ?? entity.mesh;
|
|
130
|
+
this.worldBounds.makeEmpty();
|
|
131
|
+
if (target) {
|
|
132
|
+
const wasmPose = entity.getPose?.();
|
|
133
|
+
const useWasm = wasmPose && entity.runtimeHandle >= 0;
|
|
134
|
+
const body = useWasm ? null : entity.body;
|
|
135
|
+
if (useWasm || body) {
|
|
136
|
+
this.savedPosition.copy(target.position);
|
|
137
|
+
this.savedQuaternion.copy(target.quaternion);
|
|
138
|
+
if (useWasm) {
|
|
139
|
+
target.position.set(wasmPose.position.x, wasmPose.position.y, wasmPose.position.z);
|
|
140
|
+
if (!entity.controlledRotation) {
|
|
141
|
+
target.quaternion.set(
|
|
142
|
+
wasmPose.rotation.x,
|
|
143
|
+
wasmPose.rotation.y,
|
|
144
|
+
wasmPose.rotation.z,
|
|
145
|
+
wasmPose.rotation.w
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
const translation = body.translation();
|
|
150
|
+
target.position.set(translation.x, translation.y, translation.z);
|
|
151
|
+
if (!entity.controlledRotation) {
|
|
152
|
+
const rotation = body.rotation();
|
|
153
|
+
target.quaternion.set(rotation.x, rotation.y, rotation.z, rotation.w);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
target.updateWorldMatrix(true, true);
|
|
157
|
+
this.worldBounds.setFromObject(target);
|
|
158
|
+
target.position.copy(this.savedPosition);
|
|
159
|
+
target.quaternion.copy(this.savedQuaternion);
|
|
160
|
+
target.updateWorldMatrix(true, true);
|
|
161
|
+
} else {
|
|
162
|
+
target.updateWorldMatrix(true, true);
|
|
163
|
+
this.worldBounds.setFromObject(target);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (this.worldBounds.isEmpty()) {
|
|
167
|
+
const fallbackSize = options.fallbackSize ?? (entity.options?.size ?? null);
|
|
168
|
+
this.resolveFallbackCenter(entity, target);
|
|
169
|
+
const halfX = (fallbackSize?.x ?? 0) / 2;
|
|
170
|
+
const halfY = (fallbackSize?.y ?? 0) / 2;
|
|
171
|
+
const halfZ = (fallbackSize?.z ?? 0) / 2;
|
|
172
|
+
this.fallbackMin.set(
|
|
173
|
+
this.worldPosition.x - halfX,
|
|
174
|
+
this.worldPosition.y - halfY,
|
|
175
|
+
this.worldPosition.z - halfZ
|
|
176
|
+
);
|
|
177
|
+
this.fallbackMax.set(
|
|
178
|
+
this.worldPosition.x + halfX,
|
|
179
|
+
this.worldPosition.y + halfY,
|
|
180
|
+
this.worldPosition.z + halfZ
|
|
181
|
+
);
|
|
182
|
+
this.worldBounds.set(this.fallbackMin, this.fallbackMax);
|
|
183
|
+
}
|
|
184
|
+
if (options.padding !== 0) {
|
|
185
|
+
this.worldBounds.expandByScalar(options.padding);
|
|
186
|
+
}
|
|
187
|
+
if (this.worldBounds.isEmpty()) {
|
|
188
|
+
this.boundsCache.delete(entity.uuid);
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
const cachedBounds = cached?.bounds ?? new Box3();
|
|
192
|
+
cachedBounds.copy(this.worldBounds);
|
|
193
|
+
this.boundsCache.set(entity.uuid, {
|
|
194
|
+
bounds: cachedBounds,
|
|
195
|
+
key: cacheKey
|
|
196
|
+
});
|
|
197
|
+
ref.__screenVisibilityBoundsKey = cacheKey;
|
|
198
|
+
return cachedBounds;
|
|
199
|
+
}
|
|
200
|
+
getBoundsCacheKey(entity, options) {
|
|
201
|
+
const body = entity.body;
|
|
202
|
+
if (body) {
|
|
203
|
+
const translation = body.translation();
|
|
204
|
+
const rotation = body.rotation();
|
|
205
|
+
return [
|
|
206
|
+
"b",
|
|
207
|
+
translation.x.toFixed(3),
|
|
208
|
+
translation.y.toFixed(3),
|
|
209
|
+
translation.z.toFixed(3),
|
|
210
|
+
rotation.x.toFixed(3),
|
|
211
|
+
rotation.y.toFixed(3),
|
|
212
|
+
rotation.z.toFixed(3),
|
|
213
|
+
rotation.w.toFixed(3),
|
|
214
|
+
options.padding,
|
|
215
|
+
options.requireFullyVisible,
|
|
216
|
+
options.fallbackSize?.x ?? "",
|
|
217
|
+
options.fallbackSize?.y ?? "",
|
|
218
|
+
options.fallbackSize?.z ?? ""
|
|
219
|
+
].join("|");
|
|
220
|
+
}
|
|
221
|
+
const target = entity.group ?? entity.mesh;
|
|
222
|
+
if (target) {
|
|
223
|
+
const position2 = target.position;
|
|
224
|
+
const quaternion = target.quaternion;
|
|
225
|
+
const scale = target.scale;
|
|
226
|
+
return [
|
|
227
|
+
"o",
|
|
228
|
+
position2.x.toFixed(3),
|
|
229
|
+
position2.y.toFixed(3),
|
|
230
|
+
position2.z.toFixed(3),
|
|
231
|
+
quaternion.x.toFixed(3),
|
|
232
|
+
quaternion.y.toFixed(3),
|
|
233
|
+
quaternion.z.toFixed(3),
|
|
234
|
+
quaternion.w.toFixed(3),
|
|
235
|
+
scale.x.toFixed(3),
|
|
236
|
+
scale.y.toFixed(3),
|
|
237
|
+
scale.z.toFixed(3),
|
|
238
|
+
options.padding,
|
|
239
|
+
options.requireFullyVisible,
|
|
240
|
+
options.fallbackSize?.x ?? "",
|
|
241
|
+
options.fallbackSize?.y ?? "",
|
|
242
|
+
options.fallbackSize?.z ?? ""
|
|
243
|
+
].join("|");
|
|
244
|
+
}
|
|
245
|
+
const position = entity.options?.position ?? { x: 0, y: 0, z: 0 };
|
|
246
|
+
const size = entity.options?.size ?? { x: 0, y: 0, z: 0 };
|
|
247
|
+
return [
|
|
248
|
+
"s",
|
|
249
|
+
position.x,
|
|
250
|
+
position.y,
|
|
251
|
+
position.z,
|
|
252
|
+
size.x,
|
|
253
|
+
size.y,
|
|
254
|
+
size.z,
|
|
255
|
+
options.padding,
|
|
256
|
+
options.requireFullyVisible,
|
|
257
|
+
options.fallbackSize?.x ?? "",
|
|
258
|
+
options.fallbackSize?.y ?? "",
|
|
259
|
+
options.fallbackSize?.z ?? ""
|
|
260
|
+
].join("|");
|
|
261
|
+
}
|
|
262
|
+
resolveFallbackCenter(entity, target) {
|
|
263
|
+
const body = entity.body;
|
|
264
|
+
if (body) {
|
|
265
|
+
const translation = body.translation();
|
|
266
|
+
this.worldPosition.set(translation.x, translation.y, translation.z);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (target) {
|
|
270
|
+
target.updateWorldMatrix(true, false);
|
|
271
|
+
target.getWorldPosition(this.worldPosition);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const position = entity.options?.position ?? { x: 0, y: 0, z: 0 };
|
|
275
|
+
this.worldPosition.set(position.x, position.y, position.z);
|
|
276
|
+
}
|
|
277
|
+
isBoundsVisible(bounds, cameraRef, requireFullyVisible) {
|
|
278
|
+
const camera = cameraRef.camera;
|
|
279
|
+
camera.updateMatrixWorld(true);
|
|
280
|
+
this.projectionMatrix.multiplyMatrices(
|
|
281
|
+
camera.projectionMatrix,
|
|
282
|
+
camera.matrixWorldInverse
|
|
283
|
+
);
|
|
284
|
+
this.frustum.setFromProjectionMatrix(this.projectionMatrix);
|
|
285
|
+
if (!requireFullyVisible) {
|
|
286
|
+
return this.frustum.intersectsBox(bounds);
|
|
287
|
+
}
|
|
288
|
+
return this.getCorners(bounds).every((corner) => this.frustum.containsPoint(corner));
|
|
289
|
+
}
|
|
290
|
+
getCorners(bounds) {
|
|
291
|
+
const { min, max } = bounds;
|
|
292
|
+
this.corners[0].set(min.x, min.y, min.z);
|
|
293
|
+
this.corners[1].set(min.x, min.y, max.z);
|
|
294
|
+
this.corners[2].set(min.x, max.y, min.z);
|
|
295
|
+
this.corners[3].set(min.x, max.y, max.z);
|
|
296
|
+
this.corners[4].set(max.x, min.y, min.z);
|
|
297
|
+
this.corners[5].set(max.x, min.y, max.z);
|
|
298
|
+
this.corners[6].set(max.x, max.y, min.z);
|
|
299
|
+
this.corners[7].set(max.x, max.y, max.z);
|
|
300
|
+
return this.corners;
|
|
301
|
+
}
|
|
302
|
+
getCameraLabel(camera, index) {
|
|
303
|
+
return camera.name || (index === 0 ? "primary" : `camera-${index}`);
|
|
304
|
+
}
|
|
305
|
+
notifyVisibilityChange(entity, options, previousState, nextState) {
|
|
306
|
+
if (!nextState.justEntered && !nextState.justExited) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const context = {
|
|
310
|
+
entity,
|
|
311
|
+
visible: nextState.visible,
|
|
312
|
+
wasVisible: previousState.visible,
|
|
313
|
+
justEntered: nextState.justEntered,
|
|
314
|
+
justExited: nextState.justExited,
|
|
315
|
+
visibleCameraNames: [...nextState.visibleCameraNames],
|
|
316
|
+
cameraName: options.cameraName
|
|
317
|
+
};
|
|
318
|
+
if (nextState.justEntered) {
|
|
319
|
+
options.onEnter?.(context);
|
|
320
|
+
}
|
|
321
|
+
if (nextState.justExited) {
|
|
322
|
+
options.onExit?.(context);
|
|
323
|
+
}
|
|
324
|
+
options.onChange?.(context);
|
|
325
|
+
}
|
|
326
|
+
destroy(_ecs) {
|
|
327
|
+
this.boundsCache.clear();
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
function createScreenVisibilityHandle(ref) {
|
|
331
|
+
return {
|
|
332
|
+
isVisible: () => {
|
|
333
|
+
const fsm = ref.fsm;
|
|
334
|
+
return fsm?.isVisible() ?? false;
|
|
335
|
+
},
|
|
336
|
+
isOffscreen: () => {
|
|
337
|
+
const fsm = ref.fsm;
|
|
338
|
+
return !(fsm?.isVisible() ?? false);
|
|
339
|
+
},
|
|
340
|
+
wasJustEntered: () => {
|
|
341
|
+
const fsm = ref.fsm;
|
|
342
|
+
return fsm?.wasJustEntered() ?? false;
|
|
343
|
+
},
|
|
344
|
+
wasJustExited: () => {
|
|
345
|
+
const fsm = ref.fsm;
|
|
346
|
+
return fsm?.wasJustExited() ?? false;
|
|
347
|
+
},
|
|
348
|
+
getVisibleCameraNames: () => {
|
|
349
|
+
const fsm = ref.fsm;
|
|
350
|
+
return fsm?.getVisibleCameraNames() ?? [];
|
|
351
|
+
},
|
|
352
|
+
getState: () => {
|
|
353
|
+
const fsm = ref.fsm;
|
|
354
|
+
return fsm?.getState() ?? null;
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
var ScreenVisibilityBehavior = defineBehavior({
|
|
359
|
+
name: "screen-visibility",
|
|
360
|
+
defaultOptions,
|
|
361
|
+
systemFactory: (ctx) => new ScreenVisibilitySystem(ctx.scene, ctx.getBehaviorLinks),
|
|
362
|
+
createHandle: createScreenVisibilityHandle
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
export {
|
|
366
|
+
ScreenVisibilityFSM,
|
|
367
|
+
ScreenVisibilityBehavior
|
|
368
|
+
};
|
|
369
|
+
//# sourceMappingURL=chunk-WOMHL23C.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/behaviors/screen-visibility/screen-visibility.descriptor.ts","../src/lib/behaviors/screen-visibility/screen-visibility-fsm.ts"],"sourcesContent":["import {\n\tBox3,\n\tFrustum,\n\tMatrix4,\n\tQuaternion,\n\tVector3,\n\ttype Object3D,\n} from 'three';\n\nimport { defineBehavior, type BehaviorRef } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport { ScreenVisibilityFSM, type ScreenVisibilitySnapshot } from './screen-visibility-fsm';\nimport type { GameEntity } from '../../entities/entity';\nimport type { ZylemCamera } from '../../camera/zylem-camera';\n\nexport interface ScreenVisibilitySize {\n\tx: number;\n\ty: number;\n\tz: number;\n}\n\nexport interface ScreenVisibilityChangeContext {\n\tentity: GameEntity<any>;\n\tvisible: boolean;\n\twasVisible: boolean;\n\tjustEntered: boolean;\n\tjustExited: boolean;\n\tvisibleCameraNames: string[];\n\tcameraName: string | null;\n}\n\nexport interface ScreenVisibilityOptions {\n\t/**\n\t * Restrict visibility checks to one active camera by name.\n\t * When omitted, any active camera can make the entity visible.\n\t */\n\tcameraName: string | null;\n\t/**\n\t * Require the full entity bounds to remain inside the camera frustum.\n\t * Defaults to partial visibility (any intersection counts).\n\t */\n\trequireFullyVisible: boolean;\n\t/**\n\t * Expand or shrink the computed bounds in world units.\n\t * Positive values make visibility checks more generous.\n\t */\n\tpadding: number;\n\t/**\n\t * Optional bounds to use when the entity has no renderable mesh/group.\n\t * Falls back to the entity's configured size when available.\n\t */\n\tfallbackSize: ScreenVisibilitySize | null;\n\tonChange?: (context: ScreenVisibilityChangeContext) => void;\n\tonEnter?: (context: ScreenVisibilityChangeContext) => void;\n\tonExit?: (context: ScreenVisibilityChangeContext) => void;\n}\n\nexport interface ScreenVisibilityHandle {\n\tisVisible(): boolean;\n\tisOffscreen(): boolean;\n\twasJustEntered(): boolean;\n\twasJustExited(): boolean;\n\tgetVisibleCameraNames(): string[];\n\tgetState(): ScreenVisibilitySnapshot | null;\n}\n\nconst defaultOptions: ScreenVisibilityOptions = {\n\tcameraName: null,\n\trequireFullyVisible: false,\n\tpadding: 0,\n\tfallbackSize: null,\n\tonChange: undefined,\n\tonEnter: undefined,\n\tonExit: undefined,\n};\n\nconst SCREEN_VISIBILITY_BEHAVIOR_KEY = Symbol.for(\n\t'zylem:behavior:screen-visibility',\n);\n\nclass ScreenVisibilitySystem implements BehaviorSystem {\n\tprivate readonly worldBounds = new Box3();\n\tprivate readonly projectionMatrix = new Matrix4();\n\tprivate readonly frustum = new Frustum();\n\tprivate readonly savedPosition = new Vector3();\n\tprivate readonly savedQuaternion = new Quaternion();\n\tprivate readonly worldPosition = new Vector3();\n\tprivate readonly fallbackMin = new Vector3();\n\tprivate readonly fallbackMax = new Vector3();\n\tprivate readonly corners = Array.from({ length: 8 }, () => new Vector3());\n\tprivate readonly boundsCache = new Map<string, {\n\t\tbounds: Box3;\n\t\tkey: string;\n\t}>();\n\n\tconstructor(\n\t\tprivate scene: any,\n\t\tprivate getBehaviorLinks?: (key: symbol) => Iterable<BehaviorEntityLink>,\n\t) { }\n\n\tupdate(_ecs: unknown, _delta: number): void {\n\t\tconst links = this.getBehaviorLinks?.(SCREEN_VISIBILITY_BEHAVIOR_KEY);\n\t\tif (!links) return;\n\n\t\tfor (const link of links) {\n\t\t\tconst entity = link.entity as GameEntity<any>;\n\t\t\tconst visibilityRef = link.ref as BehaviorRef<ScreenVisibilityOptions>;\n\t\t\tconst options = visibilityRef.options;\n\n\t\t\tif (!visibilityRef.fsm) {\n\t\t\t\tvisibilityRef.fsm = new ScreenVisibilityFSM();\n\t\t\t}\n\n\t\t\tconst fsm = visibilityRef.fsm as ScreenVisibilityFSM;\n\t\t\tconst previousState = fsm.getState();\n\t\t\tconst cameras = this.resolveActiveCameras(options.cameraName);\n\t\t\tconst visibleCameraNames: string[] = [];\n\n\t\t\tconst bounds = this.computeWorldBounds(entity, visibilityRef, options);\n\t\t\tif (bounds) {\n\t\t\t\tfor (let index = 0; index < cameras.length; index++) {\n\t\t\t\t\tconst cameraRef = cameras[index];\n\t\t\t\t\tif (this.isBoundsVisible(bounds, cameraRef, options.requireFullyVisible)) {\n\t\t\t\t\t\tvisibleCameraNames.push(this.getCameraLabel(cameraRef, index));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfsm.update(visibleCameraNames.length > 0, visibleCameraNames);\n\t\t\tthis.notifyVisibilityChange(entity, options, previousState, fsm.getState());\n\t\t}\n\t}\n\n\tprivate resolveActiveCameras(cameraName: string | null): ZylemCamera[] {\n\t\tconst activeCameras = this.scene?.cameraManager?.activeCameras?.length\n\t\t\t? [...this.scene.cameraManager.activeCameras]\n\t\t\t: this.scene?.zylemCamera\n\t\t\t\t? [this.scene.zylemCamera]\n\t\t\t\t: [];\n\n\t\tif (!cameraName) {\n\t\t\treturn activeCameras;\n\t\t}\n\n\t\treturn activeCameras.filter((camera: ZylemCamera) => camera.name === cameraName);\n\t}\n\n\tprivate computeWorldBounds(\n\t\tentity: GameEntity<any>,\n\t\tref: BehaviorRef<ScreenVisibilityOptions>,\n\t\toptions: ScreenVisibilityOptions,\n\t): Box3 | null {\n\t\tconst cacheKey = this.getBoundsCacheKey(entity, options);\n\t\tconst cached = this.boundsCache.get(entity.uuid);\n\t\tif (cached && cached.key === cacheKey) {\n\t\t\treturn cached.bounds;\n\t\t}\n\n\t\tconst target = (entity.group ?? entity.mesh) as Object3D | undefined;\n\t\tthis.worldBounds.makeEmpty();\n\n\t\tif (target) {\n\t\t\tconst wasmPose = (entity as any).getPose?.();\n\t\t\tconst useWasm = wasmPose && (entity as any).runtimeHandle >= 0;\n\t\t\tconst body = useWasm ? null : (entity as any).body;\n\n\t\t\tif (useWasm || body) {\n\t\t\t\tthis.savedPosition.copy(target.position);\n\t\t\t\tthis.savedQuaternion.copy(target.quaternion);\n\n\t\t\t\tif (useWasm) {\n\t\t\t\t\ttarget.position.set(wasmPose.position.x, wasmPose.position.y, wasmPose.position.z);\n\t\t\t\t\tif (!(entity as any).controlledRotation) {\n\t\t\t\t\t\ttarget.quaternion.set(\n\t\t\t\t\t\t\twasmPose.rotation.x,\n\t\t\t\t\t\t\twasmPose.rotation.y,\n\t\t\t\t\t\t\twasmPose.rotation.z,\n\t\t\t\t\t\t\twasmPose.rotation.w,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconst translation = body.translation();\n\t\t\t\t\ttarget.position.set(translation.x, translation.y, translation.z);\n\t\t\t\t\tif (!(entity as any).controlledRotation) {\n\t\t\t\t\t\tconst rotation = body.rotation();\n\t\t\t\t\t\ttarget.quaternion.set(rotation.x, rotation.y, rotation.z, rotation.w);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ttarget.updateWorldMatrix(true, true);\n\t\t\t\tthis.worldBounds.setFromObject(target);\n\n\t\t\t\ttarget.position.copy(this.savedPosition);\n\t\t\t\ttarget.quaternion.copy(this.savedQuaternion);\n\t\t\t\ttarget.updateWorldMatrix(true, true);\n\t\t\t} else {\n\t\t\t\ttarget.updateWorldMatrix(true, true);\n\t\t\t\tthis.worldBounds.setFromObject(target);\n\t\t\t}\n\t\t}\n\n\t\tif (this.worldBounds.isEmpty()) {\n\t\t\tconst fallbackSize = options.fallbackSize\n\t\t\t\t?? ((entity.options?.size as ScreenVisibilitySize | undefined) ?? null);\n\t\t\tthis.resolveFallbackCenter(entity, target);\n\n\t\t\tconst halfX = (fallbackSize?.x ?? 0) / 2;\n\t\t\tconst halfY = (fallbackSize?.y ?? 0) / 2;\n\t\t\tconst halfZ = (fallbackSize?.z ?? 0) / 2;\n\n\t\t\tthis.fallbackMin.set(\n\t\t\t\tthis.worldPosition.x - halfX,\n\t\t\t\tthis.worldPosition.y - halfY,\n\t\t\t\tthis.worldPosition.z - halfZ,\n\t\t\t);\n\t\t\tthis.fallbackMax.set(\n\t\t\t\tthis.worldPosition.x + halfX,\n\t\t\t\tthis.worldPosition.y + halfY,\n\t\t\t\tthis.worldPosition.z + halfZ,\n\t\t\t);\n\t\t\tthis.worldBounds.set(this.fallbackMin, this.fallbackMax);\n\t\t}\n\n\t\tif (options.padding !== 0) {\n\t\t\tthis.worldBounds.expandByScalar(options.padding);\n\t\t}\n\n\t\tif (this.worldBounds.isEmpty()) {\n\t\t\tthis.boundsCache.delete(entity.uuid);\n\t\t\treturn null;\n\t\t}\n\n\t\tconst cachedBounds = cached?.bounds ?? new Box3();\n\t\tcachedBounds.copy(this.worldBounds);\n\t\tthis.boundsCache.set(entity.uuid, {\n\t\t\tbounds: cachedBounds,\n\t\t\tkey: cacheKey,\n\t\t});\n\t\t(ref as any).__screenVisibilityBoundsKey = cacheKey;\n\t\treturn cachedBounds;\n\t}\n\n\tprivate getBoundsCacheKey(\n\t\tentity: GameEntity<any>,\n\t\toptions: ScreenVisibilityOptions,\n\t): string {\n\t\tconst body = (entity as any).body;\n\t\tif (body) {\n\t\t\tconst translation = body.translation();\n\t\t\tconst rotation = body.rotation();\n\t\t\treturn [\n\t\t\t\t'b',\n\t\t\t\ttranslation.x.toFixed(3),\n\t\t\t\ttranslation.y.toFixed(3),\n\t\t\t\ttranslation.z.toFixed(3),\n\t\t\t\trotation.x.toFixed(3),\n\t\t\t\trotation.y.toFixed(3),\n\t\t\t\trotation.z.toFixed(3),\n\t\t\t\trotation.w.toFixed(3),\n\t\t\t\toptions.padding,\n\t\t\t\toptions.requireFullyVisible,\n\t\t\t\toptions.fallbackSize?.x ?? '',\n\t\t\t\toptions.fallbackSize?.y ?? '',\n\t\t\t\toptions.fallbackSize?.z ?? '',\n\t\t\t].join('|');\n\t\t}\n\n\t\tconst target = (entity.group ?? entity.mesh) as Object3D | undefined;\n\t\tif (target) {\n\t\t\tconst position = target.position;\n\t\t\tconst quaternion = target.quaternion;\n\t\t\tconst scale = target.scale;\n\t\t\treturn [\n\t\t\t\t'o',\n\t\t\t\tposition.x.toFixed(3),\n\t\t\t\tposition.y.toFixed(3),\n\t\t\t\tposition.z.toFixed(3),\n\t\t\t\tquaternion.x.toFixed(3),\n\t\t\t\tquaternion.y.toFixed(3),\n\t\t\t\tquaternion.z.toFixed(3),\n\t\t\t\tquaternion.w.toFixed(3),\n\t\t\t\tscale.x.toFixed(3),\n\t\t\t\tscale.y.toFixed(3),\n\t\t\t\tscale.z.toFixed(3),\n\t\t\t\toptions.padding,\n\t\t\t\toptions.requireFullyVisible,\n\t\t\t\toptions.fallbackSize?.x ?? '',\n\t\t\t\toptions.fallbackSize?.y ?? '',\n\t\t\t\toptions.fallbackSize?.z ?? '',\n\t\t\t].join('|');\n\t\t}\n\n\t\tconst position = entity.options?.position ?? { x: 0, y: 0, z: 0 };\n\t\tconst size = entity.options?.size ?? { x: 0, y: 0, z: 0 };\n\t\treturn [\n\t\t\t's',\n\t\t\tposition.x,\n\t\t\tposition.y,\n\t\t\tposition.z,\n\t\t\tsize.x,\n\t\t\tsize.y,\n\t\t\tsize.z,\n\t\t\toptions.padding,\n\t\t\toptions.requireFullyVisible,\n\t\t\toptions.fallbackSize?.x ?? '',\n\t\t\toptions.fallbackSize?.y ?? '',\n\t\t\toptions.fallbackSize?.z ?? '',\n\t\t].join('|');\n\t}\n\n\tprivate resolveFallbackCenter(\n\t\tentity: GameEntity<any>,\n\t\ttarget: Object3D | undefined,\n\t): void {\n\t\tconst body = (entity as any).body;\n\t\tif (body) {\n\t\t\tconst translation = body.translation();\n\t\t\tthis.worldPosition.set(translation.x, translation.y, translation.z);\n\t\t\treturn;\n\t\t}\n\n\t\tif (target) {\n\t\t\ttarget.updateWorldMatrix(true, false);\n\t\t\ttarget.getWorldPosition(this.worldPosition);\n\t\t\treturn;\n\t\t}\n\n\t\tconst position = entity.options?.position ?? { x: 0, y: 0, z: 0 };\n\t\tthis.worldPosition.set(position.x, position.y, position.z);\n\t}\n\n\tprivate isBoundsVisible(\n\t\tbounds: Box3,\n\t\tcameraRef: ZylemCamera,\n\t\trequireFullyVisible: boolean,\n\t): boolean {\n\t\tconst camera = cameraRef.camera;\n\t\tcamera.updateMatrixWorld(true);\n\t\tthis.projectionMatrix.multiplyMatrices(\n\t\t\tcamera.projectionMatrix,\n\t\t\tcamera.matrixWorldInverse,\n\t\t);\n\t\tthis.frustum.setFromProjectionMatrix(this.projectionMatrix);\n\n\t\tif (!requireFullyVisible) {\n\t\t\treturn this.frustum.intersectsBox(bounds);\n\t\t}\n\n\t\treturn this.getCorners(bounds).every((corner) => this.frustum.containsPoint(corner));\n\t}\n\n\tprivate getCorners(bounds: Box3): Vector3[] {\n\t\tconst { min, max } = bounds;\n\t\tthis.corners[0].set(min.x, min.y, min.z);\n\t\tthis.corners[1].set(min.x, min.y, max.z);\n\t\tthis.corners[2].set(min.x, max.y, min.z);\n\t\tthis.corners[3].set(min.x, max.y, max.z);\n\t\tthis.corners[4].set(max.x, min.y, min.z);\n\t\tthis.corners[5].set(max.x, min.y, max.z);\n\t\tthis.corners[6].set(max.x, max.y, min.z);\n\t\tthis.corners[7].set(max.x, max.y, max.z);\n\t\treturn this.corners;\n\t}\n\n\tprivate getCameraLabel(camera: ZylemCamera, index: number): string {\n\t\treturn camera.name || (index === 0 ? 'primary' : `camera-${index}`);\n\t}\n\n\tprivate notifyVisibilityChange(\n\t\tentity: GameEntity<any>,\n\t\toptions: ScreenVisibilityOptions,\n\t\tpreviousState: ScreenVisibilitySnapshot,\n\t\tnextState: ScreenVisibilitySnapshot,\n\t): void {\n\t\tif (!nextState.justEntered && !nextState.justExited) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst context: ScreenVisibilityChangeContext = {\n\t\t\tentity,\n\t\t\tvisible: nextState.visible,\n\t\t\twasVisible: previousState.visible,\n\t\t\tjustEntered: nextState.justEntered,\n\t\t\tjustExited: nextState.justExited,\n\t\t\tvisibleCameraNames: [...nextState.visibleCameraNames],\n\t\t\tcameraName: options.cameraName,\n\t\t};\n\n\t\tif (nextState.justEntered) {\n\t\t\toptions.onEnter?.(context);\n\t\t}\n\n\t\tif (nextState.justExited) {\n\t\t\toptions.onExit?.(context);\n\t\t}\n\n\t\toptions.onChange?.(context);\n\t}\n\n\tdestroy(_ecs: unknown): void {\n\t\tthis.boundsCache.clear();\n\t}\n}\n\nfunction createScreenVisibilityHandle(\n\tref: BehaviorRef<ScreenVisibilityOptions>,\n): ScreenVisibilityHandle {\n\treturn {\n\t\tisVisible: () => {\n\t\t\tconst fsm = ref.fsm as ScreenVisibilityFSM | undefined;\n\t\t\treturn fsm?.isVisible() ?? false;\n\t\t},\n\t\tisOffscreen: () => {\n\t\t\tconst fsm = ref.fsm as ScreenVisibilityFSM | undefined;\n\t\t\treturn !(fsm?.isVisible() ?? false);\n\t\t},\n\t\twasJustEntered: () => {\n\t\t\tconst fsm = ref.fsm as ScreenVisibilityFSM | undefined;\n\t\t\treturn fsm?.wasJustEntered() ?? false;\n\t\t},\n\t\twasJustExited: () => {\n\t\t\tconst fsm = ref.fsm as ScreenVisibilityFSM | undefined;\n\t\t\treturn fsm?.wasJustExited() ?? false;\n\t\t},\n\t\tgetVisibleCameraNames: () => {\n\t\t\tconst fsm = ref.fsm as ScreenVisibilityFSM | undefined;\n\t\t\treturn fsm?.getVisibleCameraNames() ?? [];\n\t\t},\n\t\tgetState: () => {\n\t\t\tconst fsm = ref.fsm as ScreenVisibilityFSM | undefined;\n\t\t\treturn fsm?.getState() ?? null;\n\t\t},\n\t};\n}\n\nexport const ScreenVisibilityBehavior = defineBehavior<\n\tScreenVisibilityOptions,\n\tScreenVisibilityHandle\n>({\n\tname: 'screen-visibility',\n\tdefaultOptions,\n\tsystemFactory: (ctx) =>\n\t\tnew ScreenVisibilitySystem(ctx.scene, ctx.getBehaviorLinks),\n\tcreateHandle: createScreenVisibilityHandle,\n});\n","export interface ScreenVisibilitySnapshot {\n\tinitialized: boolean;\n\tvisible: boolean;\n\tjustEntered: boolean;\n\tjustExited: boolean;\n\tvisibleCameraNames: string[];\n}\n\nexport class ScreenVisibilityFSM {\n\tprivate initialized = false;\n\tprivate visible = false;\n\tprivate justEntered = false;\n\tprivate justExited = false;\n\tprivate visibleCameraNames: string[] = [];\n\n\tupdate(visible: boolean, visibleCameraNames: readonly string[]): void {\n\t\tconst wasVisible = this.visible;\n\n\t\tthis.justEntered = !wasVisible && visible;\n\t\tthis.justExited = wasVisible && !visible;\n\n\t\tif (!this.initialized) {\n\t\t\tthis.justEntered = visible;\n\t\t\tthis.justExited = false;\n\t\t}\n\n\t\tthis.initialized = true;\n\t\tthis.visible = visible;\n\t\tthis.visibleCameraNames = [...visibleCameraNames];\n\t}\n\n\tisInitialized(): boolean {\n\t\treturn this.initialized;\n\t}\n\n\tisVisible(): boolean {\n\t\treturn this.visible;\n\t}\n\n\twasJustEntered(): boolean {\n\t\treturn this.justEntered;\n\t}\n\n\twasJustExited(): boolean {\n\t\treturn this.justExited;\n\t}\n\n\tgetVisibleCameraNames(): string[] {\n\t\treturn [...this.visibleCameraNames];\n\t}\n\n\tgetState(): ScreenVisibilitySnapshot {\n\t\treturn {\n\t\t\tinitialized: this.initialized,\n\t\t\tvisible: this.visible,\n\t\t\tjustEntered: this.justEntered,\n\t\t\tjustExited: this.justExited,\n\t\t\tvisibleCameraNames: this.getVisibleCameraNames(),\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["position"]}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// src/lib/core/vector.ts
|
|
2
|
+
import { Vector2 as ThreeVector2, Vector3 as ThreeVector3 } from "three";
|
|
3
|
+
import { Vector3 as RapierVector3 } from "@dimforge/rapier3d-compat";
|
|
4
|
+
var VEC2_ZERO = Object.freeze({
|
|
5
|
+
x: 0,
|
|
6
|
+
y: 0
|
|
7
|
+
});
|
|
8
|
+
var VEC2_ONE = Object.freeze({ x: 1, y: 1 });
|
|
9
|
+
var VEC3_ZERO = Object.freeze({
|
|
10
|
+
x: 0,
|
|
11
|
+
y: 0,
|
|
12
|
+
z: 0
|
|
13
|
+
});
|
|
14
|
+
var VEC3_ONE = Object.freeze({
|
|
15
|
+
x: 1,
|
|
16
|
+
y: 1,
|
|
17
|
+
z: 1
|
|
18
|
+
});
|
|
19
|
+
function isFiniteNumber(value) {
|
|
20
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
21
|
+
}
|
|
22
|
+
function hasVec2Shape(value) {
|
|
23
|
+
return value != null && typeof value === "object" && ("x" in value || "y" in value);
|
|
24
|
+
}
|
|
25
|
+
function hasVec3Shape(value) {
|
|
26
|
+
return value != null && typeof value === "object" && ("x" in value || "y" in value || "z" in value);
|
|
27
|
+
}
|
|
28
|
+
function getArrayAxis(value, index, fallback) {
|
|
29
|
+
if (!value) {
|
|
30
|
+
return fallback;
|
|
31
|
+
}
|
|
32
|
+
const axis = value[index];
|
|
33
|
+
return isFiniteNumber(axis) ? axis : fallback;
|
|
34
|
+
}
|
|
35
|
+
function getObjectAxis(value, key, fallback) {
|
|
36
|
+
if (!value) {
|
|
37
|
+
return fallback;
|
|
38
|
+
}
|
|
39
|
+
const axis = value[key];
|
|
40
|
+
return isFiniteNumber(axis) ? axis : fallback;
|
|
41
|
+
}
|
|
42
|
+
function getVec2Axis(value, key, index, fallback) {
|
|
43
|
+
if (!value) {
|
|
44
|
+
return fallback;
|
|
45
|
+
}
|
|
46
|
+
if (Array.isArray(value)) {
|
|
47
|
+
return getArrayAxis(value, index, fallback);
|
|
48
|
+
}
|
|
49
|
+
return getObjectAxis(value, key, fallback);
|
|
50
|
+
}
|
|
51
|
+
function getVec3Axis(value, key, index, fallback) {
|
|
52
|
+
if (!value) {
|
|
53
|
+
return fallback;
|
|
54
|
+
}
|
|
55
|
+
if (Array.isArray(value)) {
|
|
56
|
+
return getArrayAxis(value, index, fallback);
|
|
57
|
+
}
|
|
58
|
+
return getObjectAxis(value, key, fallback);
|
|
59
|
+
}
|
|
60
|
+
function normalizeVec2Defaults(defaults) {
|
|
61
|
+
return {
|
|
62
|
+
x: getVec2Axis(defaults, "x", 0, 0),
|
|
63
|
+
y: getVec2Axis(defaults, "y", 1, 0)
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function normalizeVec3Defaults(defaults) {
|
|
67
|
+
return {
|
|
68
|
+
x: getVec3Axis(defaults, "x", 0, 0),
|
|
69
|
+
y: getVec3Axis(defaults, "y", 1, 0),
|
|
70
|
+
z: getVec3Axis(defaults, "z", 2, 0)
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function isVec2Input(value) {
|
|
74
|
+
return Array.isArray(value) || hasVec2Shape(value);
|
|
75
|
+
}
|
|
76
|
+
function isVec3Input(value) {
|
|
77
|
+
return Array.isArray(value) || hasVec3Shape(value);
|
|
78
|
+
}
|
|
79
|
+
function normalizeVec2(input, defaults = VEC2_ZERO) {
|
|
80
|
+
const fallback = normalizeVec2Defaults(defaults);
|
|
81
|
+
return {
|
|
82
|
+
x: getVec2Axis(input, "x", 0, fallback.x),
|
|
83
|
+
y: getVec2Axis(input, "y", 1, fallback.y)
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function normalizeVec3(input, defaults = VEC3_ZERO) {
|
|
87
|
+
const fallback = normalizeVec3Defaults(defaults);
|
|
88
|
+
return {
|
|
89
|
+
x: getVec3Axis(input, "x", 0, fallback.x),
|
|
90
|
+
y: getVec3Axis(input, "y", 1, fallback.y),
|
|
91
|
+
z: getVec3Axis(input, "z", 2, fallback.z)
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function toThreeVector2(input, defaults = VEC2_ZERO) {
|
|
95
|
+
const { x, y } = normalizeVec2(input, defaults);
|
|
96
|
+
return new ThreeVector2(x, y);
|
|
97
|
+
}
|
|
98
|
+
function toThreeVector3(input, defaults = VEC3_ZERO) {
|
|
99
|
+
const { x, y, z } = normalizeVec3(input, defaults);
|
|
100
|
+
return new ThreeVector3(x, y, z);
|
|
101
|
+
}
|
|
102
|
+
function toRapierVector3(input, defaults = VEC3_ZERO) {
|
|
103
|
+
const { x, y, z } = normalizeVec3(input, defaults);
|
|
104
|
+
return new RapierVector3(x, y, z);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
VEC2_ZERO,
|
|
109
|
+
VEC2_ONE,
|
|
110
|
+
VEC3_ZERO,
|
|
111
|
+
VEC3_ONE,
|
|
112
|
+
isVec2Input,
|
|
113
|
+
isVec3Input,
|
|
114
|
+
normalizeVec2,
|
|
115
|
+
normalizeVec3,
|
|
116
|
+
toThreeVector2,
|
|
117
|
+
toThreeVector3,
|
|
118
|
+
toRapierVector3
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=chunk-WWVD5DR5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/core/vector.ts"],"sourcesContent":["import { Vector2 as ThreeVector2, Vector3 as ThreeVector3 } from 'three';\nimport { Vector3 as RapierVector3 } from '@dimforge/rapier3d-compat';\n\nexport type Vec2 = ThreeVector2;\nexport type Vec3 = ThreeVector3 | RapierVector3;\n\nexport type Vec2Components = { x: number; y: number };\nexport type Vec3Components = { x: number; y: number; z: number };\n\ntype Vec2Tuple = readonly [number?, number?] & { x?: number; y?: number };\ntype Vec3Tuple = readonly [number?, number?, number?] & {\n x?: number;\n y?: number;\n z?: number;\n};\n\nexport type Vec2Input = Vec2 | { x?: number; y?: number } | Vec2Tuple;\nexport type Vec3Input =\n | Vec3\n | { x?: number; y?: number; z?: number }\n | Vec3Tuple;\n\nexport const VEC2_ZERO: Readonly<Vec2Components> = Object.freeze({\n x: 0,\n y: 0,\n});\nexport const VEC2_ONE: Readonly<Vec2Components> = Object.freeze({ x: 1, y: 1 });\nexport const VEC3_ZERO: Readonly<Vec3Components> = Object.freeze({\n x: 0,\n y: 0,\n z: 0,\n});\nexport const VEC3_ONE: Readonly<Vec3Components> = Object.freeze({\n x: 1,\n y: 1,\n z: 1,\n});\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nfunction hasVec2Shape(value: unknown): value is { x?: unknown; y?: unknown } {\n return (\n value != null && typeof value === 'object' && ('x' in value || 'y' in value)\n );\n}\n\nfunction hasVec3Shape(\n value: unknown,\n): value is { x?: unknown; y?: unknown; z?: unknown } {\n return (\n value != null &&\n typeof value === 'object' &&\n ('x' in value || 'y' in value || 'z' in value)\n );\n}\n\nfunction getArrayAxis(\n value: readonly unknown[] | undefined,\n index: number,\n fallback: number,\n): number {\n if (!value) {\n return fallback;\n }\n const axis = value[index];\n return isFiniteNumber(axis) ? axis : fallback;\n}\n\nfunction getObjectAxis(\n value: { [key: string]: unknown } | undefined,\n key: 'x' | 'y' | 'z',\n fallback: number,\n): number {\n if (!value) {\n return fallback;\n }\n const axis = value[key];\n return isFiniteNumber(axis) ? axis : fallback;\n}\n\nfunction getVec2Axis(\n value: Vec2Input | Partial<Vec2Components> | null | undefined,\n key: 'x' | 'y',\n index: 0 | 1,\n fallback: number,\n): number {\n if (!value) {\n return fallback;\n }\n if (Array.isArray(value)) {\n return getArrayAxis(value, index, fallback);\n }\n return getObjectAxis(value as { [key: string]: unknown }, key, fallback);\n}\n\nfunction getVec3Axis(\n value: Vec3Input | Partial<Vec3Components> | null | undefined,\n key: 'x' | 'y' | 'z',\n index: 0 | 1 | 2,\n fallback: number,\n): number {\n if (!value) {\n return fallback;\n }\n if (Array.isArray(value)) {\n return getArrayAxis(value, index, fallback);\n }\n return getObjectAxis(value as { [key: string]: unknown }, key, fallback);\n}\n\nfunction normalizeVec2Defaults(\n defaults: Vec2Input | Partial<Vec2Components> | null | undefined,\n): Vec2Components {\n return {\n x: getVec2Axis(defaults, 'x', 0, 0),\n y: getVec2Axis(defaults, 'y', 1, 0),\n };\n}\n\nfunction normalizeVec3Defaults(\n defaults: Vec3Input | Partial<Vec3Components> | null | undefined,\n): Vec3Components {\n return {\n x: getVec3Axis(defaults, 'x', 0, 0),\n y: getVec3Axis(defaults, 'y', 1, 0),\n z: getVec3Axis(defaults, 'z', 2, 0),\n };\n}\n\nexport function isVec2Input(value: unknown): value is Vec2Input {\n return Array.isArray(value) || hasVec2Shape(value);\n}\n\nexport function isVec3Input(value: unknown): value is Vec3Input {\n return Array.isArray(value) || hasVec3Shape(value);\n}\n\nexport function normalizeVec2(\n input?: Vec2Input | null,\n defaults: Vec2Input | Partial<Vec2Components> = VEC2_ZERO,\n): Vec2Components {\n const fallback = normalizeVec2Defaults(defaults);\n return {\n x: getVec2Axis(input, 'x', 0, fallback.x),\n y: getVec2Axis(input, 'y', 1, fallback.y),\n };\n}\n\nexport function normalizeVec3(\n input?: Vec3Input | null,\n defaults: Vec3Input | Partial<Vec3Components> = VEC3_ZERO,\n): Vec3Components {\n const fallback = normalizeVec3Defaults(defaults);\n return {\n x: getVec3Axis(input, 'x', 0, fallback.x),\n y: getVec3Axis(input, 'y', 1, fallback.y),\n z: getVec3Axis(input, 'z', 2, fallback.z),\n };\n}\n\nexport function toThreeVector2(\n input?: Vec2Input | null,\n defaults: Vec2Input | Partial<Vec2Components> = VEC2_ZERO,\n): ThreeVector2 {\n const { x, y } = normalizeVec2(input, defaults);\n return new ThreeVector2(x, y);\n}\n\nexport function toThreeVector3(\n input?: Vec3Input | null,\n defaults: Vec3Input | Partial<Vec3Components> = VEC3_ZERO,\n): ThreeVector3 {\n const { x, y, z } = normalizeVec3(input, defaults);\n return new ThreeVector3(x, y, z);\n}\n\nexport function toRapierVector3(\n input?: Vec3Input | null,\n defaults: Vec3Input | Partial<Vec3Components> = VEC3_ZERO,\n): RapierVector3 {\n const { x, y, z } = normalizeVec3(input, defaults);\n return new RapierVector3(x, y, z);\n}\n"],"mappings":"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","names":[]}
|