@babylonjs/addons 7.33.0 → 7.34.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.
@@ -0,0 +1,152 @@
1
+ import { Tools } from "@babylonjs/core/Misc/tools.js";
2
+ let captureRequestQueue = [];
3
+ // Key is request id, value is object with capture and release callbacks
4
+ const pendingRequestCallbacks = new Map();
5
+ // Keep track of release requests with no matching capture request
6
+ // in case the release request arrived before the capture to avoid
7
+ // the capture request never getting released.
8
+ let unmatchedReleaseRequests = [];
9
+ let currentOwner = null; // Called on first capture or release request
10
+ /**
11
+ * Get the id of the object currently capturing pointer events
12
+ * @returns The id of the object currently capturing pointer events
13
+ * or null if no object is capturing pointer events
14
+ */
15
+ export const getCapturingId = () => {
16
+ return currentOwner;
17
+ };
18
+ /**
19
+ * Request that the object with the given id capture pointer events. If there is no current
20
+ * owner, then the request is granted immediately. If there is a current owner, then the request
21
+ * is queued until the current owner releases pointer events.
22
+ * @param requestId An id to identify the request. This id will be used to match the capture
23
+ * request with the release request.
24
+ * @param captureCallback The callback to call when the request is granted and the object is capturing
25
+ * @param releaseCallback The callback to call when the object is no longer capturing pointer events
26
+ */
27
+ export const requestCapture = (requestId, captureCallback, releaseCallback) => {
28
+ debugLog(`In pointerEventsCapture.requestCapture - Pointer events capture requested for ${requestId}`);
29
+ // If there is a release for this request, then ignore the request
30
+ if (removeUnmatchedRequest(requestId)) {
31
+ debugLog(`In pointerEventsCapture.requestCapture - Capture request matched previous release request ${requestId}. Cancelling capture request`);
32
+ return;
33
+ }
34
+ else if (requestId !== currentOwner) {
35
+ // if the request is not already in the queue, add it to the queue
36
+ enqueueCaptureRequest(requestId, captureCallback, releaseCallback);
37
+ }
38
+ if (!currentOwner) {
39
+ // If there is no current owner, go ahead and grant the request
40
+ transferPointerEventsOwnership();
41
+ }
42
+ // If the request id is the current owner, do nothing
43
+ };
44
+ /**
45
+ * Release pointer events from the object with the given id. If the object is the current owner
46
+ * then pointer events are released immediately. If the object is not the current owner, then the
47
+ * associated capture request is removed from the queue. If there is no matching capture request
48
+ * in the queue, then the release request is added to a list of unmatched release requests and will
49
+ * negate the next capture request with the same id. This is to guard against the possibility that
50
+ * the release request arrived before the capture request.
51
+ * @param requestId The id which should match the id of the capture request
52
+ */
53
+ export const requestRelease = (requestId) => {
54
+ debugLog(`In pointerEventsCapture.requestRelease - Pointer events release requested for ${requestId}`);
55
+ // if the requestId is the current capture holder release it
56
+ if (!requestId || requestId === currentOwner) {
57
+ transferPointerEventsOwnership();
58
+ }
59
+ else if (cancelRequest(requestId)) {
60
+ // if the request is in the queue, but not the current capture holder, remove it and it's callbacks
61
+ pendingRequestCallbacks.delete(requestId);
62
+ }
63
+ else {
64
+ debugLog(`In pointerEventsCapture.requestRelease - Received release request ${requestId} but no matching capture request was received`);
65
+ // request was not current and not in queue, likely because we received a release
66
+ // request before the capture. Add it to the unmatched list to guard against this possibility
67
+ if (!unmatchedReleaseRequests.includes(requestId)) {
68
+ unmatchedReleaseRequests.push(requestId);
69
+ }
70
+ }
71
+ };
72
+ /**
73
+ * Relase pointer events from the current owner
74
+ */
75
+ export const releaseCurrent = () => {
76
+ requestRelease(currentOwner);
77
+ };
78
+ const enqueueCaptureRequest = (requestId, capture, release) => {
79
+ debugLog(`In pointerEventsCapture.enqueueCaptureRequest - Enqueueing capture request for ${requestId}`);
80
+ if (!captureRequestQueue.includes(requestId)) {
81
+ captureRequestQueue.push(requestId);
82
+ pendingRequestCallbacks.set(requestId, { capture, release });
83
+ }
84
+ };
85
+ // Removes the request from the queue if it exists. Returns true
86
+ // if the request was found and removed, otherwise false
87
+ const cancelRequest = (requestId) => {
88
+ let removed = false;
89
+ captureRequestQueue = captureRequestQueue.filter((id) => {
90
+ if (id !== requestId) {
91
+ return true;
92
+ }
93
+ else {
94
+ removed = true;
95
+ debugLog(`In pointerEventsCapture.cancelRequest - Canceling pointer events capture request ${requestId}`);
96
+ return false;
97
+ }
98
+ });
99
+ return removed;
100
+ };
101
+ const removeUnmatchedRequest = (requestId) => {
102
+ let removed = false;
103
+ unmatchedReleaseRequests = unmatchedReleaseRequests.filter((id) => {
104
+ if (id !== requestId) {
105
+ return true;
106
+ }
107
+ else {
108
+ removed = true;
109
+ return false;
110
+ }
111
+ });
112
+ return removed;
113
+ };
114
+ const transferPointerEventsOwnership = () => {
115
+ const newOwnerId = nextCaptureRequest();
116
+ debugLog(`In pointerEventsCapture.transferPointerEventsOwnership - Transferrring pointer events from ${currentOwner} to ${newOwnerId}`);
117
+ // Release the current owner
118
+ doRelease();
119
+ if (newOwnerId) {
120
+ doCapture(newOwnerId);
121
+ }
122
+ };
123
+ const doRelease = () => {
124
+ debugLog(`In pointerEventsCapture.doRelease - Releasing pointer events from ${currentOwner}`);
125
+ if (currentOwner) {
126
+ // call the release callback
127
+ pendingRequestCallbacks.get(currentOwner)?.release();
128
+ // And remove the callbacks
129
+ pendingRequestCallbacks.delete(currentOwner);
130
+ currentOwner = null;
131
+ }
132
+ };
133
+ const doCapture = (newOwnerId) => {
134
+ if (newOwnerId) {
135
+ // call the capture callback
136
+ pendingRequestCallbacks.get(newOwnerId)?.capture();
137
+ }
138
+ currentOwner = newOwnerId;
139
+ debugLog(`In pointerEventsCapture.doCapture - Pointer events now captured by ${newOwnerId}`);
140
+ };
141
+ const nextCaptureRequest = () => {
142
+ return captureRequestQueue.length > 0 ? captureRequestQueue.shift() : null;
143
+ };
144
+ const debugLog = (message) => {
145
+ // If we are runnning in a test runner (in node, so window is not defined)
146
+ // or if the debug flag is set, then log the message
147
+ if (typeof window === "undefined" || window["pointer-events-capture-debug"]) {
148
+ Tools.Log(`${performance.now()} - game.scene.pointerEvents - ${message}\ncurrentOwner: ${currentOwner}\nqueue: ${captureRequestQueue}\nunmatched: ${unmatchedReleaseRequests}`);
149
+ }
150
+ };
151
+ // #endregion Debugging support
152
+ //# sourceMappingURL=pointerEventsCapture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointerEventsCapture.js","sourceRoot":"","sources":["../../../../dev/addons/src/htmlMesh/pointerEventsCapture.ts"],"names":[],"mappings":"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","sourcesContent":["import { Tools } from \"core/Misc/tools\";\r\n\r\n// A capture management system to ensure that the correct object has the pointer\r\n// events by eliminating race conditions that can cause the pointer events to be\r\n// released by a different object after they are captured leaving no object\r\n// as the owner. It does this by queueing requests and only allowing\r\n// capture when the current capture owner releases pointer events.\r\n\r\ntype CaptureReleaseCallback = () => void;\r\n\r\ntype CaptureReleaseCallbacks = {\r\n capture: CaptureReleaseCallback;\r\n release: CaptureReleaseCallback;\r\n};\r\n\r\nlet captureRequestQueue: string[] = [];\r\n\r\n// Key is request id, value is object with capture and release callbacks\r\nconst pendingRequestCallbacks: Map<string, CaptureReleaseCallbacks> = new Map();\r\n\r\n// Keep track of release requests with no matching capture request\r\n// in case the release request arrived before the capture to avoid\r\n// the capture request never getting released.\r\nlet unmatchedReleaseRequests: string[] = [];\r\n\r\nlet currentOwner: string | null = null; // Called on first capture or release request\r\n\r\n/**\r\n * Get the id of the object currently capturing pointer events\r\n * @returns The id of the object currently capturing pointer events\r\n * or null if no object is capturing pointer events\r\n */\r\nexport const getCapturingId = () => {\r\n return currentOwner;\r\n};\r\n\r\n/**\r\n * Request that the object with the given id capture pointer events. If there is no current\r\n * owner, then the request is granted immediately. If there is a current owner, then the request\r\n * is queued until the current owner releases pointer events.\r\n * @param requestId An id to identify the request. This id will be used to match the capture\r\n * request with the release request.\r\n * @param captureCallback The callback to call when the request is granted and the object is capturing\r\n * @param releaseCallback The callback to call when the object is no longer capturing pointer events\r\n */\r\nexport const requestCapture = (requestId: string, captureCallback: CaptureReleaseCallback, releaseCallback: CaptureReleaseCallback) => {\r\n debugLog(`In pointerEventsCapture.requestCapture - Pointer events capture requested for ${requestId}`);\r\n\r\n // If there is a release for this request, then ignore the request\r\n if (removeUnmatchedRequest(requestId)) {\r\n debugLog(`In pointerEventsCapture.requestCapture - Capture request matched previous release request ${requestId}. Cancelling capture request`);\r\n return;\r\n } else if (requestId !== currentOwner) {\r\n // if the request is not already in the queue, add it to the queue\r\n enqueueCaptureRequest(requestId, captureCallback, releaseCallback);\r\n }\r\n\r\n if (!currentOwner) {\r\n // If there is no current owner, go ahead and grant the request\r\n transferPointerEventsOwnership();\r\n }\r\n // If the request id is the current owner, do nothing\r\n};\r\n\r\n/**\r\n * Release pointer events from the object with the given id. If the object is the current owner\r\n * then pointer events are released immediately. If the object is not the current owner, then the\r\n * associated capture request is removed from the queue. If there is no matching capture request\r\n * in the queue, then the release request is added to a list of unmatched release requests and will\r\n * negate the next capture request with the same id. This is to guard against the possibility that\r\n * the release request arrived before the capture request.\r\n * @param requestId The id which should match the id of the capture request\r\n */\r\nexport const requestRelease = (requestId: string | null) => {\r\n debugLog(`In pointerEventsCapture.requestRelease - Pointer events release requested for ${requestId}`);\r\n\r\n // if the requestId is the current capture holder release it\r\n if (!requestId || requestId === currentOwner) {\r\n transferPointerEventsOwnership();\r\n } else if (cancelRequest(requestId)) {\r\n // if the request is in the queue, but not the current capture holder, remove it and it's callbacks\r\n pendingRequestCallbacks.delete(requestId);\r\n } else {\r\n debugLog(`In pointerEventsCapture.requestRelease - Received release request ${requestId} but no matching capture request was received`);\r\n // request was not current and not in queue, likely because we received a release\r\n // request before the capture. Add it to the unmatched list to guard against this possibility\r\n if (!unmatchedReleaseRequests.includes(requestId)) {\r\n unmatchedReleaseRequests.push(requestId);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Relase pointer events from the current owner\r\n */\r\nexport const releaseCurrent = () => {\r\n requestRelease(currentOwner);\r\n};\r\n\r\nconst enqueueCaptureRequest = (requestId: string, capture: CaptureReleaseCallback, release: CaptureReleaseCallback) => {\r\n debugLog(`In pointerEventsCapture.enqueueCaptureRequest - Enqueueing capture request for ${requestId}`);\r\n if (!captureRequestQueue.includes(requestId)) {\r\n captureRequestQueue.push(requestId);\r\n pendingRequestCallbacks.set(requestId, { capture, release });\r\n }\r\n};\r\n\r\n// Removes the request from the queue if it exists. Returns true\r\n// if the request was found and removed, otherwise false\r\nconst cancelRequest = (requestId: string | null) => {\r\n let removed = false;\r\n captureRequestQueue = captureRequestQueue.filter((id) => {\r\n if (id !== requestId) {\r\n return true;\r\n } else {\r\n removed = true;\r\n debugLog(`In pointerEventsCapture.cancelRequest - Canceling pointer events capture request ${requestId}`);\r\n return false;\r\n }\r\n });\r\n return removed;\r\n};\r\n\r\nconst removeUnmatchedRequest = (requestId: string) => {\r\n let removed = false;\r\n unmatchedReleaseRequests = unmatchedReleaseRequests.filter((id) => {\r\n if (id !== requestId) {\r\n return true;\r\n } else {\r\n removed = true;\r\n return false;\r\n }\r\n });\r\n return removed;\r\n};\r\n\r\nconst transferPointerEventsOwnership = () => {\r\n const newOwnerId = nextCaptureRequest();\r\n debugLog(`In pointerEventsCapture.transferPointerEventsOwnership - Transferrring pointer events from ${currentOwner} to ${newOwnerId}`);\r\n // Release the current owner\r\n doRelease();\r\n if (newOwnerId) {\r\n doCapture(newOwnerId);\r\n }\r\n};\r\n\r\nconst doRelease = () => {\r\n debugLog(`In pointerEventsCapture.doRelease - Releasing pointer events from ${currentOwner}`);\r\n if (currentOwner) {\r\n // call the release callback\r\n pendingRequestCallbacks.get(currentOwner)?.release();\r\n // And remove the callbacks\r\n pendingRequestCallbacks.delete(currentOwner);\r\n currentOwner = null;\r\n }\r\n};\r\n\r\nconst doCapture = (newOwnerId: string) => {\r\n if (newOwnerId) {\r\n // call the capture callback\r\n pendingRequestCallbacks.get(newOwnerId)?.capture();\r\n }\r\n currentOwner = newOwnerId;\r\n debugLog(`In pointerEventsCapture.doCapture - Pointer events now captured by ${newOwnerId}`);\r\n};\r\n\r\nconst nextCaptureRequest = () => {\r\n return captureRequestQueue.length > 0 ? captureRequestQueue.shift() : null;\r\n};\r\n\r\n// #region Debugging support\r\ndeclare global {\r\n interface Window {\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \"pointer-events-capture-debug\": boolean | null;\r\n }\r\n}\r\n\r\nconst debugLog = (message: string) => {\r\n // If we are runnning in a test runner (in node, so window is not defined)\r\n // or if the debug flag is set, then log the message\r\n if (typeof window === \"undefined\" || window[\"pointer-events-capture-debug\"]) {\r\n Tools.Log(\r\n `${performance.now()} - game.scene.pointerEvents - ${message}\\ncurrentOwner: ${currentOwner}\\nqueue: ${captureRequestQueue}\\nunmatched: ${unmatchedReleaseRequests}`\r\n );\r\n }\r\n};\r\n// #endregion Debugging support\r\n"]}
@@ -0,0 +1,47 @@
1
+ import type { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh.js";
2
+ import type { Behavior } from "@babylonjs/core/Behaviors/behavior.js";
3
+ /**
4
+ * Behavior for any content that can capture pointer events, i.e. bypass the Babylon pointer event handling
5
+ * and receive pointer events directly. It will register the capture triggers and negotiate the capture and
6
+ * release of pointer events. Curerntly this applies only to HtmlMesh
7
+ */
8
+ export declare class PointerEventsCaptureBehavior implements Behavior<AbstractMesh> {
9
+ private _captureCallback;
10
+ private _releaseCallback;
11
+ /** gets or sets behavior's name */
12
+ name: string;
13
+ private _attachedMesh;
14
+ /** @internal */
15
+ _captureOnPointerEnter: boolean;
16
+ /**
17
+ * Gets or sets the mesh that the behavior is attached to
18
+ */
19
+ get attachedMesh(): AbstractMesh | null;
20
+ set attachedMesh(value: AbstractMesh | null);
21
+ constructor(_captureCallback: () => void, _releaseCallback: () => void, { captureOnPointerEnter }?: {
22
+ captureOnPointerEnter?: boolean | undefined;
23
+ });
24
+ /**
25
+ * Set if the behavior should capture pointer events when the pointer enters the mesh
26
+ */
27
+ set captureOnPointerEnter(captureOnPointerEnter: boolean);
28
+ /**
29
+ * Function called when the behavior needs to be initialized (before attaching it to a target)
30
+ */
31
+ init(): void;
32
+ /**
33
+ * Called when the behavior is attached to a target
34
+ * @param mesh defines the target where the behavior is attached to
35
+ */
36
+ attach(mesh: AbstractMesh): void;
37
+ /**
38
+ * Called when the behavior is detached from its target
39
+ */
40
+ detach(): void;
41
+ /**
42
+ * Dispose the behavior
43
+ */
44
+ dispose(): void;
45
+ releasePointerEvents(): void;
46
+ capturePointerEvents(): void;
47
+ }
@@ -0,0 +1,191 @@
1
+ import { Logger } from "@babylonjs/core/Misc/logger.js";
2
+ import { requestCapture, requestRelease, releaseCurrent, getCapturingId } from "./pointerEventsCapture.js";
3
+ // Module level variable for holding the current scene
4
+ let _scene = null;
5
+ // Module level variable to hold the count of behavior instances that are currently capturing pointer events
6
+ // on entry. This is used to determine if we need to start or stop observing pointer movement.
7
+ let captureOnEnterCount = 0;
8
+ // Map used to store instance of the PointerEventsCaptureBehavior for a mesh
9
+ // We do this because this gets checked on pointer move and we don't want to
10
+ // use getBehaviorByName() because that is a linear search
11
+ const meshToBehaviorMap = new WeakMap();
12
+ const startCaptureOnEnter = (scene) => {
13
+ // If we are not in a browser, do nothing
14
+ if (typeof document === "undefined") {
15
+ return;
16
+ }
17
+ if (captureOnEnterCount === 0) {
18
+ document.addEventListener("pointermove", onPointerMove);
19
+ document.addEventListener("touchstart", onPointerMove);
20
+ _scene = _scene ?? scene;
21
+ Logger.Log("PointerEventsCaptureBehavior: Starting observation of pointer move events.");
22
+ _scene.onDisposeObservable.add(doStopCaptureOnEnter);
23
+ }
24
+ captureOnEnterCount++;
25
+ };
26
+ const doStopCaptureOnEnter = () => {
27
+ document.removeEventListener("pointermove", onPointerMove);
28
+ document.removeEventListener("touchstart", onPointerMove);
29
+ _scene = null;
30
+ Logger.Log("PointerEventsCaptureBehavior: Stopping observation of pointer move events.");
31
+ captureOnEnterCount = 0;
32
+ };
33
+ const stopCaptureOnEnter = () => {
34
+ // If we are not in a browser, do nothing
35
+ if (typeof document === "undefined") {
36
+ return;
37
+ }
38
+ // If we are not observing pointer movement, do nothing
39
+ if (!_scene) {
40
+ return;
41
+ }
42
+ captureOnEnterCount--;
43
+ if (captureOnEnterCount <= 0) {
44
+ doStopCaptureOnEnter();
45
+ }
46
+ };
47
+ // Module level function used to determine if an entered mesh should capture pointer events
48
+ const onPointerMove = (evt) => {
49
+ if (!_scene) {
50
+ return;
51
+ }
52
+ const canvasRect = _scene.getEngine().getRenderingCanvasClientRect();
53
+ if (!canvasRect) {
54
+ return;
55
+ }
56
+ // Get the object that contains the client X and Y from either the pointer event or from the
57
+ // TouchEvent touch
58
+ const { clientX, clientY } = "touches" in evt ? evt.touches[0] : evt;
59
+ // get the picked mesh, if any
60
+ const pointerScreenX = clientX - canvasRect.left;
61
+ const pointerScreenY = clientY - canvasRect.top;
62
+ let pointerCaptureBehavior;
63
+ const pickResult = _scene.pick(pointerScreenX, pointerScreenY, (mesh) => {
64
+ // If the mesh has an instance of PointerEventsCaptureBehavior attached to it,
65
+ // and capture on pointer enter is true, then we want to pick it
66
+ const pointerCaptureBehavior = meshToBehaviorMap.get(mesh);
67
+ return mesh.isEnabled() && typeof pointerCaptureBehavior !== "undefined" && pointerCaptureBehavior._captureOnPointerEnter;
68
+ });
69
+ let pickedMesh;
70
+ if (pickResult.hit) {
71
+ pickedMesh = pickResult.pickedMesh;
72
+ }
73
+ else {
74
+ pickedMesh = null;
75
+ }
76
+ const capturingIdAsInt = parseInt(getCapturingId() || "");
77
+ // if the picked mesh is the current capturing mesh, do nothing
78
+ if (pickedMesh && pickedMesh.uniqueId === capturingIdAsInt) {
79
+ return;
80
+ }
81
+ // If there is a capturing mesh and it is not the current picked mesh, or no
82
+ // mesh is picked, release the capturing mesh
83
+ if (capturingIdAsInt && (!pickedMesh || pickedMesh.uniqueId !== capturingIdAsInt)) {
84
+ releaseCurrent();
85
+ }
86
+ // If there is a picked mesh and it is not the current capturing mesh, capture
87
+ // the pointer events. Note that the current capturing mesh has already been
88
+ // released above
89
+ if (pickedMesh) {
90
+ pointerCaptureBehavior = meshToBehaviorMap.get(pickedMesh);
91
+ pointerCaptureBehavior.capturePointerEvents();
92
+ }
93
+ };
94
+ /**
95
+ * Behavior for any content that can capture pointer events, i.e. bypass the Babylon pointer event handling
96
+ * and receive pointer events directly. It will register the capture triggers and negotiate the capture and
97
+ * release of pointer events. Curerntly this applies only to HtmlMesh
98
+ */
99
+ export class PointerEventsCaptureBehavior {
100
+ /**
101
+ * Gets or sets the mesh that the behavior is attached to
102
+ */
103
+ get attachedMesh() {
104
+ return this._attachedMesh;
105
+ }
106
+ set attachedMesh(value) {
107
+ this._attachedMesh = value;
108
+ }
109
+ constructor(_captureCallback, _releaseCallback, { captureOnPointerEnter = true } = {}) {
110
+ this._captureCallback = _captureCallback;
111
+ this._releaseCallback = _releaseCallback;
112
+ /** gets or sets behavior's name */
113
+ this.name = "PointerEventsCaptureBehavior";
114
+ this._attachedMesh = null;
115
+ this._captureOnPointerEnter = captureOnPointerEnter;
116
+ // Warn if we are not in a browser
117
+ if (typeof document === "undefined") {
118
+ Logger.Warn(`Creating an instance of PointerEventsCaptureBehavior outside of a browser. The behavior will not work.`);
119
+ }
120
+ }
121
+ /**
122
+ * Set if the behavior should capture pointer events when the pointer enters the mesh
123
+ */
124
+ set captureOnPointerEnter(captureOnPointerEnter) {
125
+ if (this._captureOnPointerEnter === captureOnPointerEnter) {
126
+ return;
127
+ }
128
+ this._captureOnPointerEnter = captureOnPointerEnter;
129
+ if (this._attachedMesh) {
130
+ if (this._captureOnPointerEnter) {
131
+ startCaptureOnEnter(this._attachedMesh.getScene());
132
+ }
133
+ else {
134
+ stopCaptureOnEnter();
135
+ }
136
+ }
137
+ }
138
+ /**
139
+ * Function called when the behavior needs to be initialized (before attaching it to a target)
140
+ */
141
+ init() { }
142
+ /**
143
+ * Called when the behavior is attached to a target
144
+ * @param mesh defines the target where the behavior is attached to
145
+ */
146
+ attach(mesh) {
147
+ // Add a reference to this behavior on the mesh. We do this so we can get a
148
+ // reference to the behavior in the onPointerMove function without relying on
149
+ // getBehaviorByName(), which does a linear search of the behaviors array.
150
+ this.attachedMesh = mesh;
151
+ meshToBehaviorMap.set(mesh, this);
152
+ if (this._captureOnPointerEnter) {
153
+ startCaptureOnEnter(mesh.getScene());
154
+ }
155
+ }
156
+ /**
157
+ * Called when the behavior is detached from its target
158
+ */
159
+ detach() {
160
+ if (!this.attachedMesh) {
161
+ return;
162
+ }
163
+ // Remove the reference to this behavior from the mesh
164
+ meshToBehaviorMap.delete(this.attachedMesh);
165
+ if (this._captureOnPointerEnter) {
166
+ stopCaptureOnEnter();
167
+ }
168
+ this.attachedMesh = null;
169
+ }
170
+ /**
171
+ * Dispose the behavior
172
+ */
173
+ dispose() {
174
+ this.detach();
175
+ }
176
+ // Release pointer events
177
+ releasePointerEvents() {
178
+ if (!this.attachedMesh) {
179
+ return;
180
+ }
181
+ requestRelease(this.attachedMesh.uniqueId.toString());
182
+ }
183
+ // Capture pointer events
184
+ capturePointerEvents() {
185
+ if (!this.attachedMesh) {
186
+ return;
187
+ }
188
+ requestCapture(this.attachedMesh.uniqueId.toString(), this._captureCallback, this._releaseCallback);
189
+ }
190
+ }
191
+ //# sourceMappingURL=pointerEventsCaptureBehavior.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointerEventsCaptureBehavior.js","sourceRoot":"","sources":["../../../../dev/addons/src/htmlMesh/pointerEventsCaptureBehavior.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,uCAAyB;AAC1C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExG,sDAAsD;AACtD,IAAI,MAAM,GAAiB,IAAI,CAAC;AAEhC,4GAA4G;AAC5G,+FAA+F;AAC/F,IAAI,mBAAmB,GAAG,CAAC,CAAC;AAE5B,4EAA4E;AAC5E,4EAA4E;AAC5E,0DAA0D;AAC1D,MAAM,iBAAiB,GAAG,IAAI,OAAO,EAA8C,CAAC;AAEpF,MAAM,mBAAmB,GAAG,CAAC,KAAY,EAAE,EAAE;IACzC,yCAAyC;IACzC,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE;QACjC,OAAO;KACV;IACD,IAAI,mBAAmB,KAAK,CAAC,EAAE;QAC3B,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QACxD,QAAQ,CAAC,gBAAgB,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;QACvD,MAAM,GAAG,MAAM,IAAI,KAAK,CAAC;QACzB,MAAM,CAAC,GAAG,CAAC,4EAA4E,CAAC,CAAC;QACzF,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;KACxD;IACD,mBAAmB,EAAE,CAAC;AAC1B,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,GAAG,EAAE;IAC9B,QAAQ,CAAC,mBAAmB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IAC3D,QAAQ,CAAC,mBAAmB,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IAC1D,MAAM,GAAG,IAAI,CAAC;IACd,MAAM,CAAC,GAAG,CAAC,4EAA4E,CAAC,CAAC;IACzF,mBAAmB,GAAG,CAAC,CAAC;AAC5B,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,GAAG,EAAE;IAC5B,yCAAyC;IACzC,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE;QACjC,OAAO;KACV;IAED,uDAAuD;IACvD,IAAI,CAAC,MAAM,EAAE;QACT,OAAO;KACV;IAED,mBAAmB,EAAE,CAAC;IACtB,IAAI,mBAAmB,IAAI,CAAC,EAAE;QAC1B,oBAAoB,EAAE,CAAC;KAC1B;AACL,CAAC,CAAC;AAEF,2FAA2F;AAC3F,MAAM,aAAa,GAAG,CAAC,GAA8B,EAAE,EAAE;IACrD,IAAI,CAAC,MAAM,EAAE;QACT,OAAO;KACV;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC,4BAA4B,EAAE,CAAC;IACrE,IAAI,CAAC,UAAU,EAAE;QACb,OAAO;KACV;IAED,4FAA4F;IAC5F,mBAAmB;IACnB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,SAAS,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAErE,8BAA8B;IAC9B,MAAM,cAAc,GAAG,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC;IACjD,MAAM,cAAc,GAAG,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC;IAEhD,IAAI,sBAAgE,CAAC;IACrE,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,cAAc,EAAE,CAAC,IAAI,EAAE,EAAE;QACpE,8EAA8E;QAC9E,gEAAgE;QAChE,MAAM,sBAAsB,GAAG,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,SAAS,EAAE,IAAI,OAAO,sBAAsB,KAAK,WAAW,IAAI,sBAAsB,CAAC,sBAAsB,CAAC;IAC9H,CAAC,CAAC,CAAC;IAEH,IAAI,UAA+B,CAAC;IACpC,IAAI,UAAU,CAAC,GAAG,EAAE;QAChB,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC;KACtC;SAAM;QACH,UAAU,GAAG,IAAI,CAAC;KACrB;IAED,MAAM,gBAAgB,GAAG,QAAQ,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;IAE1D,+DAA+D;IAC/D,IAAI,UAAU,IAAI,UAAU,CAAC,QAAQ,KAAK,gBAAgB,EAAE;QACxD,OAAO;KACV;IAED,4EAA4E;IAC5E,6CAA6C;IAC7C,IAAI,gBAAgB,IAAI,CAAC,CAAC,UAAU,IAAI,UAAU,CAAC,QAAQ,KAAK,gBAAgB,CAAC,EAAE;QAC/E,cAAc,EAAE,CAAC;KACpB;IAED,8EAA8E;IAC9E,6EAA6E;IAC7E,iBAAiB;IACjB,IAAI,UAAU,EAAE;QACZ,sBAAsB,GAAG,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC3D,sBAAuB,CAAC,oBAAoB,EAAE,CAAC;KAClD;AACL,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,OAAO,4BAA4B;IAQrC;;OAEG;IACH,IAAW,YAAY;QACnB,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC;IAED,IAAW,YAAY,CAAC,KAA0B;QAC9C,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;IAC/B,CAAC;IAED,YACY,gBAA4B,EAC5B,gBAA4B,EACpC,EAAE,qBAAqB,GAAG,IAAI,EAAE,GAAG,EAAE;QAF7B,qBAAgB,GAAhB,gBAAgB,CAAY;QAC5B,qBAAgB,GAAhB,gBAAgB,CAAY;QApBxC,mCAAmC;QAC5B,SAAI,GAAG,8BAA8B,CAAC;QAsBzC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,sBAAsB,GAAG,qBAAqB,CAAC;QAEpD,kCAAkC;QAClC,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE;YACjC,MAAM,CAAC,IAAI,CAAC,yGAAyG,CAAC,CAAC;SAC1H;IACL,CAAC;IAED;;OAEG;IACH,IAAW,qBAAqB,CAAC,qBAA8B;QAC3D,IAAI,IAAI,CAAC,sBAAsB,KAAK,qBAAqB,EAAE;YACvD,OAAO;SACV;QACD,IAAI,CAAC,sBAAsB,GAAG,qBAAqB,CAAC;QACpD,IAAI,IAAI,CAAC,aAAa,EAAE;YACpB,IAAI,IAAI,CAAC,sBAAsB,EAAE;gBAC7B,mBAAmB,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAG,CAAC,CAAC;aACvD;iBAAM;gBACH,kBAAkB,EAAE,CAAC;aACxB;SACJ;IACL,CAAC;IAED;;OAEG;IACI,IAAI,KAAI,CAAC;IAEhB;;;OAGG;IACI,MAAM,CAAC,IAAkB;QAC5B,4EAA4E;QAC5E,6EAA6E;QAC7E,0EAA0E;QAC1E,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,IAAI,CAAC,sBAAsB,EAAE;YAC7B,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAG,CAAC,CAAC;SACzC;IACL,CAAC;IAED;;OAEG;IACI,MAAM;QACT,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YACpB,OAAO;SACV;QACD,sDAAsD;QACtD,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5C,IAAI,IAAI,CAAC,sBAAsB,EAAE;YAC7B,kBAAkB,EAAE,CAAC;SACxB;QACD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,OAAO;QACV,IAAI,CAAC,MAAM,EAAE,CAAC;IAClB,CAAC;IAED,yBAAyB;IAClB,oBAAoB;QACvB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YACpB,OAAO;SACV;QACD,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,yBAAyB;IAClB,oBAAoB;QACvB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YACpB,OAAO;SACV;QACD,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACxG,CAAC;CACJ","sourcesContent":["import type { AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport type { Behavior } from \"core/Behaviors/behavior\";\r\nimport type { Scene } from \"core/scene\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { requestCapture, requestRelease, releaseCurrent, getCapturingId } from \"./pointerEventsCapture\";\r\n\r\n// Module level variable for holding the current scene\r\nlet _scene: Scene | null = null;\r\n\r\n// Module level variable to hold the count of behavior instances that are currently capturing pointer events\r\n// on entry. This is used to determine if we need to start or stop observing pointer movement.\r\nlet captureOnEnterCount = 0;\r\n\r\n// Map used to store instance of the PointerEventsCaptureBehavior for a mesh\r\n// We do this because this gets checked on pointer move and we don't want to\r\n// use getBehaviorByName() because that is a linear search\r\nconst meshToBehaviorMap = new WeakMap<AbstractMesh, PointerEventsCaptureBehavior>();\r\n\r\nconst startCaptureOnEnter = (scene: Scene) => {\r\n // If we are not in a browser, do nothing\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n if (captureOnEnterCount === 0) {\r\n document.addEventListener(\"pointermove\", onPointerMove);\r\n document.addEventListener(\"touchstart\", onPointerMove);\r\n _scene = _scene ?? scene;\r\n Logger.Log(\"PointerEventsCaptureBehavior: Starting observation of pointer move events.\");\r\n _scene.onDisposeObservable.add(doStopCaptureOnEnter);\r\n }\r\n captureOnEnterCount++;\r\n};\r\n\r\nconst doStopCaptureOnEnter = () => {\r\n document.removeEventListener(\"pointermove\", onPointerMove);\r\n document.removeEventListener(\"touchstart\", onPointerMove);\r\n _scene = null;\r\n Logger.Log(\"PointerEventsCaptureBehavior: Stopping observation of pointer move events.\");\r\n captureOnEnterCount = 0;\r\n};\r\n\r\nconst stopCaptureOnEnter = () => {\r\n // If we are not in a browser, do nothing\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n\r\n // If we are not observing pointer movement, do nothing\r\n if (!_scene) {\r\n return;\r\n }\r\n\r\n captureOnEnterCount--;\r\n if (captureOnEnterCount <= 0) {\r\n doStopCaptureOnEnter();\r\n }\r\n};\r\n\r\n// Module level function used to determine if an entered mesh should capture pointer events\r\nconst onPointerMove = (evt: PointerEvent | TouchEvent) => {\r\n if (!_scene) {\r\n return;\r\n }\r\n\r\n const canvasRect = _scene.getEngine().getRenderingCanvasClientRect();\r\n if (!canvasRect) {\r\n return;\r\n }\r\n\r\n // Get the object that contains the client X and Y from either the pointer event or from the\r\n // TouchEvent touch\r\n const { clientX, clientY } = \"touches\" in evt ? evt.touches[0] : evt;\r\n\r\n // get the picked mesh, if any\r\n const pointerScreenX = clientX - canvasRect.left;\r\n const pointerScreenY = clientY - canvasRect.top;\r\n\r\n let pointerCaptureBehavior: PointerEventsCaptureBehavior | undefined;\r\n const pickResult = _scene.pick(pointerScreenX, pointerScreenY, (mesh) => {\r\n // If the mesh has an instance of PointerEventsCaptureBehavior attached to it,\r\n // and capture on pointer enter is true, then we want to pick it\r\n const pointerCaptureBehavior = meshToBehaviorMap.get(mesh);\r\n return mesh.isEnabled() && typeof pointerCaptureBehavior !== \"undefined\" && pointerCaptureBehavior._captureOnPointerEnter;\r\n });\r\n\r\n let pickedMesh: AbstractMesh | null;\r\n if (pickResult.hit) {\r\n pickedMesh = pickResult.pickedMesh;\r\n } else {\r\n pickedMesh = null;\r\n }\r\n\r\n const capturingIdAsInt = parseInt(getCapturingId() || \"\");\r\n\r\n // if the picked mesh is the current capturing mesh, do nothing\r\n if (pickedMesh && pickedMesh.uniqueId === capturingIdAsInt) {\r\n return;\r\n }\r\n\r\n // If there is a capturing mesh and it is not the current picked mesh, or no\r\n // mesh is picked, release the capturing mesh\r\n if (capturingIdAsInt && (!pickedMesh || pickedMesh.uniqueId !== capturingIdAsInt)) {\r\n releaseCurrent();\r\n }\r\n\r\n // If there is a picked mesh and it is not the current capturing mesh, capture\r\n // the pointer events. Note that the current capturing mesh has already been\r\n // released above\r\n if (pickedMesh) {\r\n pointerCaptureBehavior = meshToBehaviorMap.get(pickedMesh);\r\n pointerCaptureBehavior!.capturePointerEvents();\r\n }\r\n};\r\n\r\n/**\r\n * Behavior for any content that can capture pointer events, i.e. bypass the Babylon pointer event handling\r\n * and receive pointer events directly. It will register the capture triggers and negotiate the capture and\r\n * release of pointer events. Curerntly this applies only to HtmlMesh\r\n */\r\nexport class PointerEventsCaptureBehavior implements Behavior<AbstractMesh> {\r\n /** gets or sets behavior's name */\r\n public name = \"PointerEventsCaptureBehavior\";\r\n\r\n private _attachedMesh: AbstractMesh | null;\r\n /** @internal */\r\n public _captureOnPointerEnter: boolean;\r\n\r\n /**\r\n * Gets or sets the mesh that the behavior is attached to\r\n */\r\n public get attachedMesh() {\r\n return this._attachedMesh;\r\n }\r\n\r\n public set attachedMesh(value: AbstractMesh | null) {\r\n this._attachedMesh = value;\r\n }\r\n\r\n constructor(\r\n private _captureCallback: () => void,\r\n private _releaseCallback: () => void,\r\n { captureOnPointerEnter = true } = {}\r\n ) {\r\n this._attachedMesh = null;\r\n this._captureOnPointerEnter = captureOnPointerEnter;\r\n\r\n // Warn if we are not in a browser\r\n if (typeof document === \"undefined\") {\r\n Logger.Warn(`Creating an instance of PointerEventsCaptureBehavior outside of a browser. The behavior will not work.`);\r\n }\r\n }\r\n\r\n /**\r\n * Set if the behavior should capture pointer events when the pointer enters the mesh\r\n */\r\n public set captureOnPointerEnter(captureOnPointerEnter: boolean) {\r\n if (this._captureOnPointerEnter === captureOnPointerEnter) {\r\n return;\r\n }\r\n this._captureOnPointerEnter = captureOnPointerEnter;\r\n if (this._attachedMesh) {\r\n if (this._captureOnPointerEnter) {\r\n startCaptureOnEnter(this._attachedMesh.getScene()!);\r\n } else {\r\n stopCaptureOnEnter();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Function called when the behavior needs to be initialized (before attaching it to a target)\r\n */\r\n public init() {}\r\n\r\n /**\r\n * Called when the behavior is attached to a target\r\n * @param mesh defines the target where the behavior is attached to\r\n */\r\n public attach(mesh: AbstractMesh) {\r\n // Add a reference to this behavior on the mesh. We do this so we can get a\r\n // reference to the behavior in the onPointerMove function without relying on\r\n // getBehaviorByName(), which does a linear search of the behaviors array.\r\n this.attachedMesh = mesh;\r\n meshToBehaviorMap.set(mesh, this);\r\n if (this._captureOnPointerEnter) {\r\n startCaptureOnEnter(mesh.getScene()!);\r\n }\r\n }\r\n\r\n /**\r\n * Called when the behavior is detached from its target\r\n */\r\n public detach() {\r\n if (!this.attachedMesh) {\r\n return;\r\n }\r\n // Remove the reference to this behavior from the mesh\r\n meshToBehaviorMap.delete(this.attachedMesh);\r\n if (this._captureOnPointerEnter) {\r\n stopCaptureOnEnter();\r\n }\r\n this.attachedMesh = null;\r\n }\r\n\r\n /**\r\n * Dispose the behavior\r\n */\r\n public dispose() {\r\n this.detach();\r\n }\r\n\r\n // Release pointer events\r\n public releasePointerEvents() {\r\n if (!this.attachedMesh) {\r\n return;\r\n }\r\n requestRelease(this.attachedMesh.uniqueId.toString());\r\n }\r\n\r\n // Capture pointer events\r\n public capturePointerEvents() {\r\n if (!this.attachedMesh) {\r\n return;\r\n }\r\n requestCapture(this.attachedMesh.uniqueId.toString(), this._captureCallback, this._releaseCallback);\r\n }\r\n}\r\n"]}
package/index.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const empty: {};
1
+ export * from "./htmlMesh";
package/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export const empty = {};
1
+ export * from "./htmlMesh.js";
2
2
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../dev/addons/src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC","sourcesContent":["export const empty = {};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../dev/addons/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC","sourcesContent":["export * from \"./htmlMesh\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babylonjs/addons",
3
- "version": "7.33.0",
3
+ "version": "7.34.0",
4
4
  "main": "index.js",
5
5
  "module": "index.js",
6
6
  "types": "index.d.ts",
@@ -18,7 +18,7 @@
18
18
  "postcompile": "build-tools -c add-js-to-es6"
19
19
  },
20
20
  "devDependencies": {
21
- "@babylonjs/core": "^7.33.0",
21
+ "@babylonjs/core": "^7.34.0",
22
22
  "@dev/addons": "^1.0.0",
23
23
  "@dev/build-tools": "^1.0.0"
24
24
  },