p5-phone 1.7.0 → 1.8.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 +34 -9
- package/dist/p5-phone.js +105 -18
- package/dist/p5-phone.min.js +1 -1
- package/examples/Phone Sensor Examples/microphone/01_mic_level/sketch.js +3 -3
- package/examples/Phone Sensor Examples/microphone/02_speech_recognition/README.md +1 -1
- package/examples/Phone Sensor Examples/microphone/02_speech_recognition/sketch.js +2 -2
- package/examples/Phone Sensor Examples/movement/01_orientation_basic/index.html +1 -0
- package/examples/Phone Sensor Examples/movement/01_orientation_basic/sketch.js +3 -3
- package/examples/Phone Sensor Examples/movement/02_rotational_velocity/index.html +1 -0
- package/examples/Phone Sensor Examples/movement/02_rotational_velocity/sketch.js +3 -3
- package/examples/Phone Sensor Examples/movement/03_acceleration/index.html +1 -0
- package/examples/Phone Sensor Examples/movement/03_acceleration/sketch.js +3 -3
- package/examples/Phone Sensor Examples/sound/01_dual_audio/index.html +1 -0
- package/examples/Phone Sensor Examples/sound/01_dual_audio/sketch.js +5 -5
- package/examples/Phone Sensor Examples/sound/02_volume_touches/index.html +1 -0
- package/examples/Phone Sensor Examples/sound/02_volume_touches/sketch.js +7 -7
- package/examples/Phone Sensor Examples/touch/01_touch_basic/index.html +1 -0
- package/examples/Phone Sensor Examples/touch/01_touch_basic/sketch.js +4 -4
- package/examples/Phone Sensor Examples/touch/02_touch_zones/index.html +1 -0
- package/examples/Phone Sensor Examples/touch/02_touch_zones/sketch.js +3 -3
- package/examples/Phone Sensor Examples/touch/03_touch_count/index.html +1 -0
- package/examples/Phone Sensor Examples/touch/03_touch_count/sketch.js +3 -3
- package/examples/Phone Sensor Examples/touch/04_touch_distance/index.html +1 -0
- package/examples/Phone Sensor Examples/touch/04_touch_distance/sketch.js +3 -3
- package/examples/Phone Sensor Examples/touch/05_touch_angle/index.html +1 -0
- package/examples/Phone Sensor Examples/touch/05_touch_angle/sketch.js +3 -3
- package/examples/Phone Sensor Examples/vibration/01_haptic_feedback/index.html +1 -0
- package/examples/Phone Sensor Examples/vibration/01_haptic_feedback/sketch.js +3 -3
- package/examples/Phone Sensor Examples - Minimal/sound/01_sound_basic/sketch.js +2 -2
- package/examples/Phone Sensor Examples - Minimal/sound/02_sound_amplitude/sketch.js +2 -2
- package/examples/Phone Sensor Examples - Minimal/touch/01_touch_basic/sketch.js +2 -2
- package/examples/Phone Sensor Examples - Minimal/touch/02_touch_zones/sketch.js +2 -2
- package/examples/Phone Sensor Examples - Minimal/touch/03_touch_count/sketch.js +2 -2
- package/examples/Phone Sensor Examples - Minimal/touch/04_touch_distance/sketch.js +2 -2
- package/examples/Phone Sensor Examples - Minimal/touch/05_touch_angle/sketch.js +2 -2
- package/examples/Phone Sensor Examples - Minimal/vibration/01_haptic_feedback/sketch.js +2 -2
- package/examples/Phone and Gif/collision/sketch.js +3 -3
- package/examples/Phone and Gif/fetch/sketch.js +3 -3
- package/examples/Phone and Gif/roll/sketch.js +3 -3
- package/examples/UIStyles/banner-style/index.html +1 -0
- package/examples/UIStyles/canvas-style/index.html +1 -0
- package/examples/UIStyles/custom-element/index.html +1 -0
- package/examples/UXcompare/button-vs-movement/index.html +1 -0
- package/examples/UXcompare/button-vs-orientation/index.html +1 -0
- package/examples/UXcompare/button-vs-shake/index.html +1 -0
- package/examples/UXcompare/gyroscope-demo/index.html +1 -0
- package/examples/UXcompare/microphone-demo/index.html +1 -0
- package/examples/UXcompare/slider-vs-angle/index.html +1 -0
- package/examples/UXcompare/slider-vs-angle/sketch.js +3 -3
- package/examples/UXcompare/slider-vs-distance/index.html +1 -0
- package/examples/UXcompare/slider-vs-distance/sketch.js +3 -3
- package/examples/UXcompare/slider-vs-microphone/index.html +1 -0
- package/examples/UXcompare/slider-vs-microphone/sketch.js +3 -3
- package/examples/UXcompare/slider-vs-touches/index.html +1 -0
- package/examples/UXcompare/slider-vs-touches/sketch.js +3 -3
- package/examples/UXcompare/sliders-vs-acceleration/index.html +1 -0
- package/examples/UXcompare/sliders-vs-acceleration/sketch.js +3 -3
- package/examples/UXcompare/sliders-vs-rotation/index.html +1 -0
- package/examples/UXcompare/sliders-vs-rotation/sketch.js +3 -3
- package/examples/blankTemplate/index.html +1 -0
- package/examples/blankTemplate/sketch.js +2 -2
- package/examples/homepage/index.html +5 -4
- package/examples/ml5/Gaze_detector_class/index.html +1 -0
- package/examples/ml5/PHONE_BodyPose_two_points/index.html +1 -0
- package/examples/ml5/PHONE_FaceMesh_two_points/index.html +1 -0
- package/examples/ml5/PHONE_HandPose_two_points/index.html +1 -0
- package/package.json +1 -1
- package/src/p5-phone.js +105 -18
package/README.md
CHANGED
|
@@ -17,9 +17,11 @@ That's where this library comes in:
|
|
|
17
17
|
|
|
18
18
|
This library simplifies access to the following p5.js mobile sensor and audio commands:
|
|
19
19
|
|
|
20
|
-
**Touch Events:**
|
|
21
|
-
- [`
|
|
22
|
-
- [`
|
|
20
|
+
**Touch/Pointer Events:**
|
|
21
|
+
- [`mousePressed()`](https://p5js.org/reference/p5/mousePressed/) - Called when a press/touch begins (works for both mouse and touch in p5.js 1.x and 2.0)
|
|
22
|
+
- [`mouseReleased()`](https://p5js.org/reference/p5/mouseReleased/) - Called when a press/touch ends (works for both mouse and touch in p5.js 1.x and 2.0)
|
|
23
|
+
- [`touchStarted()`](https://p5js.org/reference/p5/touchStarted/) - Called when a touch begins (p5.js 1.x only)
|
|
24
|
+
- [`touchEnded()`](https://p5js.org/reference/p5/touchEnded/) - Called when a touch ends (p5.js 1.x only)
|
|
23
25
|
|
|
24
26
|
**Device Motion & Orientation:**
|
|
25
27
|
- [`rotationX`](https://p5js.org/reference/p5/rotationX/) - Device tilt forward/backward
|
|
@@ -45,10 +47,31 @@ This library simplifies access to the following p5.js mobile sensor and audio co
|
|
|
45
47
|
- Safari 13+
|
|
46
48
|
- Firefox 75+
|
|
47
49
|
|
|
50
|
+
## p5.js Version Compatibility
|
|
51
|
+
|
|
52
|
+
p5-phone supports both **p5.js 1.x** and **p5.js 2.0+**.
|
|
53
|
+
|
|
54
|
+
| Feature | p5.js 1.x | p5.js 2.0+ |
|
|
55
|
+
|---------|-----------|------------|
|
|
56
|
+
| Permission UI (Tap/Button/Canvas/Banner/Custom) | ✅ | ✅ |
|
|
57
|
+
| Motion sensors (rotationX/Y/Z, accelerationX/Y/Z) | ✅ | ✅ |
|
|
58
|
+
| Microphone / Speech / Sound | ✅ | ✅ |
|
|
59
|
+
| Camera (PhoneCamera) | ✅ | ✅ |
|
|
60
|
+
| Vibration | ✅ | ✅ |
|
|
61
|
+
| Debug console | ✅ | ✅ |
|
|
62
|
+
| lockGestures() | ✅ | ✅ |
|
|
63
|
+
| `touchStarted()` / `touchEnded()` | ✅ | ❌ Use `mousePressed()` / `mouseReleased()` |
|
|
64
|
+
| `p5.registerAddon()` | ❌ | ✅ (auto-detected) |
|
|
65
|
+
|
|
66
|
+
**Key change in p5.js 2.0:** Touch-specific callbacks (`touchStarted`, `touchMoved`, `touchEnded`) are no longer dispatched. The unified Pointer API routes all input (mouse + touch) through `mousePressed()`, `mouseDragged()`, and `mouseReleased()`. These mouse callbacks work in **both** p5.js 1.x and 2.0, so use them for forward-compatible code.
|
|
67
|
+
|
|
68
|
+
p5-phone automatically detects the p5.js version and adjusts its internal touch override behavior accordingly. No configuration needed.
|
|
69
|
+
|
|
48
70
|
## Table of Contents
|
|
49
71
|
|
|
50
72
|
- [Link for Interactive Examples](#link-for-interactive-examples)
|
|
51
73
|
- [Browser Compatibility](#browser-compatibility)
|
|
74
|
+
- [p5.js Version Compatibility](#p5js-version-compatibility)
|
|
52
75
|
- [CDN (Recommended)](#cdn-recommended)
|
|
53
76
|
- [Basic Setup](#basic-setup)
|
|
54
77
|
- [Index HTML](#index-html)
|
|
@@ -77,10 +100,10 @@ This library simplifies access to the following p5.js mobile sensor and audio co
|
|
|
77
100
|
|
|
78
101
|
```html
|
|
79
102
|
<!-- Minified version (recommended) -->
|
|
80
|
-
<script src="https://cdn.jsdelivr.net/npm/p5-phone@1.
|
|
103
|
+
<script src="https://cdn.jsdelivr.net/npm/p5-phone@1.8.0/dist/p5-phone.min.js"></script>
|
|
81
104
|
|
|
82
105
|
<!-- Development version (larger, with comments) -->
|
|
83
|
-
<!-- <script src="https://cdn.jsdelivr.net/npm/p5-phone@1.
|
|
106
|
+
<!-- <script src="https://cdn.jsdelivr.net/npm/p5-phone@1.8.0/dist/p5-phone.js"></script> -->
|
|
84
107
|
```
|
|
85
108
|
|
|
86
109
|
### Basic Setup
|
|
@@ -106,9 +129,10 @@ This library simplifies access to the following p5.js mobile sensor and audio co
|
|
|
106
129
|
|
|
107
130
|
<!-- Load p5.js library -->
|
|
108
131
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/p5.min.js"></script>
|
|
132
|
+
<!-- For p5.js 2.0: <script src="https://cdn.jsdelivr.net/npm/p5@2/lib/p5.min.js"></script> -->
|
|
109
133
|
|
|
110
134
|
<!-- Load p5-phone library -->
|
|
111
|
-
<script src="https://cdn.jsdelivr.net/npm/p5-phone@1.
|
|
135
|
+
<script src="https://cdn.jsdelivr.net/npm/p5-phone@1.8.0/dist/p5-phone.min.js"></script>
|
|
112
136
|
|
|
113
137
|
</head>
|
|
114
138
|
<body>
|
|
@@ -173,11 +197,12 @@ function draw() {
|
|
|
173
197
|
}
|
|
174
198
|
|
|
175
199
|
// Prevent default touch behavior (optional but recommended)
|
|
176
|
-
|
|
200
|
+
// Use mousePressed/mouseReleased — works in both p5.js 1.x and 2.0
|
|
201
|
+
function mousePressed() {
|
|
177
202
|
return false;
|
|
178
203
|
}
|
|
179
204
|
|
|
180
|
-
function
|
|
205
|
+
function mouseReleased() {
|
|
181
206
|
return false;
|
|
182
207
|
}
|
|
183
208
|
```
|
|
@@ -580,7 +605,7 @@ function mousePressed() {
|
|
|
580
605
|
}
|
|
581
606
|
|
|
582
607
|
// Touch zones with different haptic patterns
|
|
583
|
-
function
|
|
608
|
+
function mousePressed() {
|
|
584
609
|
if (window.vibrationEnabled) {
|
|
585
610
|
if (mouseX < width/2) {
|
|
586
611
|
vibrate(50); // Left side - short pulse
|
package/dist/p5-phone.js
CHANGED
|
@@ -91,6 +91,12 @@ window.speechEnabled = false;
|
|
|
91
91
|
// Internal state
|
|
92
92
|
let _micInstance = null;
|
|
93
93
|
|
|
94
|
+
// p5.js version detection (1.x vs 2.x)
|
|
95
|
+
const _p5MajorVersion = (typeof p5 !== 'undefined' && p5.VERSION)
|
|
96
|
+
? parseInt(p5.VERSION.split('.')[0], 10)
|
|
97
|
+
: 1; // Default to 1 if p5 not loaded yet
|
|
98
|
+
const _isP5v2 = _p5MajorVersion >= 2;
|
|
99
|
+
|
|
94
100
|
// =========================================
|
|
95
101
|
// PUBLIC API - CALL THESE FROM YOUR P5 SKETCH
|
|
96
102
|
// =========================================
|
|
@@ -1141,29 +1147,37 @@ function _initializeP5TouchOverrides() {
|
|
|
1141
1147
|
}
|
|
1142
1148
|
|
|
1143
1149
|
function _overrideP5Touch() {
|
|
1144
|
-
const origTouchStarted = window.touchStarted || function() {};
|
|
1145
|
-
const origTouchMoved = window.touchMoved || function() {};
|
|
1146
|
-
const origTouchEnded = window.touchEnded || function() {};
|
|
1147
1150
|
const origMousePressed = window.mousePressed || function() {};
|
|
1148
1151
|
const origMouseDragged = window.mouseDragged || function() {};
|
|
1149
1152
|
const origMouseReleased = window.mouseReleased || function() {};
|
|
1150
1153
|
|
|
1151
|
-
//
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
origTouchMoved(
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1154
|
+
// In p5.js 2.0, touch and mouse are unified via Pointer API.
|
|
1155
|
+
// mousePressed/mouseDragged/mouseReleased fire for ALL pointer types (mouse + touch).
|
|
1156
|
+
// In p5.js 1.x, touchStarted/touchMoved/touchEnded are separate from mouse callbacks.
|
|
1157
|
+
// We wrap both sets for 1.x, and only mouse callbacks for 2.0.
|
|
1158
|
+
if (!_isP5v2) {
|
|
1159
|
+
// p5.js 1.x: also wrap touch-specific callbacks
|
|
1160
|
+
const origTouchStarted = window.touchStarted || function() {};
|
|
1161
|
+
const origTouchMoved = window.touchMoved || function() {};
|
|
1162
|
+
const origTouchEnded = window.touchEnded || function() {};
|
|
1163
|
+
|
|
1164
|
+
window.touchStarted = function(e) {
|
|
1165
|
+
origTouchStarted(e);
|
|
1166
|
+
return false;
|
|
1167
|
+
};
|
|
1168
|
+
|
|
1169
|
+
window.touchMoved = function(e) {
|
|
1170
|
+
origTouchMoved(e);
|
|
1171
|
+
return false;
|
|
1172
|
+
};
|
|
1173
|
+
|
|
1174
|
+
window.touchEnded = function(e) {
|
|
1175
|
+
origTouchEnded(e);
|
|
1176
|
+
return false;
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1166
1179
|
|
|
1180
|
+
// Mouse callbacks — work in both 1.x and 2.0
|
|
1167
1181
|
window.mousePressed = function(e) {
|
|
1168
1182
|
origMousePressed(e);
|
|
1169
1183
|
return false;
|
|
@@ -2215,4 +2229,77 @@ if (typeof p5 !== 'undefined' && p5.prototype) {
|
|
|
2215
2229
|
p5.prototype.debugWarn = debugWarn;
|
|
2216
2230
|
|
|
2217
2231
|
console.log('✅ Mobile p5.js Permissions: p5.prototype functions registered');
|
|
2232
|
+
}
|
|
2233
|
+
|
|
2234
|
+
// =========================================
|
|
2235
|
+
// P5.JS 2.0 ADDON REGISTRATION
|
|
2236
|
+
// =========================================
|
|
2237
|
+
|
|
2238
|
+
/**
|
|
2239
|
+
* Register as a p5.js 2.0 addon via p5.registerAddon().
|
|
2240
|
+
* This provides the modern lifecycle integration for p5.js 2.0+
|
|
2241
|
+
* while the p5.prototype block above handles 1.x compatibility.
|
|
2242
|
+
*/
|
|
2243
|
+
if (typeof p5 !== 'undefined' && typeof p5.registerAddon === 'function') {
|
|
2244
|
+
p5.registerAddon(function(p5, fn, lifecycles) {
|
|
2245
|
+
// Register all public functions on the prototype (fn === p5.prototype)
|
|
2246
|
+
// Core permission functions
|
|
2247
|
+
fn.lockGestures = lockGestures;
|
|
2248
|
+
fn.enableGyroTap = enableGyroTap;
|
|
2249
|
+
fn.enableGyroButton = enableGyroButton;
|
|
2250
|
+
fn.enableMicTap = enableMicTap;
|
|
2251
|
+
fn.enableMicButton = enableMicButton;
|
|
2252
|
+
fn.enableSoundTap = enableSoundTap;
|
|
2253
|
+
fn.enableSoundButton = enableSoundButton;
|
|
2254
|
+
fn.enableSpeechTap = enableSpeechTap;
|
|
2255
|
+
fn.enableSpeechButton = enableSpeechButton;
|
|
2256
|
+
fn.enableVibrationTap = enableVibrationTap;
|
|
2257
|
+
fn.enableVibrationButton = enableVibrationButton;
|
|
2258
|
+
fn.vibrate = vibrate;
|
|
2259
|
+
fn.stopVibration = stopVibration;
|
|
2260
|
+
fn.enableAllTap = enableAllTap;
|
|
2261
|
+
fn.enableAllButton = enableAllButton;
|
|
2262
|
+
|
|
2263
|
+
// Canvas-first-touch style
|
|
2264
|
+
fn.enableGyroCanvas = enableGyroCanvas;
|
|
2265
|
+
fn.enableMicCanvas = enableMicCanvas;
|
|
2266
|
+
fn.enableSoundCanvas = enableSoundCanvas;
|
|
2267
|
+
fn.enableSpeechCanvas = enableSpeechCanvas;
|
|
2268
|
+
fn.enableVibrationCanvas = enableVibrationCanvas;
|
|
2269
|
+
fn.enableAllCanvas = enableAllCanvas;
|
|
2270
|
+
fn.enableCameraCanvas = enableCameraCanvas;
|
|
2271
|
+
|
|
2272
|
+
// Banner style
|
|
2273
|
+
fn.enableGyroBanner = enableGyroBanner;
|
|
2274
|
+
fn.enableMicBanner = enableMicBanner;
|
|
2275
|
+
fn.enableSoundBanner = enableSoundBanner;
|
|
2276
|
+
fn.enableSpeechBanner = enableSpeechBanner;
|
|
2277
|
+
fn.enableVibrationBanner = enableVibrationBanner;
|
|
2278
|
+
fn.enableAllBanner = enableAllBanner;
|
|
2279
|
+
fn.enableCameraBanner = enableCameraBanner;
|
|
2280
|
+
|
|
2281
|
+
// Custom element binding
|
|
2282
|
+
fn.enableGyroOn = enableGyroOn;
|
|
2283
|
+
fn.enableMicOn = enableMicOn;
|
|
2284
|
+
fn.enableSoundOn = enableSoundOn;
|
|
2285
|
+
fn.enableSpeechOn = enableSpeechOn;
|
|
2286
|
+
fn.enableVibrationOn = enableVibrationOn;
|
|
2287
|
+
fn.enableAllOn = enableAllOn;
|
|
2288
|
+
fn.enableCameraOn = enableCameraOn;
|
|
2289
|
+
|
|
2290
|
+
// Camera functions
|
|
2291
|
+
fn.createPhoneCamera = createPhoneCamera;
|
|
2292
|
+
fn.enableCameraButton = enableCameraButton;
|
|
2293
|
+
fn.enableCameraTap = enableCameraTap;
|
|
2294
|
+
|
|
2295
|
+
// Debug functions
|
|
2296
|
+
fn.showDebug = showDebug;
|
|
2297
|
+
fn.hideDebug = hideDebug;
|
|
2298
|
+
fn.toggleDebug = toggleDebug;
|
|
2299
|
+
fn.debug = debug;
|
|
2300
|
+
fn.debugError = debugError;
|
|
2301
|
+
fn.debugWarn = debugWarn;
|
|
2302
|
+
|
|
2303
|
+
console.log('✅ Mobile p5.js Permissions: registered as p5.js 2.0 addon');
|
|
2304
|
+
});
|
|
2218
2305
|
}
|
package/dist/p5-phone.min.js
CHANGED
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
* Released under the MIT License
|
|
8
8
|
* https://opensource.org/licenses/MIT
|
|
9
9
|
*/
|
|
10
|
-
window._originalConsoleError=console.error,window._originalConsoleWarn=console.warn,window._debugErrorHandlersSet||(window._debugErrorHandlersSet=!0,window._earlyErrors=window._earlyErrors||[],window.addEventListener("error",function(e){const n=`${e.error?.message||e.message||"Unknown error"} (${e.filename?e.filename.split("/").pop():"unknown file"}:${e.lineno||"unknown line"})`;console.error("🚨 Error caught:",n),e.error?.stack&&console.error("Stack:",e.error.stack),window._earlyErrors.push({type:"error",message:"JavaScript Error: "+n,stack:e.error?.stack}),!1===window.SHOW_DEBUG||window._debugVisible||"function"==typeof showDebug&&showDebug(),window._debugVisible&&"function"==typeof debugError&&(debugError("JavaScript Error:",n),e.error?.stack&&debugError("Stack trace:",e.error.stack))}),window.addEventListener("unhandledrejection",function(e){const n=e.reason?.message||e.reason||"Unknown promise rejection";console.error("🚨 Promise rejection caught:",n),window._earlyErrors.push({type:"error",message:"Unhandled Promise Rejection: "+n}),window._debugVisible&&"function"==typeof debugError&&debugError("Unhandled Promise Rejection:",n)})),window.sensorsEnabled=!1,window.micEnabled=!1,window.soundEnabled=!1,window.gesturesLocked=!1,window.vibrationEnabled=!1,window.speechEnabled=!1;let _micInstance=null;function lockGestures(){window.gesturesLocked||(console.log("🔒 Locking mobile gestures..."),_initializeGestureBlocking(),_initializeP5TouchOverrides(),window.gesturesLocked=!0,console.log("✅ Mobile gestures locked"))}function enableGyroButton(e="ENABLE MOTION SENSORS",n="Requesting motion sensors..."){_createPermissionButton(e,n,async()=>{await _requestMotionPermissions(),console.log("✅ Gyroscope enabled via button")})}function enableGyroTap(e="Tap screen to enable motion sensors"){_createTapToEnable(e,async()=>{await _requestMotionPermissions(),console.log("✅ Gyroscope enabled via tap")})}function enableMicButton(e="ENABLE MICROPHONE",n="Requesting microphone access..."){_createPermissionButton(e,n,async()=>{await _requestMicrophonePermissions(),console.log("✅ Microphone enabled via button")})}function enableMicTap(e="Tap screen to enable microphone"){_createTapToEnable(e,async()=>{await _requestMicrophonePermissions(),console.log("✅ Microphone enabled via tap")})}function enableSoundButton(e="ENABLE SOUND",n="Enabling audio..."){_createPermissionButton(e,n,async()=>{await _requestSoundOutput(),console.log("✅ Sound output enabled via button")})}function enableSoundTap(e="Tap screen to enable sound"){_createTapToEnable(e,async()=>{await _requestSoundOutput(),console.log("✅ Sound output enabled via tap")})}function enableSpeechTap(e="Tap to enable speech recognition"){_createTapToEnable(e,async()=>{await _requestSpeechPermission(),console.log("✅ Speech recognition enabled via tap")})}function enableSpeechButton(e="ENABLE SPEECH RECOGNITION",n="Enabling speech recognition..."){_createPermissionButton(e,n,async()=>{await _requestSpeechPermission(),console.log("✅ Speech recognition enabled via button")})}function enableVibrationButton(e="ENABLE VIBRATION",n="Enabling vibration..."){_createPermissionButton(e,n,async()=>{await _requestVibrationPermission(),console.log("✅ Vibration enabled via button")})}function enableVibrationTap(e="Tap screen to enable vibration"){_createTapToEnable(e,async()=>{await _requestVibrationPermission(),console.log("✅ Vibration enabled via tap")})}function enableAllButton(e="ENABLE MOTION & MICROPHONE",n="Requesting permissions..."){_createPermissionButton(e,n,async()=>{await _requestMotionPermissionsCore(),await _requestMicrophonePermissionsCore(),_notifySketchReady(),console.log("✅ Motion sensors and microphone enabled via button")})}function enableAllTap(e="Tap screen to enable motion sensors & microphone"){_createTapToEnable(e,async()=>{await _requestMotionPermissionsCore(),await _requestMicrophonePermissionsCore(),_notifySketchReady(),console.log("✅ Motion sensors and microphone enabled via tap")})}function enableGyroCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestMotionPermissions(),console.log("✅ Gyroscope enabled via canvas touch")})}function enableMicCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestMicrophonePermissions(),console.log("✅ Microphone enabled via canvas touch")})}function enableSoundCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestSoundOutput(),console.log("✅ Sound output enabled via canvas touch")})}function enableSpeechCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestSpeechPermission(),console.log("✅ Speech recognition enabled via canvas touch")})}function enableVibrationCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestVibrationPermission(),console.log("✅ Vibration enabled via canvas touch")})}function enableAllCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestMotionPermissionsCore(),await _requestMicrophonePermissionsCore(),_notifySketchReady(),console.log("✅ Motion sensors and microphone enabled via canvas touch")})}function enableCameraCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via canvas touch")})}function enableGyroBanner(e="Tap to enable motion sensors",n="top"){_createBannerToEnable(e,n,async()=>{await _requestMotionPermissions(),console.log("✅ Gyroscope enabled via banner")})}function enableMicBanner(e="Tap to enable microphone",n="top"){_createBannerToEnable(e,n,async()=>{await _requestMicrophonePermissions(),console.log("✅ Microphone enabled via banner")})}function enableSoundBanner(e="Tap to enable sound",n="top"){_createBannerToEnable(e,n,async()=>{await _requestSoundOutput(),console.log("✅ Sound output enabled via banner")})}function enableSpeechBanner(e="Tap to enable speech recognition",n="top"){_createBannerToEnable(e,n,async()=>{await _requestSpeechPermission(),console.log("✅ Speech recognition enabled via banner")})}function enableVibrationBanner(e="Tap to enable vibration",n="top"){_createBannerToEnable(e,n,async()=>{await _requestVibrationPermission(),console.log("✅ Vibration enabled via banner")})}function enableAllBanner(e="Tap to enable sensors & microphone",n="top"){_createBannerToEnable(e,n,async()=>{await _requestMotionPermissionsCore(),await _requestMicrophonePermissionsCore(),_notifySketchReady(),console.log("✅ Motion sensors and microphone enabled via banner")})}function enableCameraBanner(e="Tap to enable camera",n="top"){_createBannerToEnable(e,n,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via banner")})}function enableGyroOn(e){_bindPermissionTo(e,async()=>{await _requestMotionPermissions(),console.log("✅ Gyroscope enabled via custom element")})}function enableMicOn(e){_bindPermissionTo(e,async()=>{await _requestMicrophonePermissions(),console.log("✅ Microphone enabled via custom element")})}function enableSoundOn(e){_bindPermissionTo(e,async()=>{await _requestSoundOutput(),console.log("✅ Sound output enabled via custom element")})}function enableSpeechOn(e){_bindPermissionTo(e,async()=>{await _requestSpeechPermission(),console.log("✅ Speech recognition enabled via custom element")})}function enableVibrationOn(e){_bindPermissionTo(e,async()=>{await _requestVibrationPermission(),console.log("✅ Vibration enabled via custom element")})}function enableAllOn(e){_bindPermissionTo(e,async()=>{await _requestMotionPermissionsCore(),await _requestMicrophonePermissionsCore(),_notifySketchReady(),console.log("✅ Motion sensors and microphone enabled via custom element")})}function enableCameraOn(e){_bindPermissionTo(e,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via custom element")})}function vibrate(e){return window.vibrationEnabled?navigator.vibrate?navigator.vibrate(e):(console.warn("⚠️ Vibration API not supported on this device"),!1):(console.warn("⚠️ Vibration not enabled. Call enableVibrationTap() or enableVibrationButton() first."),!1)}function stopVibration(){navigator.vibrate&&navigator.vibrate(0)}async function _requestMotionPermissionsCore(){try{if("undefined"!=typeof DeviceOrientationEvent&&"function"==typeof DeviceOrientationEvent.requestPermission){const e=await DeviceOrientationEvent.requestPermission();if(console.log("Orientation permission:",e),"undefined"!=typeof DeviceMotionEvent&&"function"==typeof DeviceMotionEvent.requestPermission){const e=await DeviceMotionEvent.requestPermission();console.log("Motion permission:",e)}}window.sensorsEnabled=!0}catch(e){console.error("Motion sensor permission error:",e),_debugVisible&&debugError("Motion sensor permission error:",e),window.sensorsEnabled=!0}}async function _requestMicrophonePermissionsCore(){try{"undefined"!=typeof userStartAudio&&await userStartAudio(),"undefined"!=typeof mic&&mic&&mic.start?(mic.start(),_micInstance=mic,window.micEnabled=!0):console.warn("No microphone object found. Create one with: mic = new p5.AudioIn();")}catch(e){console.error("Microphone permission error:",e),_debugVisible&&debugError("Microphone permission error:",e)}}async function _requestSoundOutputCore(){try{"undefined"!=typeof userStartAudio&&await userStartAudio(),window.soundEnabled=!0}catch(e){console.error("Sound output error:",e),_debugVisible&&debugError("Sound output error:",e),window.soundEnabled=!0}}async function _requestSpeechPermissionCore(){try{"undefined"!=typeof userStartAudio&&await userStartAudio(),window.speechEnabled=!0}catch(e){console.error("Speech permission error:",e),_debugVisible&&debugError("Speech permission error:",e)}}async function _requestVibrationPermissionCore(){try{if(!navigator.vibrate)return console.warn("⚠️ Vibration API not supported on this device (likely iOS)"),_debugVisible&&debugWarn("Vibration API not supported on this device"),void(window.vibrationEnabled=!1);navigator.vibrate(1)?(window.vibrationEnabled=!0,console.log("✅ Vibration enabled")):(console.warn("⚠️ Vibration API available but vibration failed"),window.vibrationEnabled=!1)}catch(e){console.error("Vibration permission error:",e),_debugVisible&&debugError("Vibration permission error:",e),window.vibrationEnabled=!1}}async function _requestMotionPermissions(){await _requestMotionPermissionsCore(),_notifySketchReady()}async function _requestMicrophonePermissions(){await _requestMicrophonePermissionsCore(),_notifySketchReady()}async function _requestSoundOutput(){await _requestSoundOutputCore(),_notifySketchReady()}async function _requestSpeechPermission(){await _requestSpeechPermissionCore(),_notifySketchReady()}async function _requestVibrationPermission(){await _requestVibrationPermissionCore(),_notifySketchReady()}function _notifySketchReady(){"function"==typeof userSetupComplete&&userSetupComplete(),window.dispatchEvent(new CustomEvent("permissionsReady",{detail:{sensors:window.sensorsEnabled,microphone:window.micEnabled,sound:window.soundEnabled,speech:window.speechEnabled,vibration:window.vibrationEnabled,gestures:window.gesturesLocked}}))}function _createPermissionButton(e,n,o){_removeExistingUI();const t=document.createElement("button");t.id="permissionButton",t.textContent=e,t.style.cssText="\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n padding: 20px 40px;\n font-size: 18px;\n font-weight: bold;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n border: none;\n border-radius: 12px;\n cursor: pointer;\n z-index: 999999;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 15px rgba(0,0,0,0.2);\n transition: transform 0.2s ease;\n touch-action: manipulation;\n ";const i=document.createElement("div");i.id="permissionStatus",i.textContent=n,i.style.cssText="\n position: fixed;\n top: 60%;\n left: 50%;\n transform: translate(-50%, 0);\n color: white;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n text-align: center;\n z-index: 999998;\n display: none;\n ",t.addEventListener("mouseenter",()=>{t.style.transform="translate(-50%, -50%) scale(1.05)"}),t.addEventListener("mouseleave",()=>{t.style.transform="translate(-50%, -50%) scale(1)"});const a=async()=>{t.parentNode&&(t.style.display="none",i.style.display="block",await o(),i.style.display="none",_removeExistingUI())};t.addEventListener("click",a),t.addEventListener("touchend",function(e){e.preventDefault(),e.stopPropagation(),a()}),t.addEventListener("pointerup",function(e){e.preventDefault(),e.stopPropagation(),a()}),document.body.appendChild(t),document.body.appendChild(i)}function _createTapToEnable(e,n){_removeExistingUI();const o=document.createElement("div");o.id="tapOverlay",o.style.cssText="\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 999999;\n cursor: pointer;\n touch-action: manipulation;\n ";const t=document.createElement("div");t.textContent=e,t.style.cssText="\n color: white;\n font-size: 24px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n text-align: center;\n padding: 40px;\n border: 2px solid rgba(255, 255, 255, 0.3);\n border-radius: 12px;\n background: rgba(255, 255, 255, 0.1);\n backdrop-filter: blur(10px);\n ",o.appendChild(t);const i=async()=>{o.parentNode&&(t.textContent="Enabling...",await n(),o.parentNode&&document.body.removeChild(o))};o.addEventListener("click",i),o.addEventListener("touchend",function(e){e.preventDefault(),e.stopPropagation(),i()}),o.addEventListener("pointerup",function(e){e.preventDefault(),e.stopPropagation(),i()}),document.body.appendChild(o)}function _removeExistingUI(){const e=document.getElementById("permissionButton"),n=document.getElementById("permissionStatus"),o=document.getElementById("tapOverlay"),t=document.getElementById("permissionBanner");e&&e.remove(),n&&n.remove(),o&&o.remove(),t&&t.remove()}function _createCanvasToEnable(e,n){_removeExistingUI();let o=!1,t=null;e&&(t=setInterval(()=>{const n=document.querySelector("canvas");n&&"function"==typeof push&&(push(),fill(255,255,255,200),noStroke(),textAlign(CENTER,CENTER),textSize(.04*Math.min(n.width,n.height)),text(e,("undefined"!=typeof width?width:n.width)/2,.9*("undefined"!=typeof height?height:n.height)),pop())},50));const i=async e=>{o||(o=!0,t&&(clearInterval(t),t=null),document.removeEventListener("touchstart",i,!0),document.removeEventListener("mousedown",i,!0),await n())},a=()=>{const e=document.querySelector("canvas");e?(e.addEventListener("touchstart",i,{once:!0,capture:!0}),e.addEventListener("mousedown",i,{once:!0,capture:!0})):setTimeout(a,50)};a()}function _createBannerToEnable(e,n,o){_removeExistingUI();const t=document.createElement("div");t.id="permissionBanner";const i="top"===n;t.style.cssText=`\n position: fixed;\n ${i?"top: 0;":"bottom: 0;"}\n left: 0;\n width: 100%;\n padding: 16px 20px;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n font-size: 16px;\n font-weight: 600;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n text-align: center;\n z-index: 999999;\n cursor: pointer;\n touch-action: manipulation;\n box-shadow: ${i?"0 2px 10px rgba(0,0,0,0.3)":"0 -2px 10px rgba(0,0,0,0.3)"};\n transition: opacity 0.3s ease, transform 0.3s ease;\n transform: translateY(${i?"-100%":"100%"});\n `,t.textContent=e,document.body.appendChild(t),requestAnimationFrame(()=>{requestAnimationFrame(()=>{t.style.transform="translateY(0)"})});const a=async()=>{t.parentNode&&(t.textContent="Enabling...",t.style.pointerEvents="none",await o(),t.style.transform=`translateY(${i?"-100%":"100%"})`,t.style.opacity="0",setTimeout(()=>{t.parentNode&&t.remove()},300))};t.addEventListener("click",a),t.addEventListener("touchend",function(e){e.preventDefault(),e.stopPropagation(),a()}),t.addEventListener("pointerup",function(e){e.preventDefault(),e.stopPropagation(),a()})}function _bindPermissionTo(e,n){let o=!1;const t=()=>{const i=document.querySelector(e);if(!i)return console.warn(`p5-phone: Element "${e}" not found. Retrying...`),void setTimeout(t,100);const a=async()=>{o||(o=!0,await n())};i.addEventListener("click",a),i.addEventListener("touchend",function(e){e.preventDefault(),e.stopPropagation(),a()})};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}function _initializeGestureBlocking(){window.history.pushState(null,"",window.location.href),window.onpopstate=function(){window.history.pushState(null,"",window.location.href)},window.addEventListener("beforeunload",function(e){e.preventDefault(),e.returnValue=""}),_initializeEdgeSwipePrevention(),_initializeOtherGesturePrevention()}function _initializeEdgeSwipePrevention(){let e=0,n=0;document.addEventListener("touchstart",function(o){o.touches&&o.touches.length>0&&(e=o.touches[0].clientX,n=o.touches[0].clientY,(e<20||e>window.innerWidth-20)&&o.preventDefault())},{passive:!1,capture:!0}),document.addEventListener("touchmove",function(o){if(!o.touches||0===o.touches.length)return;let t=o.touches[0].clientX,i=o.touches[0].clientY,a=t-e,r=i-n;(e<20&&a>0||e>window.innerWidth-20&&a<0)&&(o.preventDefault(),o.stopPropagation()),0===window.pageYOffset&&r>0&&o.preventDefault(),!o.target||"CANVAS"!==o.target.tagName||document.getElementById("tapOverlay")||document.getElementById("permissionButton")||o.preventDefault()},{passive:!1,capture:!0})}function _initializeOtherGesturePrevention(){document.addEventListener("gesturestart",function(e){e.preventDefault()}),document.addEventListener("gesturechange",function(e){e.preventDefault()}),document.addEventListener("gestureend",function(e){e.preventDefault()});let e=0;document.addEventListener("touchend",function(n){if(n.target&&("tapOverlay"===n.target.id||n.target.closest("#tapOverlay")||"permissionButton"===n.target.id||"permissionStatus"===n.target.id||n.target.closest("#permissionButton")||n.target.closest("#permissionStatus")))return;const o=Date.now();o-e<=300&&n.preventDefault(),e=o},!1),window.oncontextmenu=function(e){return e.preventDefault(),e.stopPropagation(),!1}}function _initializeP5TouchOverrides(){let e=0;const n=()=>{e++;"undefined"!=typeof p5&&p5.instance||document.querySelector("canvas")||"function"==typeof window.setup&&"function"==typeof window.draw?_overrideP5Touch():e<50?setTimeout(n,100):console.warn("p5-phone: Could not detect p5.js setup completion. Touch overrides not applied.")};setTimeout(n,100)}function _overrideP5Touch(){const e=window.touchStarted||function(){},n=window.touchMoved||function(){},o=window.touchEnded||function(){},t=window.mousePressed||function(){},i=window.mouseDragged||function(){},a=window.mouseReleased||function(){};window.touchStarted=function(n){return e(n),!1},window.touchMoved=function(e){return n(e),!1},window.touchEnded=function(e){return o(e),!1},window.mousePressed=function(e){return t(e),!1},window.mouseDragged=function(e){return i(e),!1},window.mouseReleased=function(e){return a(e),!1}}document.addEventListener("DOMContentLoaded",function(){const e=document.getElementById("startButton"),n=document.getElementById("statusText");e&&n&&(console.warn("⚠️ Legacy HTML elements detected. Consider using the new API functions instead."),e.addEventListener("click",async()=>{e.classList.add("hidden"),n.classList.remove("hidden"),n.textContent="Requesting permissions...",await _requestMotionPermissions(),await _requestMicrophonePermissions(),n.classList.add("hidden")}),lockGestures())});let _debugPanel=null,_debugVisible=!1,_debugMessages=[];const MAX_DEBUG_MESSAGES=20;function showDebug(){_createDebugPanel(),_debugPanel.style.display="block",_debugVisible=!0,window._debugVisible=!0,_setupConsoleOverrides(),_displayEarlyErrors()}function hideDebug(){_debugPanel&&(_debugPanel.style.display="none",_debugVisible=!1)}function toggleDebug(){_debugVisible?hideDebug():showDebug()}function debug(...e){console.log(...e);_addDebugMessage(e.map(e=>{if("object"==typeof e&&null!==e)try{return JSON.stringify(e,null,2)}catch(n){return String(e)}return String(e)}).join(" "),"log")}function debugError(...e){(window._originalConsoleError||console.error).apply(console,e);_addDebugMessage(`❌ ERROR: ${e.map(e=>{if("object"==typeof e&&null!==e)try{return JSON.stringify(e,null,2)}catch(n){return String(e)}return String(e)}).join(" ")}`,"error")}function debugWarn(...e){(window._originalConsoleWarn||console.warn).apply(console,e);_addDebugMessage(`⚠️ WARNING: ${e.map(e=>{if("object"==typeof e&&null!==e)try{return JSON.stringify(e,null,2)}catch(n){return String(e)}return String(e)}).join(" ")}`,"warning")}function _addDebugMessage(e,n="log"){const o={text:`[${(new Date).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit",fractionalSecondDigits:3})}] ${e}`,type:n};_debugMessages.push(o),_debugMessages.length>20&&_debugMessages.shift(),_debugPanel&&_updateDebugDisplay()}function _setupConsoleOverrides(){window._consoleOverrideSet||(window._consoleOverrideSet=!0,"function"==typeof console.error&&(window._originalConsoleError=console.error),"function"==typeof console.warn&&(window._originalConsoleWarn=console.warn),console.error=function(...e){try{window._originalConsoleError.apply(console,e)}catch(e){}_debugVisible&&debugError(...e)},console.warn=function(...e){try{window._originalConsoleWarn.apply(console,e)}catch(e){}_debugVisible&&debugWarn(...e)})}function _displayEarlyErrors(){window._earlyErrors&&window._earlyErrors.length>0&&(debugError(`🚨 Found ${window._earlyErrors.length} early error(s):`),window._earlyErrors.forEach(e=>{debugError(e.message),e.stack&&debugError("Stack trace:",e.stack)}),window._earlyErrors=[])}function _createDebugPanel(){if(_debugPanel)return;_debugPanel=document.createElement("div"),_debugPanel.id="mobile-debug-panel",_debugPanel.innerHTML='\n <div id="mobile-debug-header">\n <span>Debug</span>\n <button id="mobile-debug-close">×</button>\n </div>\n <div id="mobile-debug-content"></div>\n ';const e=document.createElement("style");e.textContent="\n #mobile-debug-panel {\n position: fixed;\n top: 20px;\n right: 20px;\n width: 350px;\n max-width: calc(100vw - 40px);\n max-height: 400px;\n background: rgba(0, 0, 0, 0.9);\n color: #ffffff;\n font-family: 'Courier New', monospace;\n font-size: 12px;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n z-index: 10000;\n display: none;\n }\n \n #mobile-debug-header {\n background: rgba(255, 255, 255, 0.1);\n padding: 8px 12px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.2);\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-radius: 8px 8px 0 0;\n }\n \n #mobile-debug-header span {\n font-weight: bold;\n font-size: 13px;\n }\n \n #mobile-debug-close {\n background: none;\n border: none;\n color: #ffffff;\n font-size: 18px;\n cursor: pointer;\n padding: 0;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n #mobile-debug-close:hover {\n background: rgba(255, 255, 255, 0.1);\n border-radius: 4px;\n }\n \n #mobile-debug-content {\n padding: 12px;\n max-height: 340px;\n overflow-y: auto;\n word-wrap: break-word;\n line-height: 1.4;\n }\n \n .debug-message {\n margin-bottom: 4px;\n white-space: pre-wrap;\n }\n \n .debug-message.error {\n color: #ff6b6b;\n background: rgba(255, 107, 107, 0.1);\n padding: 4px;\n border-radius: 3px;\n border-left: 3px solid #ff6b6b;\n }\n \n .debug-message.warning {\n color: #ffd93d;\n background: rgba(255, 217, 61, 0.1);\n padding: 4px;\n border-radius: 3px;\n border-left: 3px solid #ffd93d;\n }\n \n .debug-timestamp {\n color: #888;\n font-size: 10px;\n }\n \n @media (max-width: 480px) {\n #mobile-debug-panel {\n width: calc(100vw - 20px);\n right: 10px;\n top: 10px;\n }\n }\n ",document.head.appendChild(e),document.body.appendChild(_debugPanel),document.getElementById("mobile-debug-close").onclick=hideDebug,_updateDebugDisplay()}function _updateDebugDisplay(){if(!_debugPanel)return;const e=document.getElementById("mobile-debug-content");e&&(e.innerHTML=_debugMessages.map(e=>"string"==typeof e?`<div class="debug-message">${e}</div>`:`<div class="debug-message ${e.type}">${e.text}</div>`).join(""),e.scrollTop=e.scrollHeight)}debug.clear=function(){_debugMessages=[],_debugPanel&&_updateDebugDisplay(),console.clear()},window.debug=debug,window.debugError=debugError,window.debugWarn=debugWarn,window.showDebug=showDebug,window.hideDebug=hideDebug,window.toggleDebug=toggleDebug,window.lockGestures=lockGestures,window.enableGyroTap=enableGyroTap,window.enableGyroButton=enableGyroButton,window.enableMicTap=enableMicTap,window.enableMicButton=enableMicButton,window.enableSoundTap=enableSoundTap,window.enableSoundButton=enableSoundButton,window.enableSpeechTap=enableSpeechTap,window.enableSpeechButton=enableSpeechButton,window.enableVibrationTap=enableVibrationTap,window.enableVibrationButton=enableVibrationButton,window.vibrate=vibrate,window.stopVibration=stopVibration,window.enableAllTap=enableAllTap,window.enableAllButton=enableAllButton,window.enableGyroCanvas=enableGyroCanvas,window.enableMicCanvas=enableMicCanvas,window.enableSoundCanvas=enableSoundCanvas,window.enableSpeechCanvas=enableSpeechCanvas,window.enableVibrationCanvas=enableVibrationCanvas,window.enableAllCanvas=enableAllCanvas,window.enableCameraCanvas=enableCameraCanvas,window.enableGyroBanner=enableGyroBanner,window.enableMicBanner=enableMicBanner,window.enableSoundBanner=enableSoundBanner,window.enableSpeechBanner=enableSpeechBanner,window.enableVibrationBanner=enableVibrationBanner,window.enableAllBanner=enableAllBanner,window.enableCameraBanner=enableCameraBanner,window.enableGyroOn=enableGyroOn,window.enableMicOn=enableMicOn,window.enableSoundOn=enableSoundOn,window.enableSpeechOn=enableSpeechOn,window.enableVibrationOn=enableVibrationOn,window.enableAllOn=enableAllOn,window.enableCameraOn=enableCameraOn;class PhoneCamera{constructor(e="user",n=!0,o="fitHeight"){this._active=e,this._mirror=n,this._mode=o,this._fixedWidth=640,this._fixedHeight=480,this._video=null,this._ready=!1,this._p5Instance=window,this._onReadyCallback=null,this._createCaptureRef=null,window._phoneCameras||(window._phoneCameras=[]),window._phoneCameras.push(this)}get ready(){return this._ready}get video(){return this._video}get videoElement(){return this._video?this._video.elt:null}get width(){if(!this._ready)return 0;return this.getDimensions().width}get height(){if(!this._ready)return 0;return this.getDimensions().height}get active(){return this._active}set active(e){"user"===e||"environment"===e?this._active!==e&&(this._active=e,this._ready&&this._switchCamera()):console.error('PhoneCamera: active must be "user" or "environment"')}get mirror(){return this._mirror}set mirror(e){this._mirror=!!e}get mode(){return this._mode}set mode(e){const n=["fitWidth","fitHeight","cover","contain","fixed"];n.includes(e)?this._mode=e:console.error("PhoneCamera: mode must be one of:",n.join(", "))}get fixedWidth(){return this._fixedWidth}set fixedWidth(e){this._fixedWidth=Math.max(1,e)}get fixedHeight(){return this._fixedHeight}set fixedHeight(e){this._fixedHeight=Math.max(1,e)}onReady(e){this._onReadyCallback=e,this._ready&&this._video&&this._video.elt&&this._video.elt.readyState>=2?e():this._video&&this._checkVideoReady()}_initializeCamera(){if(this._ready||this._video)return;const e={video:{facingMode:this._active},audio:!1};this._video=createCapture(e,()=>{this._ready=!0,this._video.hide(),console.log("✅ PhoneCamera ready"),this._checkVideoReady()}),this._video&&this._video.elt&&this._video.elt.addEventListener("loadeddata",()=>{this._ready=!0,this._checkVideoReady()})}_checkVideoReady(e=0){if(this._video&&this._video.elt&&this._video.elt.readyState>=2){if(this._onReadyCallback){const e=this._onReadyCallback;this._onReadyCallback=null,e()}}else e<100?setTimeout(()=>this._checkVideoReady(e+1),100):(console.warn("PhoneCamera: Video failed to reach ready state after 10 seconds"),_debugVisible&&debugWarn("PhoneCamera: Video not ready after timeout. Check camera permissions."))}_switchCamera(){if(!this._video)return;this._ready;this._ready=!1,this._video.remove();const e={video:{facingMode:this._active},audio:!1};this._video=createCapture(e,()=>{this._ready=!0,this._video.hide(),console.log(`✅ PhoneCamera switched to ${this._active} camera`)}),this._video&&this._video.elt&&this._video.elt.addEventListener("loadeddata",()=>{this._ready=!0})}remove(){this._video&&(this._video.remove(),this._video=null),this._ready=!1}getDimensions(){if(!this._ready||!this._video)return{x:0,y:0,width:0,height:0,scaleX:1,scaleY:1};const e=this._video.width,n=this._video.height,o="undefined"!=typeof width?width:window.innerWidth,t="undefined"!=typeof height?height:window.innerHeight;let i,a,r,s;if("fixed"===this._mode)i=this._fixedWidth,a=this._fixedHeight,r=(o-i)/2,s=(t-a)/2;else if("fitWidth"===this._mode)i=o,a=n/e*i,r=0,s=(t-a)/2;else if("fitHeight"===this._mode)a=t,i=e/n*a,r=(o-i)/2,s=0;else if("cover"===this._mode){const d=Math.max(o/e,t/n);i=e*d,a=n*d,r=(o-i)/2,s=(t-a)/2}else if("contain"===this._mode){const d=Math.min(o/e,t/n);i=e*d,a=n*d,r=(o-i)/2,s=(t-a)/2}return{x:r,y:s,width:i,height:a,scaleX:i/e,scaleY:a/n}}mapPoint(e,n){const o=this.getDimensions();let t=e*o.scaleX;const i=n*o.scaleY;this._mirror&&(t=o.width-t);return{x:t+o.x,y:i+o.y}}mapKeypoint(e){if(!e||void 0===e.x||void 0===e.y)return console.warn("PhoneCamera.mapKeypoint: invalid keypoint",e),e;const n=this.mapPoint(e.x,e.y);return{...e,x:n.x,y:n.y}}mapKeypoints(e){return Array.isArray(e)?e.map(e=>this.mapKeypoint(e)):(console.warn("PhoneCamera.mapKeypoints: expected array, got",typeof e),e)}_draw(){if(!this._ready||!this._video)return;const e=this.getDimensions(),n="undefined"!=typeof width?width:window.innerWidth;this._drawDebugLogged||(console.log("_draw() params:",{x:e.x,y:e.y,width:e.width,height:e.height,canvasWidth:n,mirror:this._mirror}),this._drawDebugLogged=!0),push(),this._mirror?(translate(n,0),scale(-1,1),image(this._video,e.x,e.y,e.width,e.height)):image(this._video,e.x,e.y,e.width,e.height),pop()}}function createPhoneCamera(e="user",n=!0,o="fitHeight"){return new PhoneCamera(e,n,o)}function enableCameraButton(e="ENABLE CAMERA",n="Starting camera..."){_createPermissionButton(e,n,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via button")})}function enableCameraTap(e="Tap screen to enable camera"){navigator.permissions&&navigator.permissions.query?navigator.permissions.query({name:"camera"}).then(n=>{"granted"===n.state?(console.log("✅ Camera permission already granted - auto-starting"),_requestCameraPermission()):_createTapToEnable(e,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via tap")})}).catch(()=>{_createTapToEnable(e,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via tap")})}):_createTapToEnable(e,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via tap")})}async function _requestCameraPermission(){try{if(void 0!==window._phoneCameras&&Array.isArray(window._phoneCameras))for(let e of window._phoneCameras)!e||e._ready||e._video||e._initializeCamera();"function"==typeof userCameraReady&&userCameraReady(),_notifySketchReady()}catch(e){console.error("Camera permission error:",e),_debugVisible&&debugError("Camera permission error:",e),_notifySketchReady()}}if(window.createPhoneCamera=createPhoneCamera,window.enableCameraButton=enableCameraButton,window.enableCameraTap=enableCameraTap,"undefined"!=typeof p5&&p5.prototype){const e=p5.prototype.image;p5.prototype.image=function(...n){if(n[0]instanceof PhoneCamera){n[0]._draw()}else e.apply(this,n)}}"undefined"!=typeof p5&&p5.prototype&&(p5.prototype.lockGestures=lockGestures,p5.prototype.enableGyroTap=enableGyroTap,p5.prototype.enableGyroButton=enableGyroButton,p5.prototype.enableMicTap=enableMicTap,p5.prototype.enableMicButton=enableMicButton,p5.prototype.enableSoundTap=enableSoundTap,p5.prototype.enableSoundButton=enableSoundButton,p5.prototype.enableSpeechTap=enableSpeechTap,p5.prototype.enableSpeechButton=enableSpeechButton,p5.prototype.enableVibrationTap=enableVibrationTap,p5.prototype.enableVibrationButton=enableVibrationButton,p5.prototype.vibrate=vibrate,p5.prototype.stopVibration=stopVibration,p5.prototype.enableAllTap=enableAllTap,p5.prototype.enableAllButton=enableAllButton,p5.prototype.enableGyroCanvas=enableGyroCanvas,p5.prototype.enableMicCanvas=enableMicCanvas,p5.prototype.enableSoundCanvas=enableSoundCanvas,p5.prototype.enableSpeechCanvas=enableSpeechCanvas,p5.prototype.enableVibrationCanvas=enableVibrationCanvas,p5.prototype.enableAllCanvas=enableAllCanvas,p5.prototype.enableCameraCanvas=enableCameraCanvas,p5.prototype.enableGyroBanner=enableGyroBanner,p5.prototype.enableMicBanner=enableMicBanner,p5.prototype.enableSoundBanner=enableSoundBanner,p5.prototype.enableSpeechBanner=enableSpeechBanner,p5.prototype.enableVibrationBanner=enableVibrationBanner,p5.prototype.enableAllBanner=enableAllBanner,p5.prototype.enableCameraBanner=enableCameraBanner,p5.prototype.enableGyroOn=enableGyroOn,p5.prototype.enableMicOn=enableMicOn,p5.prototype.enableSoundOn=enableSoundOn,p5.prototype.enableSpeechOn=enableSpeechOn,p5.prototype.enableVibrationOn=enableVibrationOn,p5.prototype.enableAllOn=enableAllOn,p5.prototype.enableCameraOn=enableCameraOn,p5.prototype.createPhoneCamera=createPhoneCamera,p5.prototype.enableCameraButton=enableCameraButton,p5.prototype.enableCameraTap=enableCameraTap,p5.prototype.showDebug=showDebug,p5.prototype.hideDebug=hideDebug,p5.prototype.toggleDebug=toggleDebug,p5.prototype.debug=debug,p5.prototype.debugError=debugError,p5.prototype.debugWarn=debugWarn,console.log("✅ Mobile p5.js Permissions: p5.prototype functions registered"));
|
|
10
|
+
window._originalConsoleError=console.error,window._originalConsoleWarn=console.warn,window._debugErrorHandlersSet||(window._debugErrorHandlersSet=!0,window._earlyErrors=window._earlyErrors||[],window.addEventListener("error",function(e){const n=`${e.error?.message||e.message||"Unknown error"} (${e.filename?e.filename.split("/").pop():"unknown file"}:${e.lineno||"unknown line"})`;console.error("🚨 Error caught:",n),e.error?.stack&&console.error("Stack:",e.error.stack),window._earlyErrors.push({type:"error",message:"JavaScript Error: "+n,stack:e.error?.stack}),!1===window.SHOW_DEBUG||window._debugVisible||"function"==typeof showDebug&&showDebug(),window._debugVisible&&"function"==typeof debugError&&(debugError("JavaScript Error:",n),e.error?.stack&&debugError("Stack trace:",e.error.stack))}),window.addEventListener("unhandledrejection",function(e){const n=e.reason?.message||e.reason||"Unknown promise rejection";console.error("🚨 Promise rejection caught:",n),window._earlyErrors.push({type:"error",message:"Unhandled Promise Rejection: "+n}),window._debugVisible&&"function"==typeof debugError&&debugError("Unhandled Promise Rejection:",n)})),window.sensorsEnabled=!1,window.micEnabled=!1,window.soundEnabled=!1,window.gesturesLocked=!1,window.vibrationEnabled=!1,window.speechEnabled=!1;let _micInstance=null;const _p5MajorVersion="undefined"!=typeof p5&&p5.VERSION?parseInt(p5.VERSION.split(".")[0],10):1,_isP5v2=_p5MajorVersion>=2;function lockGestures(){window.gesturesLocked||(console.log("🔒 Locking mobile gestures..."),_initializeGestureBlocking(),_initializeP5TouchOverrides(),window.gesturesLocked=!0,console.log("✅ Mobile gestures locked"))}function enableGyroButton(e="ENABLE MOTION SENSORS",n="Requesting motion sensors..."){_createPermissionButton(e,n,async()=>{await _requestMotionPermissions(),console.log("✅ Gyroscope enabled via button")})}function enableGyroTap(e="Tap screen to enable motion sensors"){_createTapToEnable(e,async()=>{await _requestMotionPermissions(),console.log("✅ Gyroscope enabled via tap")})}function enableMicButton(e="ENABLE MICROPHONE",n="Requesting microphone access..."){_createPermissionButton(e,n,async()=>{await _requestMicrophonePermissions(),console.log("✅ Microphone enabled via button")})}function enableMicTap(e="Tap screen to enable microphone"){_createTapToEnable(e,async()=>{await _requestMicrophonePermissions(),console.log("✅ Microphone enabled via tap")})}function enableSoundButton(e="ENABLE SOUND",n="Enabling audio..."){_createPermissionButton(e,n,async()=>{await _requestSoundOutput(),console.log("✅ Sound output enabled via button")})}function enableSoundTap(e="Tap screen to enable sound"){_createTapToEnable(e,async()=>{await _requestSoundOutput(),console.log("✅ Sound output enabled via tap")})}function enableSpeechTap(e="Tap to enable speech recognition"){_createTapToEnable(e,async()=>{await _requestSpeechPermission(),console.log("✅ Speech recognition enabled via tap")})}function enableSpeechButton(e="ENABLE SPEECH RECOGNITION",n="Enabling speech recognition..."){_createPermissionButton(e,n,async()=>{await _requestSpeechPermission(),console.log("✅ Speech recognition enabled via button")})}function enableVibrationButton(e="ENABLE VIBRATION",n="Enabling vibration..."){_createPermissionButton(e,n,async()=>{await _requestVibrationPermission(),console.log("✅ Vibration enabled via button")})}function enableVibrationTap(e="Tap screen to enable vibration"){_createTapToEnable(e,async()=>{await _requestVibrationPermission(),console.log("✅ Vibration enabled via tap")})}function enableAllButton(e="ENABLE MOTION & MICROPHONE",n="Requesting permissions..."){_createPermissionButton(e,n,async()=>{await _requestMotionPermissionsCore(),await _requestMicrophonePermissionsCore(),_notifySketchReady(),console.log("✅ Motion sensors and microphone enabled via button")})}function enableAllTap(e="Tap screen to enable motion sensors & microphone"){_createTapToEnable(e,async()=>{await _requestMotionPermissionsCore(),await _requestMicrophonePermissionsCore(),_notifySketchReady(),console.log("✅ Motion sensors and microphone enabled via tap")})}function enableGyroCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestMotionPermissions(),console.log("✅ Gyroscope enabled via canvas touch")})}function enableMicCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestMicrophonePermissions(),console.log("✅ Microphone enabled via canvas touch")})}function enableSoundCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestSoundOutput(),console.log("✅ Sound output enabled via canvas touch")})}function enableSpeechCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestSpeechPermission(),console.log("✅ Speech recognition enabled via canvas touch")})}function enableVibrationCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestVibrationPermission(),console.log("✅ Vibration enabled via canvas touch")})}function enableAllCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestMotionPermissionsCore(),await _requestMicrophonePermissionsCore(),_notifySketchReady(),console.log("✅ Motion sensors and microphone enabled via canvas touch")})}function enableCameraCanvas(e="Touch to start"){_createCanvasToEnable(e,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via canvas touch")})}function enableGyroBanner(e="Tap to enable motion sensors",n="top"){_createBannerToEnable(e,n,async()=>{await _requestMotionPermissions(),console.log("✅ Gyroscope enabled via banner")})}function enableMicBanner(e="Tap to enable microphone",n="top"){_createBannerToEnable(e,n,async()=>{await _requestMicrophonePermissions(),console.log("✅ Microphone enabled via banner")})}function enableSoundBanner(e="Tap to enable sound",n="top"){_createBannerToEnable(e,n,async()=>{await _requestSoundOutput(),console.log("✅ Sound output enabled via banner")})}function enableSpeechBanner(e="Tap to enable speech recognition",n="top"){_createBannerToEnable(e,n,async()=>{await _requestSpeechPermission(),console.log("✅ Speech recognition enabled via banner")})}function enableVibrationBanner(e="Tap to enable vibration",n="top"){_createBannerToEnable(e,n,async()=>{await _requestVibrationPermission(),console.log("✅ Vibration enabled via banner")})}function enableAllBanner(e="Tap to enable sensors & microphone",n="top"){_createBannerToEnable(e,n,async()=>{await _requestMotionPermissionsCore(),await _requestMicrophonePermissionsCore(),_notifySketchReady(),console.log("✅ Motion sensors and microphone enabled via banner")})}function enableCameraBanner(e="Tap to enable camera",n="top"){_createBannerToEnable(e,n,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via banner")})}function enableGyroOn(e){_bindPermissionTo(e,async()=>{await _requestMotionPermissions(),console.log("✅ Gyroscope enabled via custom element")})}function enableMicOn(e){_bindPermissionTo(e,async()=>{await _requestMicrophonePermissions(),console.log("✅ Microphone enabled via custom element")})}function enableSoundOn(e){_bindPermissionTo(e,async()=>{await _requestSoundOutput(),console.log("✅ Sound output enabled via custom element")})}function enableSpeechOn(e){_bindPermissionTo(e,async()=>{await _requestSpeechPermission(),console.log("✅ Speech recognition enabled via custom element")})}function enableVibrationOn(e){_bindPermissionTo(e,async()=>{await _requestVibrationPermission(),console.log("✅ Vibration enabled via custom element")})}function enableAllOn(e){_bindPermissionTo(e,async()=>{await _requestMotionPermissionsCore(),await _requestMicrophonePermissionsCore(),_notifySketchReady(),console.log("✅ Motion sensors and microphone enabled via custom element")})}function enableCameraOn(e){_bindPermissionTo(e,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via custom element")})}function vibrate(e){return window.vibrationEnabled?navigator.vibrate?navigator.vibrate(e):(console.warn("⚠️ Vibration API not supported on this device"),!1):(console.warn("⚠️ Vibration not enabled. Call enableVibrationTap() or enableVibrationButton() first."),!1)}function stopVibration(){navigator.vibrate&&navigator.vibrate(0)}async function _requestMotionPermissionsCore(){try{if("undefined"!=typeof DeviceOrientationEvent&&"function"==typeof DeviceOrientationEvent.requestPermission){const e=await DeviceOrientationEvent.requestPermission();if(console.log("Orientation permission:",e),"undefined"!=typeof DeviceMotionEvent&&"function"==typeof DeviceMotionEvent.requestPermission){const e=await DeviceMotionEvent.requestPermission();console.log("Motion permission:",e)}}window.sensorsEnabled=!0}catch(e){console.error("Motion sensor permission error:",e),_debugVisible&&debugError("Motion sensor permission error:",e),window.sensorsEnabled=!0}}async function _requestMicrophonePermissionsCore(){try{"undefined"!=typeof userStartAudio&&await userStartAudio(),"undefined"!=typeof mic&&mic&&mic.start?(mic.start(),_micInstance=mic,window.micEnabled=!0):console.warn("No microphone object found. Create one with: mic = new p5.AudioIn();")}catch(e){console.error("Microphone permission error:",e),_debugVisible&&debugError("Microphone permission error:",e)}}async function _requestSoundOutputCore(){try{"undefined"!=typeof userStartAudio&&await userStartAudio(),window.soundEnabled=!0}catch(e){console.error("Sound output error:",e),_debugVisible&&debugError("Sound output error:",e),window.soundEnabled=!0}}async function _requestSpeechPermissionCore(){try{"undefined"!=typeof userStartAudio&&await userStartAudio(),window.speechEnabled=!0}catch(e){console.error("Speech permission error:",e),_debugVisible&&debugError("Speech permission error:",e)}}async function _requestVibrationPermissionCore(){try{if(!navigator.vibrate)return console.warn("⚠️ Vibration API not supported on this device (likely iOS)"),_debugVisible&&debugWarn("Vibration API not supported on this device"),void(window.vibrationEnabled=!1);navigator.vibrate(1)?(window.vibrationEnabled=!0,console.log("✅ Vibration enabled")):(console.warn("⚠️ Vibration API available but vibration failed"),window.vibrationEnabled=!1)}catch(e){console.error("Vibration permission error:",e),_debugVisible&&debugError("Vibration permission error:",e),window.vibrationEnabled=!1}}async function _requestMotionPermissions(){await _requestMotionPermissionsCore(),_notifySketchReady()}async function _requestMicrophonePermissions(){await _requestMicrophonePermissionsCore(),_notifySketchReady()}async function _requestSoundOutput(){await _requestSoundOutputCore(),_notifySketchReady()}async function _requestSpeechPermission(){await _requestSpeechPermissionCore(),_notifySketchReady()}async function _requestVibrationPermission(){await _requestVibrationPermissionCore(),_notifySketchReady()}function _notifySketchReady(){"function"==typeof userSetupComplete&&userSetupComplete(),window.dispatchEvent(new CustomEvent("permissionsReady",{detail:{sensors:window.sensorsEnabled,microphone:window.micEnabled,sound:window.soundEnabled,speech:window.speechEnabled,vibration:window.vibrationEnabled,gestures:window.gesturesLocked}}))}function _createPermissionButton(e,n,o){_removeExistingUI();const t=document.createElement("button");t.id="permissionButton",t.textContent=e,t.style.cssText="\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n padding: 20px 40px;\n font-size: 18px;\n font-weight: bold;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n border: none;\n border-radius: 12px;\n cursor: pointer;\n z-index: 999999;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 15px rgba(0,0,0,0.2);\n transition: transform 0.2s ease;\n touch-action: manipulation;\n ";const a=document.createElement("div");a.id="permissionStatus",a.textContent=n,a.style.cssText="\n position: fixed;\n top: 60%;\n left: 50%;\n transform: translate(-50%, 0);\n color: white;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n text-align: center;\n z-index: 999998;\n display: none;\n ",t.addEventListener("mouseenter",()=>{t.style.transform="translate(-50%, -50%) scale(1.05)"}),t.addEventListener("mouseleave",()=>{t.style.transform="translate(-50%, -50%) scale(1)"});const i=async()=>{t.parentNode&&(t.style.display="none",a.style.display="block",await o(),a.style.display="none",_removeExistingUI())};t.addEventListener("click",i),t.addEventListener("touchend",function(e){e.preventDefault(),e.stopPropagation(),i()}),t.addEventListener("pointerup",function(e){e.preventDefault(),e.stopPropagation(),i()}),document.body.appendChild(t),document.body.appendChild(a)}function _createTapToEnable(e,n){_removeExistingUI();const o=document.createElement("div");o.id="tapOverlay",o.style.cssText="\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 999999;\n cursor: pointer;\n touch-action: manipulation;\n ";const t=document.createElement("div");t.textContent=e,t.style.cssText="\n color: white;\n font-size: 24px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n text-align: center;\n padding: 40px;\n border: 2px solid rgba(255, 255, 255, 0.3);\n border-radius: 12px;\n background: rgba(255, 255, 255, 0.1);\n backdrop-filter: blur(10px);\n ",o.appendChild(t);const a=async()=>{o.parentNode&&(t.textContent="Enabling...",await n(),o.parentNode&&document.body.removeChild(o))};o.addEventListener("click",a),o.addEventListener("touchend",function(e){e.preventDefault(),e.stopPropagation(),a()}),o.addEventListener("pointerup",function(e){e.preventDefault(),e.stopPropagation(),a()}),document.body.appendChild(o)}function _removeExistingUI(){const e=document.getElementById("permissionButton"),n=document.getElementById("permissionStatus"),o=document.getElementById("tapOverlay"),t=document.getElementById("permissionBanner");e&&e.remove(),n&&n.remove(),o&&o.remove(),t&&t.remove()}function _createCanvasToEnable(e,n){_removeExistingUI();let o=!1,t=null;e&&(t=setInterval(()=>{const n=document.querySelector("canvas");n&&"function"==typeof push&&(push(),fill(255,255,255,200),noStroke(),textAlign(CENTER,CENTER),textSize(.04*Math.min(n.width,n.height)),text(e,("undefined"!=typeof width?width:n.width)/2,.9*("undefined"!=typeof height?height:n.height)),pop())},50));const a=async e=>{o||(o=!0,t&&(clearInterval(t),t=null),document.removeEventListener("touchstart",a,!0),document.removeEventListener("mousedown",a,!0),await n())},i=()=>{const e=document.querySelector("canvas");e?(e.addEventListener("touchstart",a,{once:!0,capture:!0}),e.addEventListener("mousedown",a,{once:!0,capture:!0})):setTimeout(i,50)};i()}function _createBannerToEnable(e,n,o){_removeExistingUI();const t=document.createElement("div");t.id="permissionBanner";const a="top"===n;t.style.cssText=`\n position: fixed;\n ${a?"top: 0;":"bottom: 0;"}\n left: 0;\n width: 100%;\n padding: 16px 20px;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n font-size: 16px;\n font-weight: 600;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n text-align: center;\n z-index: 999999;\n cursor: pointer;\n touch-action: manipulation;\n box-shadow: ${a?"0 2px 10px rgba(0,0,0,0.3)":"0 -2px 10px rgba(0,0,0,0.3)"};\n transition: opacity 0.3s ease, transform 0.3s ease;\n transform: translateY(${a?"-100%":"100%"});\n `,t.textContent=e,document.body.appendChild(t),requestAnimationFrame(()=>{requestAnimationFrame(()=>{t.style.transform="translateY(0)"})});const i=async()=>{t.parentNode&&(t.textContent="Enabling...",t.style.pointerEvents="none",await o(),t.style.transform=`translateY(${a?"-100%":"100%"})`,t.style.opacity="0",setTimeout(()=>{t.parentNode&&t.remove()},300))};t.addEventListener("click",i),t.addEventListener("touchend",function(e){e.preventDefault(),e.stopPropagation(),i()}),t.addEventListener("pointerup",function(e){e.preventDefault(),e.stopPropagation(),i()})}function _bindPermissionTo(e,n){let o=!1;const t=()=>{const a=document.querySelector(e);if(!a)return console.warn(`p5-phone: Element "${e}" not found. Retrying...`),void setTimeout(t,100);const i=async()=>{o||(o=!0,await n())};a.addEventListener("click",i),a.addEventListener("touchend",function(e){e.preventDefault(),e.stopPropagation(),i()})};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}function _initializeGestureBlocking(){window.history.pushState(null,"",window.location.href),window.onpopstate=function(){window.history.pushState(null,"",window.location.href)},window.addEventListener("beforeunload",function(e){e.preventDefault(),e.returnValue=""}),_initializeEdgeSwipePrevention(),_initializeOtherGesturePrevention()}function _initializeEdgeSwipePrevention(){let e=0,n=0;document.addEventListener("touchstart",function(o){o.touches&&o.touches.length>0&&(e=o.touches[0].clientX,n=o.touches[0].clientY,(e<20||e>window.innerWidth-20)&&o.preventDefault())},{passive:!1,capture:!0}),document.addEventListener("touchmove",function(o){if(!o.touches||0===o.touches.length)return;let t=o.touches[0].clientX,a=o.touches[0].clientY,i=t-e,r=a-n;(e<20&&i>0||e>window.innerWidth-20&&i<0)&&(o.preventDefault(),o.stopPropagation()),0===window.pageYOffset&&r>0&&o.preventDefault(),!o.target||"CANVAS"!==o.target.tagName||document.getElementById("tapOverlay")||document.getElementById("permissionButton")||o.preventDefault()},{passive:!1,capture:!0})}function _initializeOtherGesturePrevention(){document.addEventListener("gesturestart",function(e){e.preventDefault()}),document.addEventListener("gesturechange",function(e){e.preventDefault()}),document.addEventListener("gestureend",function(e){e.preventDefault()});let e=0;document.addEventListener("touchend",function(n){if(n.target&&("tapOverlay"===n.target.id||n.target.closest("#tapOverlay")||"permissionButton"===n.target.id||"permissionStatus"===n.target.id||n.target.closest("#permissionButton")||n.target.closest("#permissionStatus")))return;const o=Date.now();o-e<=300&&n.preventDefault(),e=o},!1),window.oncontextmenu=function(e){return e.preventDefault(),e.stopPropagation(),!1}}function _initializeP5TouchOverrides(){let e=0;const n=()=>{e++;"undefined"!=typeof p5&&p5.instance||document.querySelector("canvas")||"function"==typeof window.setup&&"function"==typeof window.draw?_overrideP5Touch():e<50?setTimeout(n,100):console.warn("p5-phone: Could not detect p5.js setup completion. Touch overrides not applied.")};setTimeout(n,100)}function _overrideP5Touch(){const e=window.mousePressed||function(){},n=window.mouseDragged||function(){},o=window.mouseReleased||function(){};if(!_isP5v2){const e=window.touchStarted||function(){},n=window.touchMoved||function(){},o=window.touchEnded||function(){};window.touchStarted=function(n){return e(n),!1},window.touchMoved=function(e){return n(e),!1},window.touchEnded=function(e){return o(e),!1}}window.mousePressed=function(n){return e(n),!1},window.mouseDragged=function(e){return n(e),!1},window.mouseReleased=function(e){return o(e),!1}}document.addEventListener("DOMContentLoaded",function(){const e=document.getElementById("startButton"),n=document.getElementById("statusText");e&&n&&(console.warn("⚠️ Legacy HTML elements detected. Consider using the new API functions instead."),e.addEventListener("click",async()=>{e.classList.add("hidden"),n.classList.remove("hidden"),n.textContent="Requesting permissions...",await _requestMotionPermissions(),await _requestMicrophonePermissions(),n.classList.add("hidden")}),lockGestures())});let _debugPanel=null,_debugVisible=!1,_debugMessages=[];const MAX_DEBUG_MESSAGES=20;function showDebug(){_createDebugPanel(),_debugPanel.style.display="block",_debugVisible=!0,window._debugVisible=!0,_setupConsoleOverrides(),_displayEarlyErrors()}function hideDebug(){_debugPanel&&(_debugPanel.style.display="none",_debugVisible=!1)}function toggleDebug(){_debugVisible?hideDebug():showDebug()}function debug(...e){console.log(...e);_addDebugMessage(e.map(e=>{if("object"==typeof e&&null!==e)try{return JSON.stringify(e,null,2)}catch(n){return String(e)}return String(e)}).join(" "),"log")}function debugError(...e){(window._originalConsoleError||console.error).apply(console,e);_addDebugMessage(`❌ ERROR: ${e.map(e=>{if("object"==typeof e&&null!==e)try{return JSON.stringify(e,null,2)}catch(n){return String(e)}return String(e)}).join(" ")}`,"error")}function debugWarn(...e){(window._originalConsoleWarn||console.warn).apply(console,e);_addDebugMessage(`⚠️ WARNING: ${e.map(e=>{if("object"==typeof e&&null!==e)try{return JSON.stringify(e,null,2)}catch(n){return String(e)}return String(e)}).join(" ")}`,"warning")}function _addDebugMessage(e,n="log"){const o={text:`[${(new Date).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit",fractionalSecondDigits:3})}] ${e}`,type:n};_debugMessages.push(o),_debugMessages.length>20&&_debugMessages.shift(),_debugPanel&&_updateDebugDisplay()}function _setupConsoleOverrides(){window._consoleOverrideSet||(window._consoleOverrideSet=!0,"function"==typeof console.error&&(window._originalConsoleError=console.error),"function"==typeof console.warn&&(window._originalConsoleWarn=console.warn),console.error=function(...e){try{window._originalConsoleError.apply(console,e)}catch(e){}_debugVisible&&debugError(...e)},console.warn=function(...e){try{window._originalConsoleWarn.apply(console,e)}catch(e){}_debugVisible&&debugWarn(...e)})}function _displayEarlyErrors(){window._earlyErrors&&window._earlyErrors.length>0&&(debugError(`🚨 Found ${window._earlyErrors.length} early error(s):`),window._earlyErrors.forEach(e=>{debugError(e.message),e.stack&&debugError("Stack trace:",e.stack)}),window._earlyErrors=[])}function _createDebugPanel(){if(_debugPanel)return;_debugPanel=document.createElement("div"),_debugPanel.id="mobile-debug-panel",_debugPanel.innerHTML='\n <div id="mobile-debug-header">\n <span>Debug</span>\n <button id="mobile-debug-close">×</button>\n </div>\n <div id="mobile-debug-content"></div>\n ';const e=document.createElement("style");e.textContent="\n #mobile-debug-panel {\n position: fixed;\n top: 20px;\n right: 20px;\n width: 350px;\n max-width: calc(100vw - 40px);\n max-height: 400px;\n background: rgba(0, 0, 0, 0.9);\n color: #ffffff;\n font-family: 'Courier New', monospace;\n font-size: 12px;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n z-index: 10000;\n display: none;\n }\n \n #mobile-debug-header {\n background: rgba(255, 255, 255, 0.1);\n padding: 8px 12px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.2);\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-radius: 8px 8px 0 0;\n }\n \n #mobile-debug-header span {\n font-weight: bold;\n font-size: 13px;\n }\n \n #mobile-debug-close {\n background: none;\n border: none;\n color: #ffffff;\n font-size: 18px;\n cursor: pointer;\n padding: 0;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n #mobile-debug-close:hover {\n background: rgba(255, 255, 255, 0.1);\n border-radius: 4px;\n }\n \n #mobile-debug-content {\n padding: 12px;\n max-height: 340px;\n overflow-y: auto;\n word-wrap: break-word;\n line-height: 1.4;\n }\n \n .debug-message {\n margin-bottom: 4px;\n white-space: pre-wrap;\n }\n \n .debug-message.error {\n color: #ff6b6b;\n background: rgba(255, 107, 107, 0.1);\n padding: 4px;\n border-radius: 3px;\n border-left: 3px solid #ff6b6b;\n }\n \n .debug-message.warning {\n color: #ffd93d;\n background: rgba(255, 217, 61, 0.1);\n padding: 4px;\n border-radius: 3px;\n border-left: 3px solid #ffd93d;\n }\n \n .debug-timestamp {\n color: #888;\n font-size: 10px;\n }\n \n @media (max-width: 480px) {\n #mobile-debug-panel {\n width: calc(100vw - 20px);\n right: 10px;\n top: 10px;\n }\n }\n ",document.head.appendChild(e),document.body.appendChild(_debugPanel),document.getElementById("mobile-debug-close").onclick=hideDebug,_updateDebugDisplay()}function _updateDebugDisplay(){if(!_debugPanel)return;const e=document.getElementById("mobile-debug-content");e&&(e.innerHTML=_debugMessages.map(e=>"string"==typeof e?`<div class="debug-message">${e}</div>`:`<div class="debug-message ${e.type}">${e.text}</div>`).join(""),e.scrollTop=e.scrollHeight)}debug.clear=function(){_debugMessages=[],_debugPanel&&_updateDebugDisplay(),console.clear()},window.debug=debug,window.debugError=debugError,window.debugWarn=debugWarn,window.showDebug=showDebug,window.hideDebug=hideDebug,window.toggleDebug=toggleDebug,window.lockGestures=lockGestures,window.enableGyroTap=enableGyroTap,window.enableGyroButton=enableGyroButton,window.enableMicTap=enableMicTap,window.enableMicButton=enableMicButton,window.enableSoundTap=enableSoundTap,window.enableSoundButton=enableSoundButton,window.enableSpeechTap=enableSpeechTap,window.enableSpeechButton=enableSpeechButton,window.enableVibrationTap=enableVibrationTap,window.enableVibrationButton=enableVibrationButton,window.vibrate=vibrate,window.stopVibration=stopVibration,window.enableAllTap=enableAllTap,window.enableAllButton=enableAllButton,window.enableGyroCanvas=enableGyroCanvas,window.enableMicCanvas=enableMicCanvas,window.enableSoundCanvas=enableSoundCanvas,window.enableSpeechCanvas=enableSpeechCanvas,window.enableVibrationCanvas=enableVibrationCanvas,window.enableAllCanvas=enableAllCanvas,window.enableCameraCanvas=enableCameraCanvas,window.enableGyroBanner=enableGyroBanner,window.enableMicBanner=enableMicBanner,window.enableSoundBanner=enableSoundBanner,window.enableSpeechBanner=enableSpeechBanner,window.enableVibrationBanner=enableVibrationBanner,window.enableAllBanner=enableAllBanner,window.enableCameraBanner=enableCameraBanner,window.enableGyroOn=enableGyroOn,window.enableMicOn=enableMicOn,window.enableSoundOn=enableSoundOn,window.enableSpeechOn=enableSpeechOn,window.enableVibrationOn=enableVibrationOn,window.enableAllOn=enableAllOn,window.enableCameraOn=enableCameraOn;class PhoneCamera{constructor(e="user",n=!0,o="fitHeight"){this._active=e,this._mirror=n,this._mode=o,this._fixedWidth=640,this._fixedHeight=480,this._video=null,this._ready=!1,this._p5Instance=window,this._onReadyCallback=null,this._createCaptureRef=null,window._phoneCameras||(window._phoneCameras=[]),window._phoneCameras.push(this)}get ready(){return this._ready}get video(){return this._video}get videoElement(){return this._video?this._video.elt:null}get width(){if(!this._ready)return 0;return this.getDimensions().width}get height(){if(!this._ready)return 0;return this.getDimensions().height}get active(){return this._active}set active(e){"user"===e||"environment"===e?this._active!==e&&(this._active=e,this._ready&&this._switchCamera()):console.error('PhoneCamera: active must be "user" or "environment"')}get mirror(){return this._mirror}set mirror(e){this._mirror=!!e}get mode(){return this._mode}set mode(e){const n=["fitWidth","fitHeight","cover","contain","fixed"];n.includes(e)?this._mode=e:console.error("PhoneCamera: mode must be one of:",n.join(", "))}get fixedWidth(){return this._fixedWidth}set fixedWidth(e){this._fixedWidth=Math.max(1,e)}get fixedHeight(){return this._fixedHeight}set fixedHeight(e){this._fixedHeight=Math.max(1,e)}onReady(e){this._onReadyCallback=e,this._ready&&this._video&&this._video.elt&&this._video.elt.readyState>=2?e():this._video&&this._checkVideoReady()}_initializeCamera(){if(this._ready||this._video)return;const e={video:{facingMode:this._active},audio:!1};this._video=createCapture(e,()=>{this._ready=!0,this._video.hide(),console.log("✅ PhoneCamera ready"),this._checkVideoReady()}),this._video&&this._video.elt&&this._video.elt.addEventListener("loadeddata",()=>{this._ready=!0,this._checkVideoReady()})}_checkVideoReady(e=0){if(this._video&&this._video.elt&&this._video.elt.readyState>=2){if(this._onReadyCallback){const e=this._onReadyCallback;this._onReadyCallback=null,e()}}else e<100?setTimeout(()=>this._checkVideoReady(e+1),100):(console.warn("PhoneCamera: Video failed to reach ready state after 10 seconds"),_debugVisible&&debugWarn("PhoneCamera: Video not ready after timeout. Check camera permissions."))}_switchCamera(){if(!this._video)return;this._ready;this._ready=!1,this._video.remove();const e={video:{facingMode:this._active},audio:!1};this._video=createCapture(e,()=>{this._ready=!0,this._video.hide(),console.log(`✅ PhoneCamera switched to ${this._active} camera`)}),this._video&&this._video.elt&&this._video.elt.addEventListener("loadeddata",()=>{this._ready=!0})}remove(){this._video&&(this._video.remove(),this._video=null),this._ready=!1}getDimensions(){if(!this._ready||!this._video)return{x:0,y:0,width:0,height:0,scaleX:1,scaleY:1};const e=this._video.width,n=this._video.height,o="undefined"!=typeof width?width:window.innerWidth,t="undefined"!=typeof height?height:window.innerHeight;let a,i,r,s;if("fixed"===this._mode)a=this._fixedWidth,i=this._fixedHeight,r=(o-a)/2,s=(t-i)/2;else if("fitWidth"===this._mode)a=o,i=n/e*a,r=0,s=(t-i)/2;else if("fitHeight"===this._mode)i=t,a=e/n*i,r=(o-a)/2,s=0;else if("cover"===this._mode){const l=Math.max(o/e,t/n);a=e*l,i=n*l,r=(o-a)/2,s=(t-i)/2}else if("contain"===this._mode){const l=Math.min(o/e,t/n);a=e*l,i=n*l,r=(o-a)/2,s=(t-i)/2}return{x:r,y:s,width:a,height:i,scaleX:a/e,scaleY:i/n}}mapPoint(e,n){const o=this.getDimensions();let t=e*o.scaleX;const a=n*o.scaleY;this._mirror&&(t=o.width-t);return{x:t+o.x,y:a+o.y}}mapKeypoint(e){if(!e||void 0===e.x||void 0===e.y)return console.warn("PhoneCamera.mapKeypoint: invalid keypoint",e),e;const n=this.mapPoint(e.x,e.y);return{...e,x:n.x,y:n.y}}mapKeypoints(e){return Array.isArray(e)?e.map(e=>this.mapKeypoint(e)):(console.warn("PhoneCamera.mapKeypoints: expected array, got",typeof e),e)}_draw(){if(!this._ready||!this._video)return;const e=this.getDimensions(),n="undefined"!=typeof width?width:window.innerWidth;this._drawDebugLogged||(console.log("_draw() params:",{x:e.x,y:e.y,width:e.width,height:e.height,canvasWidth:n,mirror:this._mirror}),this._drawDebugLogged=!0),push(),this._mirror?(translate(n,0),scale(-1,1),image(this._video,e.x,e.y,e.width,e.height)):image(this._video,e.x,e.y,e.width,e.height),pop()}}function createPhoneCamera(e="user",n=!0,o="fitHeight"){return new PhoneCamera(e,n,o)}function enableCameraButton(e="ENABLE CAMERA",n="Starting camera..."){_createPermissionButton(e,n,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via button")})}function enableCameraTap(e="Tap screen to enable camera"){navigator.permissions&&navigator.permissions.query?navigator.permissions.query({name:"camera"}).then(n=>{"granted"===n.state?(console.log("✅ Camera permission already granted - auto-starting"),_requestCameraPermission()):_createTapToEnable(e,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via tap")})}).catch(()=>{_createTapToEnable(e,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via tap")})}):_createTapToEnable(e,async()=>{await _requestCameraPermission(),console.log("✅ Camera enabled via tap")})}async function _requestCameraPermission(){try{if(void 0!==window._phoneCameras&&Array.isArray(window._phoneCameras))for(let e of window._phoneCameras)!e||e._ready||e._video||e._initializeCamera();"function"==typeof userCameraReady&&userCameraReady(),_notifySketchReady()}catch(e){console.error("Camera permission error:",e),_debugVisible&&debugError("Camera permission error:",e),_notifySketchReady()}}if(window.createPhoneCamera=createPhoneCamera,window.enableCameraButton=enableCameraButton,window.enableCameraTap=enableCameraTap,"undefined"!=typeof p5&&p5.prototype){const e=p5.prototype.image;p5.prototype.image=function(...n){if(n[0]instanceof PhoneCamera){n[0]._draw()}else e.apply(this,n)}}"undefined"!=typeof p5&&p5.prototype&&(p5.prototype.lockGestures=lockGestures,p5.prototype.enableGyroTap=enableGyroTap,p5.prototype.enableGyroButton=enableGyroButton,p5.prototype.enableMicTap=enableMicTap,p5.prototype.enableMicButton=enableMicButton,p5.prototype.enableSoundTap=enableSoundTap,p5.prototype.enableSoundButton=enableSoundButton,p5.prototype.enableSpeechTap=enableSpeechTap,p5.prototype.enableSpeechButton=enableSpeechButton,p5.prototype.enableVibrationTap=enableVibrationTap,p5.prototype.enableVibrationButton=enableVibrationButton,p5.prototype.vibrate=vibrate,p5.prototype.stopVibration=stopVibration,p5.prototype.enableAllTap=enableAllTap,p5.prototype.enableAllButton=enableAllButton,p5.prototype.enableGyroCanvas=enableGyroCanvas,p5.prototype.enableMicCanvas=enableMicCanvas,p5.prototype.enableSoundCanvas=enableSoundCanvas,p5.prototype.enableSpeechCanvas=enableSpeechCanvas,p5.prototype.enableVibrationCanvas=enableVibrationCanvas,p5.prototype.enableAllCanvas=enableAllCanvas,p5.prototype.enableCameraCanvas=enableCameraCanvas,p5.prototype.enableGyroBanner=enableGyroBanner,p5.prototype.enableMicBanner=enableMicBanner,p5.prototype.enableSoundBanner=enableSoundBanner,p5.prototype.enableSpeechBanner=enableSpeechBanner,p5.prototype.enableVibrationBanner=enableVibrationBanner,p5.prototype.enableAllBanner=enableAllBanner,p5.prototype.enableCameraBanner=enableCameraBanner,p5.prototype.enableGyroOn=enableGyroOn,p5.prototype.enableMicOn=enableMicOn,p5.prototype.enableSoundOn=enableSoundOn,p5.prototype.enableSpeechOn=enableSpeechOn,p5.prototype.enableVibrationOn=enableVibrationOn,p5.prototype.enableAllOn=enableAllOn,p5.prototype.enableCameraOn=enableCameraOn,p5.prototype.createPhoneCamera=createPhoneCamera,p5.prototype.enableCameraButton=enableCameraButton,p5.prototype.enableCameraTap=enableCameraTap,p5.prototype.showDebug=showDebug,p5.prototype.hideDebug=hideDebug,p5.prototype.toggleDebug=toggleDebug,p5.prototype.debug=debug,p5.prototype.debugError=debugError,p5.prototype.debugWarn=debugWarn,console.log("✅ Mobile p5.js Permissions: p5.prototype functions registered")),"undefined"!=typeof p5&&"function"==typeof p5.registerAddon&&p5.registerAddon(function(e,n,o){n.lockGestures=lockGestures,n.enableGyroTap=enableGyroTap,n.enableGyroButton=enableGyroButton,n.enableMicTap=enableMicTap,n.enableMicButton=enableMicButton,n.enableSoundTap=enableSoundTap,n.enableSoundButton=enableSoundButton,n.enableSpeechTap=enableSpeechTap,n.enableSpeechButton=enableSpeechButton,n.enableVibrationTap=enableVibrationTap,n.enableVibrationButton=enableVibrationButton,n.vibrate=vibrate,n.stopVibration=stopVibration,n.enableAllTap=enableAllTap,n.enableAllButton=enableAllButton,n.enableGyroCanvas=enableGyroCanvas,n.enableMicCanvas=enableMicCanvas,n.enableSoundCanvas=enableSoundCanvas,n.enableSpeechCanvas=enableSpeechCanvas,n.enableVibrationCanvas=enableVibrationCanvas,n.enableAllCanvas=enableAllCanvas,n.enableCameraCanvas=enableCameraCanvas,n.enableGyroBanner=enableGyroBanner,n.enableMicBanner=enableMicBanner,n.enableSoundBanner=enableSoundBanner,n.enableSpeechBanner=enableSpeechBanner,n.enableVibrationBanner=enableVibrationBanner,n.enableAllBanner=enableAllBanner,n.enableCameraBanner=enableCameraBanner,n.enableGyroOn=enableGyroOn,n.enableMicOn=enableMicOn,n.enableSoundOn=enableSoundOn,n.enableSpeechOn=enableSpeechOn,n.enableVibrationOn=enableVibrationOn,n.enableAllOn=enableAllOn,n.enableCameraOn=enableCameraOn,n.createPhoneCamera=createPhoneCamera,n.enableCameraButton=enableCameraButton,n.enableCameraTap=enableCameraTap,n.showDebug=showDebug,n.hideDebug=hideDebug,n.toggleDebug=toggleDebug,n.debug=debug,n.debugError=debugError,n.debugWarn=debugWarn,console.log("✅ Mobile p5.js Permissions: registered as p5.js 2.0 addon")});
|
|
@@ -99,18 +99,18 @@ function draw()
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
// ==============================================
|
|
102
|
-
//
|
|
102
|
+
// INPUT EVENT FUNCTIONS
|
|
103
103
|
// ==============================================
|
|
104
104
|
|
|
105
105
|
// This function runs when a new touch begins
|
|
106
|
-
function
|
|
106
|
+
function mousePressed()
|
|
107
107
|
{
|
|
108
108
|
// Touch positions will be updated in draw() function
|
|
109
109
|
return false;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
// This function runs when a touch ends
|
|
113
|
-
function
|
|
113
|
+
function mouseReleased()
|
|
114
114
|
{
|
|
115
115
|
// Touch positions will be updated in draw() function
|
|
116
116
|
return false;
|
|
@@ -71,7 +71,7 @@ function showResult() {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// Touch started - start listening
|
|
74
|
-
function
|
|
74
|
+
function mousePressed() {
|
|
75
75
|
if (speechRec && window.speechEnabled && !isListening) {
|
|
76
76
|
isListening = true;
|
|
77
77
|
speechRec.start();
|
|
@@ -81,7 +81,7 @@ function touchStarted() {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
// Touch ended - stop listening
|
|
84
|
-
function
|
|
84
|
+
function mouseReleased() {
|
|
85
85
|
if (speechRec && isListening) {
|
|
86
86
|
isListening = false;
|
|
87
87
|
// Don't call stop - just let it process what was said
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
<!-- Load p5.js library -->
|
|
18
18
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/p5.min.js"></script>
|
|
19
|
+
<!-- For p5.js 2.0: <script src="https://cdn.jsdelivr.net/npm/p5@2/lib/p5.min.js"></script> -->
|
|
19
20
|
|
|
20
21
|
<!-- Load the mobile p5.js permissions library -->
|
|
21
22
|
<script src="https://cdn.jsdelivr.net/npm/p5-phone@1.6.4/dist/p5-phone.js"></script>
|
|
@@ -106,17 +106,17 @@ function draw()
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
// ==============================================
|
|
109
|
-
//
|
|
109
|
+
// INPUT EVENT FUNCTIONS
|
|
110
110
|
// ==============================================
|
|
111
111
|
// Note: Touch events are handled by enableGyroTap for permissions
|
|
112
112
|
|
|
113
|
-
function
|
|
113
|
+
function mousePressed()
|
|
114
114
|
{
|
|
115
115
|
// Permission handling is done by enableGyroTap
|
|
116
116
|
return false;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
function
|
|
119
|
+
function mouseReleased()
|
|
120
120
|
{
|
|
121
121
|
return false;
|
|
122
122
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
<!-- Load p5.js library -->
|
|
18
18
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/p5.min.js"></script>
|
|
19
|
+
<!-- For p5.js 2.0: <script src="https://cdn.jsdelivr.net/npm/p5@2/lib/p5.min.js"></script> -->
|
|
19
20
|
|
|
20
21
|
<!-- Load the mobile p5.js permissions library -->
|
|
21
22
|
<script src="https://cdn.jsdelivr.net/npm/p5-phone@1.6.4/dist/p5-phone.js"></script>
|
|
@@ -127,17 +127,17 @@ function draw()
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
// ==============================================
|
|
130
|
-
//
|
|
130
|
+
// INPUT EVENT FUNCTIONS
|
|
131
131
|
// ==============================================
|
|
132
132
|
// Note: Touch events are handled by enableGyroTap for permissions
|
|
133
133
|
|
|
134
|
-
function
|
|
134
|
+
function mousePressed()
|
|
135
135
|
{
|
|
136
136
|
// Permission handling is done by enableGyroTap
|
|
137
137
|
return false;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
function
|
|
140
|
+
function mouseReleased()
|
|
141
141
|
{
|
|
142
142
|
return false;
|
|
143
143
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
<!-- Load p5.js library -->
|
|
18
18
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/p5.min.js"></script>
|
|
19
|
+
<!-- For p5.js 2.0: <script src="https://cdn.jsdelivr.net/npm/p5@2/lib/p5.min.js"></script> -->
|
|
19
20
|
|
|
20
21
|
<!-- Load the mobile p5.js permissions library -->
|
|
21
22
|
<script src="https://cdn.jsdelivr.net/npm/p5-phone@1.6.4/dist/p5-phone.js"></script>
|
|
@@ -69,18 +69,18 @@ function draw()
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
// ==============================================
|
|
72
|
-
//
|
|
72
|
+
// INPUT EVENT FUNCTIONS
|
|
73
73
|
// ==============================================
|
|
74
74
|
|
|
75
75
|
// This function runs when a new touch begins
|
|
76
|
-
function
|
|
76
|
+
function mousePressed()
|
|
77
77
|
{
|
|
78
78
|
// Touch positions will be updated in draw() function
|
|
79
79
|
return false;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// This function runs when a touch ends
|
|
83
|
-
function
|
|
83
|
+
function mouseReleased()
|
|
84
84
|
{
|
|
85
85
|
// Touch positions will be updated in draw() function
|
|
86
86
|
return false;
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
<!-- Load p5.js library -->
|
|
18
18
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/p5.min.js"></script>
|
|
19
|
+
<!-- For p5.js 2.0: <script src="https://cdn.jsdelivr.net/npm/p5@2/lib/p5.min.js"></script> -->
|
|
19
20
|
|
|
20
21
|
<!-- Load p5.sound library for audio -->
|
|
21
22
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/addons/p5.sound.min.js"></script>
|
|
@@ -167,12 +167,12 @@ function drawVisualizers()
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
// ==============================================
|
|
170
|
-
//
|
|
170
|
+
// INPUT EVENT FUNCTIONS
|
|
171
171
|
// ==============================================
|
|
172
172
|
|
|
173
|
-
//
|
|
173
|
+
// mousePressed() runs when a touch begins
|
|
174
174
|
// This function starts playing audio based on which zone is touched
|
|
175
|
-
function
|
|
175
|
+
function mousePressed()
|
|
176
176
|
{
|
|
177
177
|
// Only process if sound system is enabled
|
|
178
178
|
if (!window.soundEnabled)
|
|
@@ -207,9 +207,9 @@ function touchStarted()
|
|
|
207
207
|
return false;
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
//
|
|
210
|
+
// mouseReleased() runs when a touch is released
|
|
211
211
|
// This function stops the audio when touch is released
|
|
212
|
-
function
|
|
212
|
+
function mouseReleased()
|
|
213
213
|
{
|
|
214
214
|
// Only process if sound system is enabled
|
|
215
215
|
if (window.soundEnabled)
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
<!-- Load p5.js library -->
|
|
18
18
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/p5.min.js"></script>
|
|
19
|
+
<!-- For p5.js 2.0: <script src="https://cdn.jsdelivr.net/npm/p5@2/lib/p5.min.js"></script> -->
|
|
19
20
|
|
|
20
21
|
<!-- Load p5.sound library for audio -->
|
|
21
22
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/addons/p5.sound.min.js"></script>
|