p5-phone 1.4.4

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 (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +509 -0
  3. package/dist/p5-phone.js +1062 -0
  4. package/dist/p5-phone.min.js +10 -0
  5. package/examples/Phone Sensor Examples/microphone/01_mic_level/index.html +19 -0
  6. package/examples/Phone Sensor Examples/microphone/01_mic_level/sketch.js +117 -0
  7. package/examples/Phone Sensor Examples/movement/01_orientation_basic/index.html +28 -0
  8. package/examples/Phone Sensor Examples/movement/01_orientation_basic/sketch.js +123 -0
  9. package/examples/Phone Sensor Examples/movement/02_rotational_velocity/index.html +28 -0
  10. package/examples/Phone Sensor Examples/movement/02_rotational_velocity/sketch.js +144 -0
  11. package/examples/Phone Sensor Examples/movement/03_acceleration/index.html +28 -0
  12. package/examples/Phone Sensor Examples/movement/03_acceleration/sketch.js +87 -0
  13. package/examples/Phone Sensor Examples/sound/01_dual_audio/index.html +31 -0
  14. package/examples/Phone Sensor Examples/sound/01_dual_audio/sketch.js +225 -0
  15. package/examples/Phone Sensor Examples/sound/01_dual_audio/tracks/audio1.mp3 +0 -0
  16. package/examples/Phone Sensor Examples/sound/01_dual_audio/tracks/audio2.mp3 +0 -0
  17. package/examples/Phone Sensor Examples/sound/02_volume_touches/index.html +31 -0
  18. package/examples/Phone Sensor Examples/sound/02_volume_touches/sketch.js +269 -0
  19. package/examples/Phone Sensor Examples/sound/02_volume_touches/tracks/audio1.mp3 +0 -0
  20. package/examples/Phone Sensor Examples/touch/01_touch_basic/index.html +28 -0
  21. package/examples/Phone Sensor Examples/touch/01_touch_basic/sketch.js +94 -0
  22. package/examples/Phone Sensor Examples/touch/02_touch_zones/index.html +28 -0
  23. package/examples/Phone Sensor Examples/touch/02_touch_zones/sketch.js +220 -0
  24. package/examples/Phone Sensor Examples/touch/03_touch_count/index.html +28 -0
  25. package/examples/Phone Sensor Examples/touch/03_touch_count/sketch.js +93 -0
  26. package/examples/Phone Sensor Examples/touch/04_touch_distance/index.html +28 -0
  27. package/examples/Phone Sensor Examples/touch/04_touch_distance/sketch.js +120 -0
  28. package/examples/Phone Sensor Examples/touch/05_touch_angle/index.html +28 -0
  29. package/examples/Phone Sensor Examples/touch/05_touch_angle/sketch.js +117 -0
  30. package/examples/Phone Sensor Examples - Minimal/microphone/01_mic_level/index.html +19 -0
  31. package/examples/Phone Sensor Examples - Minimal/microphone/01_mic_level/sketch.js +72 -0
  32. package/examples/Phone Sensor Examples - Minimal/movement/01_orientation_basic/index.html +18 -0
  33. package/examples/Phone Sensor Examples - Minimal/movement/01_orientation_basic/sketch.js +51 -0
  34. package/examples/Phone Sensor Examples - Minimal/movement/02_rotational_velocity/index.html +18 -0
  35. package/examples/Phone Sensor Examples - Minimal/movement/02_rotational_velocity/sketch.js +70 -0
  36. package/examples/Phone Sensor Examples - Minimal/movement/03_acceleration/index.html +18 -0
  37. package/examples/Phone Sensor Examples - Minimal/movement/03_acceleration/sketch.js +83 -0
  38. package/examples/Phone Sensor Examples - Minimal/sound/01_sound_basic/index.html +19 -0
  39. package/examples/Phone Sensor Examples - Minimal/sound/01_sound_basic/sketch.js +96 -0
  40. package/examples/Phone Sensor Examples - Minimal/sound/01_sound_basic/tracks/audio1.mp3 +0 -0
  41. package/examples/Phone Sensor Examples - Minimal/sound/02_sound_amplitude/index.html +19 -0
  42. package/examples/Phone Sensor Examples - Minimal/sound/02_sound_amplitude/sketch.js +118 -0
  43. package/examples/Phone Sensor Examples - Minimal/sound/02_sound_amplitude/tracks/audio1.mp3 +0 -0
  44. package/examples/Phone Sensor Examples - Minimal/touch/01_touch_basic/index.html +18 -0
  45. package/examples/Phone Sensor Examples - Minimal/touch/01_touch_basic/sketch.js +58 -0
  46. package/examples/Phone Sensor Examples - Minimal/touch/02_touch_zones/index.html +18 -0
  47. package/examples/Phone Sensor Examples - Minimal/touch/02_touch_zones/sketch.js +78 -0
  48. package/examples/Phone Sensor Examples - Minimal/touch/03_touch_count/index.html +18 -0
  49. package/examples/Phone Sensor Examples - Minimal/touch/03_touch_count/sketch.js +64 -0
  50. package/examples/Phone Sensor Examples - Minimal/touch/04_touch_distance/index.html +18 -0
  51. package/examples/Phone Sensor Examples - Minimal/touch/04_touch_distance/sketch.js +69 -0
  52. package/examples/Phone Sensor Examples - Minimal/touch/05_touch_angle/index.html +18 -0
  53. package/examples/Phone Sensor Examples - Minimal/touch/05_touch_angle/sketch.js +85 -0
  54. package/examples/Phone and Gif/collision/README.md +31 -0
  55. Gif/collision/gifs/spaceSuit2.png +0 -0
  56. package/examples/Phone and Gif/collision/index.html +19 -0
  57. package/examples/Phone and Gif/collision/sketch.js +226 -0
  58. Gif/fetch/gifs/corgiswimflip.gif +0 -0
  59. package/examples/Phone and Gif/fetch/index.html +18 -0
  60. package/examples/Phone and Gif/fetch/sketch.js +139 -0
  61. Gif/fly/gifs/comparison.gif +0 -0
  62. package/examples/Phone and Gif/fly/index.html +18 -0
  63. package/examples/Phone and Gif/fly/sketch.js +103 -0
  64. Gif/roll/gifs/how-penciles-are-made.gif +0 -0
  65. package/examples/Phone and Gif/roll/index.html +18 -0
  66. package/examples/Phone and Gif/roll/sketch.js +121 -0
  67. package/examples/UXcompare/button-vs-movement/index.html +45 -0
  68. package/examples/UXcompare/button-vs-movement/sketch.js +355 -0
  69. package/examples/UXcompare/button-vs-orientation/index.html +25 -0
  70. package/examples/UXcompare/button-vs-orientation/sketch.js +317 -0
  71. package/examples/UXcompare/button-vs-shake/index.html +45 -0
  72. package/examples/UXcompare/button-vs-shake/sketch.js +320 -0
  73. package/examples/UXcompare/gyroscope-demo/index.html +78 -0
  74. package/examples/UXcompare/gyroscope-demo/sketch.js +166 -0
  75. package/examples/UXcompare/index.html +419 -0
  76. package/examples/UXcompare/microphone-demo/index.html +79 -0
  77. package/examples/UXcompare/microphone-demo/sketch.js +210 -0
  78. package/examples/UXcompare/slider-vs-angle/index.html +25 -0
  79. package/examples/UXcompare/slider-vs-angle/sketch.js +429 -0
  80. package/examples/UXcompare/slider-vs-distance/index.html +25 -0
  81. package/examples/UXcompare/slider-vs-distance/sketch.js +401 -0
  82. package/examples/UXcompare/slider-vs-microphone/index.html +26 -0
  83. package/examples/UXcompare/slider-vs-microphone/sketch.js +336 -0
  84. package/examples/UXcompare/slider-vs-touches/index.html +25 -0
  85. package/examples/UXcompare/slider-vs-touches/sketch.js +376 -0
  86. package/examples/UXcompare/sliders-vs-acceleration/index.html +25 -0
  87. package/examples/UXcompare/sliders-vs-acceleration/sketch.js +361 -0
  88. package/examples/UXcompare/sliders-vs-rotation/index.html +25 -0
  89. package/examples/UXcompare/sliders-vs-rotation/sketch.js +375 -0
  90. package/examples/blankTemplate/index.html +31 -0
  91. package/examples/blankTemplate/sketch.js +55 -0
  92. package/examples/homepage/index.html +506 -0
  93. package/package.json +73 -0
  94. package/src/p5-phone.js +1062 -0
  95. package/src/permissionMic.js +240 -0
  96. package/src/permissionsGesture.js +213 -0
  97. package/src/permissionsGyro.js +246 -0
@@ -0,0 +1,240 @@
1
+ // =============================================
2
+ // MICROPHONE PERMISSIONS & GESTURE HANDLING
3
+ // For projects that only need microphone/audio input
4
+ // Students don't need to modify this
5
+ // =============================================
6
+
7
+ // Global flag for sketch.js to check
8
+ window.micEnabled = false;
9
+
10
+ // Store references
11
+ let startButton;
12
+ let statusText;
13
+
14
+ // =========================================
15
+ // INITIALIZATION
16
+ // =========================================
17
+ document.addEventListener('DOMContentLoaded', function() {
18
+ startButton = document.getElementById('startButton');
19
+ statusText = document.getElementById('statusText');
20
+
21
+ // Add click event listener to start button
22
+ startButton.addEventListener('click', handleMicrophonePermissionRequest);
23
+
24
+ // Initialize other event listeners
25
+ initializeGestureBlocking();
26
+ initializeP5TouchOverrides();
27
+ });
28
+
29
+ // =========================================
30
+ // MICROPHONE PERMISSION HANDLING
31
+ // =========================================
32
+ async function handleMicrophonePermissionRequest() {
33
+ startButton.classList.add('hidden');
34
+ statusText.classList.remove('hidden');
35
+ statusText.textContent = 'Requesting microphone permissions...';
36
+
37
+ try {
38
+ // Start audio context
39
+ statusText.textContent = 'Enabling audio input...';
40
+
41
+ // Handle p5.sound
42
+ if (typeof userStartAudio !== 'undefined') {
43
+ await userStartAudio();
44
+
45
+ // If there's a global mic object created by sketch.js, start it
46
+ if (typeof mic !== 'undefined' && mic && mic.start) {
47
+ statusText.textContent = 'Starting microphone...';
48
+ mic.start();
49
+ window.micEnabled = true;
50
+ console.log('Microphone enabled. Use mic.getLevel() to get audio input level.');
51
+ } else {
52
+ console.log('No microphone object found. Create one in sketch.js with: mic = new p5.AudioIn();');
53
+ }
54
+ } else {
55
+ console.log('p5.sound not detected. Make sure p5.sound.js is loaded.');
56
+ }
57
+
58
+ // Hide status text
59
+ statusText.classList.add('hidden');
60
+
61
+ // Call setup again if it exists (to reinitialize with permissions)
62
+ if (typeof userSetupComplete === 'function') {
63
+ userSetupComplete();
64
+ }
65
+
66
+ } catch (error) {
67
+ console.error('Microphone permission error:', error);
68
+ statusText.textContent = 'Error accessing microphone: ' + error.message;
69
+
70
+ setTimeout(() => {
71
+ statusText.classList.add('hidden');
72
+ }, 3000);
73
+ }
74
+ }
75
+
76
+ // =========================================
77
+ // GESTURE PREVENTION INITIALIZATION
78
+ // =========================================
79
+ function initializeGestureBlocking() {
80
+ // Prevent back navigation
81
+ window.history.pushState(null, '', window.location.href);
82
+ window.onpopstate = function() {
83
+ window.history.pushState(null, '', window.location.href);
84
+ };
85
+
86
+ // Warn before leaving
87
+ window.addEventListener('beforeunload', function(e) {
88
+ e.preventDefault();
89
+ e.returnValue = '';
90
+ });
91
+
92
+ // Initialize edge swipe prevention
93
+ initializeEdgeSwipePrevention();
94
+
95
+ // Initialize other gesture prevention
96
+ initializeOtherGesturePrevention();
97
+ }
98
+
99
+ // =========================================
100
+ // EDGE SWIPE PREVENTION
101
+ // =========================================
102
+ function initializeEdgeSwipePrevention() {
103
+ let touchStartX = 0;
104
+ let touchStartY = 0;
105
+ const edgeThreshold = 20;
106
+
107
+ document.addEventListener('touchstart', function(e) {
108
+ if (e.touches && e.touches.length > 0) {
109
+ touchStartX = e.touches[0].clientX;
110
+ touchStartY = e.touches[0].clientY;
111
+
112
+ // Prevent edge swipes
113
+ if (touchStartX < edgeThreshold ||
114
+ touchStartX > window.innerWidth - edgeThreshold) {
115
+ e.preventDefault();
116
+ }
117
+ }
118
+ }, { passive: false, capture: true });
119
+
120
+ document.addEventListener('touchmove', function(e) {
121
+ if (!e.touches || e.touches.length === 0) return;
122
+
123
+ let currentX = e.touches[0].clientX;
124
+ let currentY = e.touches[0].clientY;
125
+ let deltaX = currentX - touchStartX;
126
+ let deltaY = currentY - touchStartY;
127
+
128
+ // Prevent horizontal edge swipes (back/forward)
129
+ if ((touchStartX < edgeThreshold && deltaX > 0) ||
130
+ (touchStartX > window.innerWidth - edgeThreshold && deltaX < 0)) {
131
+ e.preventDefault();
132
+ e.stopPropagation();
133
+ }
134
+
135
+ // Prevent pull-to-refresh
136
+ if (window.pageYOffset === 0 && deltaY > 0) {
137
+ e.preventDefault();
138
+ }
139
+
140
+ // Always prevent on canvas
141
+ if (e.target && e.target.tagName === 'CANVAS') {
142
+ e.preventDefault();
143
+ }
144
+ }, { passive: false, capture: true });
145
+ }
146
+
147
+ // =========================================
148
+ // OTHER GESTURE PREVENTION
149
+ // =========================================
150
+ function initializeOtherGesturePrevention() {
151
+ // Prevent pinch zoom
152
+ document.addEventListener('gesturestart', function(e) {
153
+ e.preventDefault();
154
+ });
155
+
156
+ document.addEventListener('gesturechange', function(e) {
157
+ e.preventDefault();
158
+ });
159
+
160
+ document.addEventListener('gestureend', function(e) {
161
+ e.preventDefault();
162
+ });
163
+
164
+ // Prevent double-tap zoom
165
+ let lastTouchEnd = 0;
166
+ document.addEventListener('touchend', function(e) {
167
+ const now = Date.now();
168
+ if (now - lastTouchEnd <= 300) {
169
+ e.preventDefault();
170
+ }
171
+ lastTouchEnd = now;
172
+ }, false);
173
+
174
+ // Prevent long-press context menu
175
+ window.oncontextmenu = function(e) {
176
+ e.preventDefault();
177
+ e.stopPropagation();
178
+ return false;
179
+ };
180
+ }
181
+
182
+ // =========================================
183
+ // P5.JS GESTURE OVERRIDE HELPERS
184
+ // =========================================
185
+ function initializeP5TouchOverrides() {
186
+ // Wait for p5 to be ready
187
+ setTimeout(() => {
188
+ if (window._setupDone) {
189
+ overrideP5Touch();
190
+ } else {
191
+ // Try again after setup
192
+ const checkP5 = setInterval(() => {
193
+ if (window._setupDone) {
194
+ overrideP5Touch();
195
+ clearInterval(checkP5);
196
+ }
197
+ }, 100);
198
+ }
199
+ }, 100);
200
+ }
201
+
202
+ function overrideP5Touch() {
203
+ const origTouchStarted = window.touchStarted || function() {};
204
+ const origTouchMoved = window.touchMoved || function() {};
205
+ const origTouchEnded = window.touchEnded || function() {};
206
+ const origMousePressed = window.mousePressed || function() {};
207
+ const origMouseDragged = window.mouseDragged || function() {};
208
+ const origMouseReleased = window.mouseReleased || function() {};
209
+
210
+ // Ensure all touch functions return false
211
+ window.touchStarted = function(e) {
212
+ origTouchStarted(e);
213
+ return false;
214
+ };
215
+
216
+ window.touchMoved = function(e) {
217
+ origTouchMoved(e);
218
+ return false;
219
+ };
220
+
221
+ window.touchEnded = function(e) {
222
+ origTouchEnded(e);
223
+ return false;
224
+ };
225
+
226
+ window.mousePressed = function(e) {
227
+ origMousePressed(e);
228
+ return false;
229
+ };
230
+
231
+ window.mouseDragged = function(e) {
232
+ origMouseDragged(e);
233
+ return false;
234
+ };
235
+
236
+ window.mouseReleased = function(e) {
237
+ origMouseReleased(e);
238
+ return false;
239
+ };
240
+ }
@@ -0,0 +1,213 @@
1
+ // =============================================
2
+ // GESTURE BLOCKING ONLY
3
+ // For projects that only need touch input and gesture prevention
4
+ // No sensor or microphone permissions requested
5
+ // Students don't need to modify this
6
+ // =============================================
7
+
8
+ // Store references
9
+ let startButton;
10
+ let statusText;
11
+
12
+ // =========================================
13
+ // INITIALIZATION
14
+ // =========================================
15
+ document.addEventListener('DOMContentLoaded', function() {
16
+ startButton = document.getElementById('startButton');
17
+ statusText = document.getElementById('statusText');
18
+
19
+ // Add click event listener to start button
20
+ startButton.addEventListener('click', handleGestureOnlySetup);
21
+
22
+ // Initialize gesture blocking immediately
23
+ initializeGestureBlocking();
24
+ initializeP5TouchOverrides();
25
+ });
26
+
27
+ // =========================================
28
+ // GESTURE-ONLY SETUP
29
+ // =========================================
30
+ function handleGestureOnlySetup() {
31
+ startButton.classList.add('hidden');
32
+ statusText.classList.remove('hidden');
33
+ statusText.textContent = 'Enabling touch input...';
34
+
35
+ // No permissions needed, just hide the button and enable touch
36
+ console.log('Gesture blocking enabled. Touch input available: touchX, touchY, touches[], mouseX, mouseY');
37
+
38
+ // Hide status text after brief moment
39
+ setTimeout(() => {
40
+ statusText.classList.add('hidden');
41
+ }, 500);
42
+
43
+ // Call setup again if it exists (to reinitialize)
44
+ if (typeof userSetupComplete === 'function') {
45
+ userSetupComplete();
46
+ }
47
+ }
48
+
49
+ // =========================================
50
+ // GESTURE PREVENTION INITIALIZATION
51
+ // =========================================
52
+ function initializeGestureBlocking() {
53
+ // Prevent back navigation
54
+ window.history.pushState(null, '', window.location.href);
55
+ window.onpopstate = function() {
56
+ window.history.pushState(null, '', window.location.href);
57
+ };
58
+
59
+ // Warn before leaving
60
+ window.addEventListener('beforeunload', function(e) {
61
+ e.preventDefault();
62
+ e.returnValue = '';
63
+ });
64
+
65
+ // Initialize edge swipe prevention
66
+ initializeEdgeSwipePrevention();
67
+
68
+ // Initialize other gesture prevention
69
+ initializeOtherGesturePrevention();
70
+ }
71
+
72
+ // =========================================
73
+ // EDGE SWIPE PREVENTION
74
+ // =========================================
75
+ function initializeEdgeSwipePrevention() {
76
+ let touchStartX = 0;
77
+ let touchStartY = 0;
78
+ const edgeThreshold = 20;
79
+
80
+ document.addEventListener('touchstart', function(e) {
81
+ if (e.touches && e.touches.length > 0) {
82
+ touchStartX = e.touches[0].clientX;
83
+ touchStartY = e.touches[0].clientY;
84
+
85
+ // Prevent edge swipes
86
+ if (touchStartX < edgeThreshold ||
87
+ touchStartX > window.innerWidth - edgeThreshold) {
88
+ e.preventDefault();
89
+ }
90
+ }
91
+ }, { passive: false, capture: true });
92
+
93
+ document.addEventListener('touchmove', function(e) {
94
+ if (!e.touches || e.touches.length === 0) return;
95
+
96
+ let currentX = e.touches[0].clientX;
97
+ let currentY = e.touches[0].clientY;
98
+ let deltaX = currentX - touchStartX;
99
+ let deltaY = currentY - touchStartY;
100
+
101
+ // Prevent horizontal edge swipes (back/forward)
102
+ if ((touchStartX < edgeThreshold && deltaX > 0) ||
103
+ (touchStartX > window.innerWidth - edgeThreshold && deltaX < 0)) {
104
+ e.preventDefault();
105
+ e.stopPropagation();
106
+ }
107
+
108
+ // Prevent pull-to-refresh
109
+ if (window.pageYOffset === 0 && deltaY > 0) {
110
+ e.preventDefault();
111
+ }
112
+
113
+ // Always prevent on canvas
114
+ if (e.target && e.target.tagName === 'CANVAS') {
115
+ e.preventDefault();
116
+ }
117
+ }, { passive: false, capture: true });
118
+ }
119
+
120
+ // =========================================
121
+ // OTHER GESTURE PREVENTION
122
+ // =========================================
123
+ function initializeOtherGesturePrevention() {
124
+ // Prevent pinch zoom
125
+ document.addEventListener('gesturestart', function(e) {
126
+ e.preventDefault();
127
+ });
128
+
129
+ document.addEventListener('gesturechange', function(e) {
130
+ e.preventDefault();
131
+ });
132
+
133
+ document.addEventListener('gestureend', function(e) {
134
+ e.preventDefault();
135
+ });
136
+
137
+ // Prevent double-tap zoom
138
+ let lastTouchEnd = 0;
139
+ document.addEventListener('touchend', function(e) {
140
+ const now = Date.now();
141
+ if (now - lastTouchEnd <= 300) {
142
+ e.preventDefault();
143
+ }
144
+ lastTouchEnd = now;
145
+ }, false);
146
+
147
+ // Prevent long-press context menu
148
+ window.oncontextmenu = function(e) {
149
+ e.preventDefault();
150
+ e.stopPropagation();
151
+ return false;
152
+ };
153
+ }
154
+
155
+ // =========================================
156
+ // P5.JS GESTURE OVERRIDE HELPERS
157
+ // =========================================
158
+ function initializeP5TouchOverrides() {
159
+ // Wait for p5 to be ready
160
+ setTimeout(() => {
161
+ if (window._setupDone) {
162
+ overrideP5Touch();
163
+ } else {
164
+ // Try again after setup
165
+ const checkP5 = setInterval(() => {
166
+ if (window._setupDone) {
167
+ overrideP5Touch();
168
+ clearInterval(checkP5);
169
+ }
170
+ }, 100);
171
+ }
172
+ }, 100);
173
+ }
174
+
175
+ function overrideP5Touch() {
176
+ const origTouchStarted = window.touchStarted || function() {};
177
+ const origTouchMoved = window.touchMoved || function() {};
178
+ const origTouchEnded = window.touchEnded || function() {};
179
+ const origMousePressed = window.mousePressed || function() {};
180
+ const origMouseDragged = window.mouseDragged || function() {};
181
+ const origMouseReleased = window.mouseReleased || function() {};
182
+
183
+ // Ensure all touch functions return false
184
+ window.touchStarted = function(e) {
185
+ origTouchStarted(e);
186
+ return false;
187
+ };
188
+
189
+ window.touchMoved = function(e) {
190
+ origTouchMoved(e);
191
+ return false;
192
+ };
193
+
194
+ window.touchEnded = function(e) {
195
+ origTouchEnded(e);
196
+ return false;
197
+ };
198
+
199
+ window.mousePressed = function(e) {
200
+ origMousePressed(e);
201
+ return false;
202
+ };
203
+
204
+ window.mouseDragged = function(e) {
205
+ origMouseDragged(e);
206
+ return false;
207
+ };
208
+
209
+ window.mouseReleased = function(e) {
210
+ origMouseReleased(e);
211
+ return false;
212
+ };
213
+ }
@@ -0,0 +1,246 @@
1
+ // =============================================
2
+ // GYROSCOPE/ACCELEROMETER PERMISSIONS & GESTURE HANDLING
3
+ // For projects that only need motion/orientation sensor data
4
+ // Students don't need to modify this
5
+ // =============================================
6
+
7
+ // Global flag for sketch.js to check
8
+ window.sensorsEnabled = false;
9
+
10
+ // Store references
11
+ let startButton;
12
+ let statusText;
13
+
14
+ // =========================================
15
+ // INITIALIZATION
16
+ // =========================================
17
+ document.addEventListener('DOMContentLoaded', function() {
18
+ startButton = document.getElementById('startButton');
19
+ statusText = document.getElementById('statusText');
20
+
21
+ // Add click event listener to start button
22
+ startButton.addEventListener('click', handleGyroPermissionRequest);
23
+
24
+ // Initialize other event listeners
25
+ initializeGestureBlocking();
26
+ initializeP5TouchOverrides();
27
+ });
28
+
29
+ // =========================================
30
+ // GYROSCOPE/ACCELEROMETER PERMISSION HANDLING
31
+ // =========================================
32
+ async function handleGyroPermissionRequest() {
33
+ startButton.classList.add('hidden');
34
+ statusText.classList.remove('hidden');
35
+ statusText.textContent = 'Requesting motion sensor permissions...';
36
+
37
+ try {
38
+ // Request motion sensor permissions (iOS 13+)
39
+ if (typeof DeviceOrientationEvent !== 'undefined' &&
40
+ typeof DeviceOrientationEvent.requestPermission === 'function') {
41
+
42
+ statusText.textContent = 'Requesting gyroscope access...';
43
+
44
+ const orientationPermission = await DeviceOrientationEvent.requestPermission();
45
+ console.log('Orientation permission:', orientationPermission);
46
+
47
+ if (typeof DeviceMotionEvent !== 'undefined' &&
48
+ typeof DeviceMotionEvent.requestPermission === 'function') {
49
+
50
+ statusText.textContent = 'Requesting accelerometer access...';
51
+ const motionPermission = await DeviceMotionEvent.requestPermission();
52
+ console.log('Motion permission:', motionPermission);
53
+ }
54
+ }
55
+
56
+ // Mark sensors as enabled
57
+ window.sensorsEnabled = true;
58
+
59
+ // Hide status text
60
+ statusText.classList.add('hidden');
61
+
62
+ console.log('Motion sensors enabled. Available data: rotationX, rotationY, rotationZ, accelerationX, accelerationY, accelerationZ');
63
+
64
+ // Call setup again if it exists (to reinitialize with permissions)
65
+ if (typeof userSetupComplete === 'function') {
66
+ userSetupComplete();
67
+ }
68
+
69
+ } catch (error) {
70
+ console.error('Motion sensor permission error:', error);
71
+ statusText.textContent = 'Error accessing motion sensors: ' + error.message;
72
+
73
+ // Still enable what we can
74
+ window.sensorsEnabled = true;
75
+
76
+ setTimeout(() => {
77
+ statusText.classList.add('hidden');
78
+ }, 3000);
79
+ }
80
+ }
81
+
82
+ // =========================================
83
+ // GESTURE PREVENTION INITIALIZATION
84
+ // =========================================
85
+ function initializeGestureBlocking() {
86
+ // Prevent back navigation
87
+ window.history.pushState(null, '', window.location.href);
88
+ window.onpopstate = function() {
89
+ window.history.pushState(null, '', window.location.href);
90
+ };
91
+
92
+ // Warn before leaving
93
+ window.addEventListener('beforeunload', function(e) {
94
+ e.preventDefault();
95
+ e.returnValue = '';
96
+ });
97
+
98
+ // Initialize edge swipe prevention
99
+ initializeEdgeSwipePrevention();
100
+
101
+ // Initialize other gesture prevention
102
+ initializeOtherGesturePrevention();
103
+ }
104
+
105
+ // =========================================
106
+ // EDGE SWIPE PREVENTION
107
+ // =========================================
108
+ function initializeEdgeSwipePrevention() {
109
+ let touchStartX = 0;
110
+ let touchStartY = 0;
111
+ const edgeThreshold = 20;
112
+
113
+ document.addEventListener('touchstart', function(e) {
114
+ if (e.touches && e.touches.length > 0) {
115
+ touchStartX = e.touches[0].clientX;
116
+ touchStartY = e.touches[0].clientY;
117
+
118
+ // Prevent edge swipes
119
+ if (touchStartX < edgeThreshold ||
120
+ touchStartX > window.innerWidth - edgeThreshold) {
121
+ e.preventDefault();
122
+ }
123
+ }
124
+ }, { passive: false, capture: true });
125
+
126
+ document.addEventListener('touchmove', function(e) {
127
+ if (!e.touches || e.touches.length === 0) return;
128
+
129
+ let currentX = e.touches[0].clientX;
130
+ let currentY = e.touches[0].clientY;
131
+ let deltaX = currentX - touchStartX;
132
+ let deltaY = currentY - touchStartY;
133
+
134
+ // Prevent horizontal edge swipes (back/forward)
135
+ if ((touchStartX < edgeThreshold && deltaX > 0) ||
136
+ (touchStartX > window.innerWidth - edgeThreshold && deltaX < 0)) {
137
+ e.preventDefault();
138
+ e.stopPropagation();
139
+ }
140
+
141
+ // Prevent pull-to-refresh
142
+ if (window.pageYOffset === 0 && deltaY > 0) {
143
+ e.preventDefault();
144
+ }
145
+
146
+ // Always prevent on canvas
147
+ if (e.target && e.target.tagName === 'CANVAS') {
148
+ e.preventDefault();
149
+ }
150
+ }, { passive: false, capture: true });
151
+ }
152
+
153
+ // =========================================
154
+ // OTHER GESTURE PREVENTION
155
+ // =========================================
156
+ function initializeOtherGesturePrevention() {
157
+ // Prevent pinch zoom
158
+ document.addEventListener('gesturestart', function(e) {
159
+ e.preventDefault();
160
+ });
161
+
162
+ document.addEventListener('gesturechange', function(e) {
163
+ e.preventDefault();
164
+ });
165
+
166
+ document.addEventListener('gestureend', function(e) {
167
+ e.preventDefault();
168
+ });
169
+
170
+ // Prevent double-tap zoom
171
+ let lastTouchEnd = 0;
172
+ document.addEventListener('touchend', function(e) {
173
+ const now = Date.now();
174
+ if (now - lastTouchEnd <= 300) {
175
+ e.preventDefault();
176
+ }
177
+ lastTouchEnd = now;
178
+ }, false);
179
+
180
+ // Prevent long-press context menu
181
+ window.oncontextmenu = function(e) {
182
+ e.preventDefault();
183
+ e.stopPropagation();
184
+ return false;
185
+ };
186
+ }
187
+
188
+ // =========================================
189
+ // P5.JS GESTURE OVERRIDE HELPERS
190
+ // =========================================
191
+ function initializeP5TouchOverrides() {
192
+ // Wait for p5 to be ready
193
+ setTimeout(() => {
194
+ if (window._setupDone) {
195
+ overrideP5Touch();
196
+ } else {
197
+ // Try again after setup
198
+ const checkP5 = setInterval(() => {
199
+ if (window._setupDone) {
200
+ overrideP5Touch();
201
+ clearInterval(checkP5);
202
+ }
203
+ }, 100);
204
+ }
205
+ }, 100);
206
+ }
207
+
208
+ function overrideP5Touch() {
209
+ const origTouchStarted = window.touchStarted || function() {};
210
+ const origTouchMoved = window.touchMoved || function() {};
211
+ const origTouchEnded = window.touchEnded || function() {};
212
+ const origMousePressed = window.mousePressed || function() {};
213
+ const origMouseDragged = window.mouseDragged || function() {};
214
+ const origMouseReleased = window.mouseReleased || function() {};
215
+
216
+ // Ensure all touch functions return false
217
+ window.touchStarted = function(e) {
218
+ origTouchStarted(e);
219
+ return false;
220
+ };
221
+
222
+ window.touchMoved = function(e) {
223
+ origTouchMoved(e);
224
+ return false;
225
+ };
226
+
227
+ window.touchEnded = function(e) {
228
+ origTouchEnded(e);
229
+ return false;
230
+ };
231
+
232
+ window.mousePressed = function(e) {
233
+ origMousePressed(e);
234
+ return false;
235
+ };
236
+
237
+ window.mouseDragged = function(e) {
238
+ origMouseDragged(e);
239
+ return false;
240
+ };
241
+
242
+ window.mouseReleased = function(e) {
243
+ origMouseReleased(e);
244
+ return false;
245
+ };
246
+ }