zimjs 20.0.5 → 20.0.8

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/src/zim.js CHANGED
@@ -57817,290 +57817,6 @@ RETURNS obj for chaining
57817
57817
  };//-34.7
57818
57818
 
57819
57819
 
57820
- /*--
57821
- obj.tilt = function(boundary, damp, factor, mode, type, call)
57822
-
57823
- tilt
57824
- zim DisplayObject method
57825
-
57826
- DESCRIPTION
57827
- Moves or positions an object based on device sensors (deviceorientation or devicemotion).
57828
- Automatically manages user sensor permission via ZIM PermissionAsk if permission has not yet been requested.
57829
-
57830
- NOTE
57831
- If permission has already been granted, tilt activates immediately.
57832
- If multiple objects call tilt() before permission is granted, they are queued and activated together once the user accepts.
57833
- ALSO see noTilt() to remove tilt behaviors.
57834
- ALSO see tiltBoundary() to dynamically change or clear the boundary rectangle.
57835
-
57836
- EXAMPLE
57837
- // Basic rolling ball constrained to stage bounds
57838
- const ball = new Circle(30, red)
57839
- .center()
57840
- .tilt(S);
57841
- END EXAMPLE
57842
-
57843
- EXAMPLE
57844
- // Custom damping, sensitivity factor, and boundary
57845
- new Rectangle(80, 80, blue)
57846
- .center()
57847
- .tilt({
57848
- boundary: new Boundary(50, 50, W - 100, H - 100),
57849
- damp: 0.08,
57850
- factor: 0.75,
57851
- call: (success, obj) => {
57852
- if (!success) new Pane("Device orientation not available", yellow).show();
57853
- }
57854
- });
57855
- END EXAMPLE
57856
-
57857
- PARAMETERS
57858
- ** supports DUO - parameters or single object with properties below
57859
- boundary - (default null) a ZIM Boundary object, an Array of [x, y, width, height], or true for the Stage dimensions
57860
- damp - (default 0.05) smoothing factor via ZIM Damp, or null / false for immediate direct tracking
57861
- factor - (default 0.5) sensitivity factor multiplier, or an Object with {x, y} for independent axis sensitivity
57862
- mode - (default "move") "move" for continuous velocity / rolling behavior, or "position" for tilt offset relative to starting coordinates
57863
- type - (default "deviceorientation") the sensor event type ("deviceorientation" or "devicemotion")
57864
- call - (default null) callback function called when permission resolves, receiving (success:Boolean, obj:DisplayObject)
57865
-
57866
- RETURNS obj for chaining
57867
- --*///+34.75
57868
- zim.tilt = function(obj, boundary, damp, factor, mode, type, call) {
57869
- var sig = "obj, boundary, damp, factor, mode, type, call";
57870
- var duo; if (duo = zob(zim.tilt, arguments, sig)) return duo;
57871
- if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("tilt", arguments); return obj;}
57872
- z_d("34.75");
57873
-
57874
- // MONITOR
57875
- var mID = "z~tilt";
57876
- if (obj && obj.mID && ((obj.mID[2] && obj.mID[2]=="-") || obj.mID[0]=="-")) mID = "z~-";
57877
-
57878
- if (zot(obj)) return;
57879
-
57880
- // Clean up any existing tilt on this object first
57881
- if (obj._tiltTicker) zim.noTilt(obj);
57882
-
57883
- var f = obj.frame || (typeof zdf != "undefined" ? zdf : WW.zdf);
57884
- var s = obj.stage || (f ? f.stage : null);
57885
-
57886
- // Set initial boundary
57887
- zim.tiltBoundary(obj, boundary);
57888
-
57889
- if (zot(damp)) damp = 0.05;
57890
- if (zot(factor)) factor = 0.5;
57891
- var factorX = typeof factor === "object" ? factor.x : factor;
57892
- var factorY = typeof factor === "object" ? factor.y : factor;
57893
- if (zot(mode)) mode = "move"; // "move" | "position" | "rotation"
57894
- if (zot(type)) type = "deviceorientation";
57895
-
57896
- // Damp angles for "move" mode (starts at 0) or positions for "position" mode
57897
- var dampX = damp ? new zim.Damp(mode == "position" ? obj.x : 0, damp) : null;
57898
- var dampY = damp ? new zim.Damp(mode == "position" ? obj.y : 0, damp) : null;
57899
- var currentRot = {x: 0, y: 0, z: 0};
57900
-
57901
- function updateTilt() {
57902
- if (mode == "move") {
57903
- // Damping the rotation angle gives smooth acceleration & deceleration
57904
- var rotY = dampX ? dampX.convert(currentRot.y) : currentRot.y;
57905
- var rotX = dampY ? dampY.convert(currentRot.x) : currentRot.x;
57906
- obj.x += rotY * factorX;
57907
- obj.y += rotX * factorY;
57908
- } else if (mode == "position") {
57909
- var targetX = (obj._tiltStartX != null ? obj._tiltStartX : obj.x) + currentRot.y * factorX * 10;
57910
- var targetY = (obj._tiltStartY != null ? obj._tiltStartY : obj.y) + currentRot.x * factorY * 10;
57911
- obj.x = dampX ? dampX.convert(targetX) : targetX;
57912
- obj.y = dampY ? dampY.convert(targetY) : targetY;
57913
- }
57914
-
57915
- // Dynamically applies boundary constraint
57916
- if (obj._tiltBoundary) {
57917
- obj.x = zim.constrain(obj.x, obj._tiltBoundary.x, obj._tiltBoundary.x + obj._tiltBoundary.width);
57918
- obj.y = zim.constrain(obj.y, obj._tiltBoundary.y, obj._tiltBoundary.y + obj._tiltBoundary.height);
57919
- }
57920
-
57921
- if (s) s.update();
57922
- }
57923
-
57924
- function activate() {
57925
- obj._tiltStartX = obj.x;
57926
- obj._tiltStartY = obj.y;
57927
- if (mode == "position" && dampX && dampY) {
57928
- dampX.immediate(obj.x);
57929
- dampY.immediate(obj.y);
57930
- }
57931
-
57932
- obj._tiltType = type;
57933
- obj._tiltListener = function(e) {
57934
- if (e.rotation) {
57935
- currentRot.x = e.rotation.x || 0;
57936
- currentRot.y = e.rotation.y || 0;
57937
- currentRot.z = e.rotation.z || 0;
57938
- } else {
57939
- currentRot.x = e.beta || 0;
57940
- currentRot.y = e.gamma || 0;
57941
- currentRot.z = e.alpha || 0;
57942
- }
57943
- };
57944
- f.on(type, obj._tiltListener);
57945
-
57946
- obj._tiltTicker = zim.Ticker.add(updateTilt);
57947
- if (call) call(true, obj);
57948
- }
57949
-
57950
- // Permission check & queueing
57951
- if (f._permissionGranted) {
57952
- activate();
57953
- } else if (f._permissionPending) {
57954
- f._permissionQueue.push(activate);
57955
- } else {
57956
- f._permissionPending = true;
57957
- f._permissionQueue = [activate];
57958
-
57959
- new zim.PermissionAsk(function(yes) {
57960
- f._permissionPending = false;
57961
- if (yes) {
57962
- f._permissionGranted = true;
57963
- zim.loop(f._permissionQueue, function(fn) { fn(); });
57964
- f._permissionQueue = [];
57965
- } else {
57966
- if (call) call(false, obj);
57967
- }
57968
- }, type);
57969
- }
57970
-
57971
- return obj;
57972
- };//-34.75
57973
-
57974
-
57975
- /*--
57976
- obj.noTilt = function()
57977
-
57978
- noTilt
57979
- zim DisplayObject method
57980
-
57981
- DESCRIPTION
57982
- Removes tilt listeners, removes internal ticker updates, and clears tilt boundary properties from the object.
57983
-
57984
- EXAMPLE
57985
- const player = new Circle(25, green).center().tilt(true);
57986
-
57987
- // Stop tilt control when game ends or is paused
57988
- player.noTilt();
57989
- END EXAMPLE
57990
-
57991
- RETURNS obj for chaining
57992
- --*///+34.76
57993
- zim.noTilt = function(obj) {
57994
- var sig = "obj";
57995
- var duo; if (duo = zob(zim.noTilt, arguments, sig)) return duo;
57996
- z_d("34.76");
57997
-
57998
- if (zot(obj) || !obj.on || !obj.zimTouch) return;
57999
-
58000
- // MONITOR
58001
- var mID = "z~noTilt";
58002
- if (obj && obj.mID && ((obj.mID[2] && obj.mID[2]=="-") || obj.mID[0]=="-")) mID = "z~-";
58003
-
58004
- if (zot(obj)) return;
58005
- var f = obj.frame || (typeof zdf != "undefined" ? zdf : WW.zdf);
58006
-
58007
- if (obj._tiltListener && f) {
58008
- f.off(obj._tiltType || "deviceorientation", obj._tiltListener);
58009
- obj._tiltListener = null;
58010
- }
58011
- if (obj._tiltTicker) {
58012
- zim.Ticker.remove(obj._tiltTicker);
58013
- obj._tiltTicker = null;
58014
- }
58015
- obj._tiltBoundary = null;
58016
-
58017
- return obj;
58018
-
58019
- };//-34.76
58020
-
58021
- /*--
58022
- obj.tiltBoundary = function(boundary, y, width, height)
58023
-
58024
- tiltBoundary
58025
- zim DisplayObject method
58026
-
58027
- DESCRIPTION
58028
- Dynamically sets, updates, or removes the boundary rectangle for an object with tilt().
58029
-
58030
- EXAMPLE
58031
- const marble = new Circle(20, purple).center().tilt(true);
58032
-
58033
- // Update boundary dynamically later (e.g., on resize or game level change)
58034
- marble.tiltBoundary(new Boundary(50, 50, W - 100, H - 100));
58035
-
58036
- // Or clear the boundary
58037
- // marble.tiltBoundary(null);
58038
- END EXAMPLE
58039
-
58040
- PARAMETERS
58041
- ** supports DUO - parameters or single object with properties below
58042
- boundary - (default null) a ZIM Boundary object, an Array of [x, y, width, height], true for Frame bounds, null / false to remove boundary, or the x position if passing (x, y, width, height) positionally
58043
- y - (default null) y coordinate if boundary parameter is used as x
58044
- width - (default null) width if boundary parameter is used as x
58045
- height - (default null) height if boundary parameter is used as x
58046
-
58047
- RETURNS obj for chaining
58048
- --*///+34.77
58049
- zim.tiltBoundary = function(obj, boundary, y, width, height) {
58050
- var sig = "obj, boundary, y, width, height";
58051
- var duo; if (duo = zob(zim.tiltBoundary, arguments, sig)) return duo;
58052
- z_d("34.77");
58053
- if (zot(obj) || !obj.on) return;
58054
- var f = obj.frame || (typeof zdf != "undefined" ? zdf : WW.zdf);
58055
- var s = obj.stage || (f ? f.stage : null);
58056
-
58057
- // Helper to calculate bounded limits keeping obj inside container bounds
58058
- function getContainedBoundary(bx, by, bw, bh) {
58059
- var b = obj.getBounds ? obj.getBounds() : null;
58060
- if (b) {
58061
- return new zim.Boundary(
58062
- bx - b.x * obj.scaleX,
58063
- by - b.y * obj.scaleY,
58064
- Math.max(0, bw - b.width * obj.scaleX),
58065
- Math.max(0, bh - b.height * obj.scaleY)
58066
- );
58067
- }
58068
- return new zim.Boundary(bx, by, bw, bh);
58069
- }
58070
-
58071
- if (zot(boundary) || boundary === false || boundary === null) {
58072
- obj._tiltBoundary = null;
58073
- } else if (boundary === true) {
58074
- // True -> Stage dimensions
58075
- var sw = f ? f.width : (s ? s.width : 0);
58076
- var sh = f ? f.height : (s ? s.height : 0);
58077
- obj._tiltBoundary = getContainedBoundary(0, 0, sw, sh);
58078
- } else if (boundary && (boundary.type == "Stage" || boundary == s || (s && boundary == s.canvas))) {
58079
- // Stage passed as boundary
58080
- var sw = boundary.width || (f ? f.width : 0);
58081
- var sh = boundary.height || (f ? f.height : 0);
58082
- obj._tiltBoundary = getContainedBoundary(0, 0, sw, sh);
58083
- } else if (boundary && boundary.type != "Boundary" && !Array.isArray(boundary) && (boundary.getBounds || boundary.width != null)) {
58084
- // DisplayObject (Container, Rectangle, etc.) passed as boundary
58085
- var b = boundary.getBounds ? boundary.getBounds() : null;
58086
- var bw = boundary.width != null ? boundary.width : (b ? b.width : 0);
58087
- var bh = boundary.height != null ? boundary.height : (b ? b.height : 0);
58088
- var bx = boundary.x || 0;
58089
- var by = boundary.y || 0;
58090
- obj._tiltBoundary = getContainedBoundary(bx, by, bw, bh);
58091
- } else if (Array.isArray(boundary)) {
58092
- obj._tiltBoundary = new zim.Boundary(boundary[0], boundary[1], boundary[2], boundary[3]);
58093
- } else if (typeof boundary === "number" && !zot(y)) {
58094
- obj._tiltBoundary = new zim.Boundary(boundary, y, width, height);
58095
- } else if (boundary && boundary.type == "Boundary") {
58096
- obj._tiltBoundary = boundary;
58097
- } else {
58098
- obj._tiltBoundary = null;
58099
- }
58100
-
58101
- return obj;
58102
- };//-34.77
58103
-
58104
57820
  /*--
58105
57821
  obj.effect = function(effect, x, y, width, height)
58106
57822
 
@@ -58555,6 +58271,814 @@ RETURNS obj for chaining
58555
58271
  return obj;
58556
58272
  };//-34.85
58557
58273
 
58274
+
58275
+ // SUBSECTION SENSORS
58276
+
58277
+ /*--
58278
+ obj.tilt = function(boundary, damp, factor, mode, type, ready)
58279
+
58280
+ tilt
58281
+ zim DisplayObject method
58282
+
58283
+ DESCRIPTION
58284
+ Moves or positions an object based on device sensors (deviceorientation or devicemotion).
58285
+ Automatically manages user sensor permission via ZIM PermissionAsk if permission has not yet been requested.
58286
+
58287
+ NOTE: If permission has already been granted, tilt activates immediately.
58288
+ If multiple objects call tilt(), turn(), or shake() before permission is granted, they are queued and activated together once the user accepts.
58289
+
58290
+ NOTE: To change the text of the Dialog set: F.sensorText = "OKAY?"; // BEFORE calling the tilt()
58291
+ To change buttons of the Dialog set: F.sensorAsk.yes.text = "OUI"; F.sensorAsk.no.text = "NON"; // AFTER calling the tilt()
58292
+
58293
+ ALSO: see noTilt() to remove tilt behaviors.
58294
+
58295
+ ALSO: see tiltBoundary() to dynamically change or clear the boundary rectangle.
58296
+
58297
+ EXAMPLE
58298
+ // Basic rolling ball constrained to stage bounds
58299
+ const ball = new Circle(30, red)
58300
+ .center()
58301
+ .tilt(S);
58302
+ END EXAMPLE
58303
+
58304
+ EXAMPLE
58305
+ // Custom damping, sensitivity factor, and boundary with ready callback
58306
+ new Rectangle(80, 80, blue)
58307
+ .center()
58308
+ .tilt({
58309
+ boundary: new Boundary(50, 50, W - 100, H - 100),
58310
+ damp: 0.08,
58311
+ factor: 0.75,
58312
+ ready: (success, obj) => {
58313
+ if (!success) new Pane("Device orientation not available", yellow).show();
58314
+ }
58315
+ });
58316
+ END EXAMPLE
58317
+
58318
+ PARAMETERS
58319
+ ** supports DUO - parameters or single object with properties below
58320
+ boundary - (default null) a ZIM Boundary object, an Array of [x, y, width, height], or true for the Stage dimensions
58321
+ damp - (default 0.05) smoothing factor via ZIM Damp, or null / false for immediate direct tracking
58322
+ factor - (default 0.5) sensitivity factor multiplier, or an Object with {x, y} for independent axis sensitivity
58323
+ mode - (default "move") "move" for continuous velocity / rolling behavior, or "position" for tilt offset relative to starting coordinates
58324
+ type - (default "deviceorientation") the sensor event type ("deviceorientation" or "devicemotion")
58325
+ ready - (default null) callback function called when permission resolves, receiving (success:Boolean, obj:DisplayObject)
58326
+
58327
+ RETURNS obj for chaining
58328
+ --*///+34.9
58329
+ zim.tilt = function(obj, boundary, damp, factor, mode, type, ready) {
58330
+ var sig = "obj, boundary, damp, factor, mode, type, ready";
58331
+ var duo; if (duo = zob(zim.tilt, arguments, sig)) return duo;
58332
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("tilt", arguments); return obj;}
58333
+ z_d("34.9");
58334
+
58335
+ // MONITOR
58336
+ var mID = "z~tilt";
58337
+ if (obj && obj.mID && ((obj.mID[2] && obj.mID[2]=="-") || obj.mID[0]=="-")) mID = "z~-";
58338
+
58339
+ if (zot(obj)) return;
58340
+
58341
+ // Clean up any existing tilt on this object first
58342
+ if (obj._tiltTicker) zim.noTilt(obj);
58343
+
58344
+ var f = obj.frame || (typeof zdf != "undefined" ? zdf : WW.zdf);
58345
+ var s = obj.stage || (f ? f.stage : null);
58346
+
58347
+ // Set initial boundary
58348
+ zim.tiltBoundary(obj, boundary);
58349
+
58350
+ if (zot(damp)) damp = 0.05;
58351
+ if (zot(factor)) factor = 0.5;
58352
+ var factorX = typeof factor === "object" ? factor.x : factor;
58353
+ var factorY = typeof factor === "object" ? factor.y : factor;
58354
+ if (zot(mode)) mode = "move";
58355
+ if (zot(type)) type = "deviceorientation";
58356
+
58357
+ var dampX = damp ? new zim.Damp(mode == "position" ? obj.x : 0, damp) : null;
58358
+ var dampY = damp ? new zim.Damp(mode == "position" ? obj.y : 0, damp) : null;
58359
+ var currentRot = {x: 0, y: 0, z: 0};
58360
+
58361
+ function updateTilt() {
58362
+ var orient = 0;
58363
+ if (typeof WW != "undefined") {
58364
+ if (WW.screen && WW.screen.orientation && WW.screen.orientation.angle != null) {
58365
+ orient = WW.screen.orientation.angle;
58366
+ } else if (typeof WW.orientation != "undefined") {
58367
+ orient = WW.orientation;
58368
+ }
58369
+ }
58370
+
58371
+ var beta = currentRot.x;
58372
+ var gamma = currentRot.y;
58373
+ var tiltX, tiltY;
58374
+
58375
+ if (orient == 90) {
58376
+ tiltX = beta;
58377
+ tiltY = -gamma;
58378
+ } else if (orient == -90 || orient == 270) {
58379
+ tiltX = -beta;
58380
+ tiltY = gamma;
58381
+ } else if (orient == 180) {
58382
+ tiltX = -gamma;
58383
+ tiltY = -beta;
58384
+ } else {
58385
+ tiltX = gamma;
58386
+ tiltY = beta;
58387
+ }
58388
+
58389
+ if (mode == "move") {
58390
+ var rotX = dampX ? dampX.convert(tiltX) : tiltX;
58391
+ var rotY = dampY ? dampY.convert(tiltY) : tiltY;
58392
+ obj.x += rotX * factorX;
58393
+ obj.y += rotY * factorY;
58394
+ } else if (mode == "position") {
58395
+ var targetX = (obj._tiltStartX != null ? obj._tiltStartX : obj.x) + tiltX * factorX * 10;
58396
+ var targetY = (obj._tiltStartY != null ? obj._tiltStartY : obj.y) + tiltY * factorY * 10;
58397
+ obj.x = dampX ? dampX.convert(targetX) : targetX;
58398
+ obj.y = dampY ? dampY.convert(targetY) : targetY;
58399
+ }
58400
+
58401
+ if (obj._tiltBoundary) {
58402
+ obj.x = zim.constrain(obj.x, obj._tiltBoundary.x, obj._tiltBoundary.x + obj._tiltBoundary.width);
58403
+ obj.y = zim.constrain(obj.y, obj._tiltBoundary.y, obj._tiltBoundary.y + obj._tiltBoundary.height);
58404
+ }
58405
+
58406
+ if (s) s.update();
58407
+ }
58408
+
58409
+ function activate() {
58410
+ obj._tiltStartX = obj.x;
58411
+ obj._tiltStartY = obj.y;
58412
+ if (mode == "position" && dampX && dampY) {
58413
+ dampX.immediate(obj.x);
58414
+ dampY.immediate(obj.y);
58415
+ }
58416
+
58417
+ obj._tiltType = type;
58418
+ obj._tiltListener = function(e) {
58419
+ if (e.rotation) {
58420
+ currentRot.x = e.rotation.x || 0;
58421
+ currentRot.y = e.rotation.y || 0;
58422
+ currentRot.z = e.rotation.z || 0;
58423
+ } else {
58424
+ currentRot.x = e.beta || 0;
58425
+ currentRot.y = e.gamma || 0;
58426
+ currentRot.z = e.alpha || 0;
58427
+ }
58428
+ };
58429
+ f.on(type, obj._tiltListener);
58430
+
58431
+ obj._tiltTicker = zim.Ticker.add(updateTilt);
58432
+ if (ready) ready(true, obj);
58433
+ }
58434
+
58435
+ // Shared Permission check & queueing
58436
+ if (f._permissionGranted) {
58437
+ activate();
58438
+ } else if (f._permissionPending) {
58439
+ f._permissionQueue.push({ activate: activate, reject: function() { if (ready) ready(false, obj); } });
58440
+ } else {
58441
+ f._permissionPending = true;
58442
+ f._permissionQueue = [{ activate: activate, reject: function() { if (ready) ready(false, obj); } }];
58443
+
58444
+ new zim.PermissionAsk(function(yes) {
58445
+ f._permissionPending = false;
58446
+ if (yes) {
58447
+ f._permissionGranted = true;
58448
+ zim.loop(f._permissionQueue, function(item) { item.activate(); });
58449
+ } else {
58450
+ zim.loop(f._permissionQueue, function(item) { item.reject(); });
58451
+ }
58452
+ f._permissionQueue = [];
58453
+ }, type);
58454
+ }
58455
+
58456
+ return obj;
58457
+ };//-34.9
58458
+
58459
+
58460
+ /*--
58461
+ obj.noTilt = function()
58462
+
58463
+ noTilt
58464
+ zim DisplayObject method
58465
+
58466
+ DESCRIPTION
58467
+ Removes tilt listeners, ticker updates, and clears tilt boundary properties from the object.
58468
+
58469
+ EXAMPLE
58470
+ const player = new Circle(25, green).center().tilt(true);
58471
+
58472
+ // Stop tilt control when game ends or is paused
58473
+ player.noTilt();
58474
+ END EXAMPLE
58475
+
58476
+ RETURNS obj for chaining
58477
+ --*///+34.91
58478
+ zim.noTilt = function(obj) {
58479
+ var sig = "obj";
58480
+ var duo; if (duo = zob(zim.noTilt, arguments, sig)) return duo;
58481
+ z_d("34.91");
58482
+
58483
+ if (zot(obj) || !obj.on || !obj.zimTouch) return;
58484
+
58485
+ // MONITOR
58486
+ var mID = "z~noTilt";
58487
+ if (obj && obj.mID && ((obj.mID[2] && obj.mID[2]=="-") || obj.mID[0]=="-")) mID = "z~-";
58488
+
58489
+ var f = obj.frame || (typeof zdf != "undefined" ? zdf : WW.zdf);
58490
+
58491
+ if (obj._tiltListener && f) {
58492
+ f.off(obj._tiltType || "deviceorientation", obj._tiltListener);
58493
+ obj._tiltListener = null;
58494
+ }
58495
+ if (obj._tiltTicker) {
58496
+ zim.Ticker.remove(obj._tiltTicker);
58497
+ obj._tiltTicker = null;
58498
+ }
58499
+ obj._tiltBoundary = null;
58500
+
58501
+ return obj;
58502
+ };//-34.91
58503
+
58504
+
58505
+ /*--
58506
+ obj.tiltBoundary = function(boundary, y, width, height)
58507
+
58508
+ tiltBoundary
58509
+ zim DisplayObject method
58510
+
58511
+ DESCRIPTION
58512
+ Dynamically sets, updates, or removes the boundary rectangle for an object with tilt().
58513
+ Accurately accounts for registration points (like centerReg), scaling, and rotation using zim.boundsToGlobal().
58514
+
58515
+ EXAMPLE
58516
+ const rect = new Rectangle(120, 80, purple).centerReg().tilt(S);
58517
+
58518
+ // Update boundary dynamically later
58519
+ rect.tiltBoundary(new Boundary(50, 50, W - 100, H - 100));
58520
+
58521
+ // Or clear the boundary
58522
+ // rect.tiltBoundary(null);
58523
+ END EXAMPLE
58524
+
58525
+ PARAMETERS
58526
+ ** supports DUO - parameters or single object with properties below
58527
+ boundary - (default null) a ZIM Boundary object, an Array of [x, y, width, height], true for Frame bounds, null / false to remove boundary, or the x position if passing (x, y, width, height) positionally
58528
+ y - (default null) y coordinate if boundary parameter is used as x
58529
+ width - (default null) width if boundary parameter is used as x
58530
+ height - (default null) height if boundary parameter is used as x
58531
+
58532
+ RETURNS obj for chaining
58533
+ --*///+34.92
58534
+ zim.tiltBoundary = function(obj, boundary, y, width, height) {
58535
+ var sig = "obj, boundary, y, width, height";
58536
+ var duo; if (duo = zob(zim.tiltBoundary, arguments, sig)) return duo;
58537
+ z_d("34.92");
58538
+ if (zot(obj) || !obj.on) return;
58539
+ var f = obj.frame || (typeof zdf != "undefined" ? zdf : WW.zdf);
58540
+ var s = obj.stage || (f ? f.stage : null);
58541
+
58542
+ function getContainedBoundary(bx, by, bw, bh) {
58543
+ var gb = zim.boundsToGlobal ? zim.boundsToGlobal(obj) : (obj.getTransformedBounds ? obj.getTransformedBounds() : null);
58544
+ if (!gb) return new zim.Boundary(bx, by, bw, bh);
58545
+
58546
+ var leftOffset = gb.x - obj.x;
58547
+ var rightOffset = (gb.x + gb.width) - obj.x;
58548
+ var topOffset = gb.y - obj.y;
58549
+ var bottomOffset = (gb.y + gb.height) - obj.y;
58550
+
58551
+ var minXAllowed = bx - leftOffset;
58552
+ var maxXAllowed = bx + bw - rightOffset;
58553
+ var minYAllowed = by - topOffset;
58554
+ var maxYAllowed = by + bh - bottomOffset;
58555
+
58556
+ if (maxXAllowed < minXAllowed) maxXAllowed = minXAllowed;
58557
+ if (maxYAllowed < minYAllowed) maxYAllowed = minYAllowed;
58558
+
58559
+ return new zim.Boundary(
58560
+ minXAllowed,
58561
+ minYAllowed,
58562
+ maxXAllowed - minXAllowed,
58563
+ maxYAllowed - minYAllowed
58564
+ );
58565
+ }
58566
+
58567
+ if (zot(boundary) || boundary === false || boundary === null) {
58568
+ obj._tiltBoundary = null;
58569
+ } else if (boundary === true) {
58570
+ var sw = f ? f.width : (s ? s.width : 0);
58571
+ var sh = f ? f.height : (s ? s.height : 0);
58572
+ obj._tiltBoundary = getContainedBoundary(0, 0, sw, sh);
58573
+ } else if (boundary && (boundary.type == "Stage" || boundary == s || (s && boundary == s.canvas))) {
58574
+ var sw = boundary.width || (f ? f.width : 0);
58575
+ var sh = boundary.height || (f ? f.height : 0);
58576
+ obj._tiltBoundary = getContainedBoundary(0, 0, sw, sh);
58577
+ } else if (boundary && boundary.type != "Boundary" && !Array.isArray(boundary) && (boundary.getBounds || boundary.width != null)) {
58578
+ var b = boundary.getBounds ? boundary.getBounds() : null;
58579
+ var bw = boundary.width != null ? boundary.width : (b ? b.width : 0);
58580
+ var bh = boundary.height != null ? boundary.height : (b ? b.height : 0);
58581
+ var bx = boundary.x || 0;
58582
+ var by = boundary.y || 0;
58583
+ obj._tiltBoundary = getContainedBoundary(bx, by, bw, bh);
58584
+ } else if (Array.isArray(boundary)) {
58585
+ obj._tiltBoundary = getContainedBoundary(boundary[0], boundary[1], boundary[2], boundary[3]);
58586
+ } else if (typeof boundary === "number" && !zot(y)) {
58587
+ obj._tiltBoundary = getContainedBoundary(boundary, y, width, height);
58588
+ } else if (boundary && boundary.type == "Boundary") {
58589
+ obj._tiltBoundary = getContainedBoundary(boundary.x, boundary.y, boundary.width, boundary.height);
58590
+ } else {
58591
+ obj._tiltBoundary = null;
58592
+ }
58593
+
58594
+ return obj;
58595
+ };//-34.92
58596
+
58597
+
58598
+ /*--
58599
+ obj.turn = function(damp, factor, mode, min, max, type, ready)
58600
+
58601
+ turn
58602
+ zim DisplayObject method
58603
+
58604
+ DESCRIPTION
58605
+ Rotates an object based on device yaw / roll orientation (turning the device like a steering wheel, dial, or compass).
58606
+ Automatically detects whether the device is held upright (full 360-degree steering wheel) or flat (compass) with seamless transitions between both.
58607
+ By default, inverts rotation so the object stays oriented relative to the world as the device turns.
58608
+ Automatically manages user sensor permission via ZIM PermissionAsk if permission has not yet been requested.
58609
+
58610
+ NOTE: If permission has already been granted, turn activates immediately.
58611
+ If multiple objects call tilt(), turn(), or shake() before permission is granted, they are queued and activated together once the user accepts.
58612
+ Rotation is applied relative to the object's initial rotation when turn() is called (for example, an arrow rotated -90 to point up will maintain that -90 offset).
58613
+
58614
+ NOTE: To change the text of the Dialog set: F.sensorText = "OKAY?"; // BEFORE calling the turn()
58615
+ To change buttons of the Dialog set: F.sensorAsk.yes.text = "OUI"; F.sensorAsk.no.text = "NON"; // AFTER calling the turn()
58616
+
58617
+ ALSO: see noTurn() to remove turning behaviors.
58618
+
58619
+ EXAMPLE
58620
+ // Point an arrow with device heading (stays pointing up in world space)
58621
+ const arrow = new Arrow({type:"thick"}).sca(4).rot(-90).centerReg().turn();
58622
+ END EXAMPLE
58623
+
58624
+ EXAMPLE
58625
+ // Continuous steering wheel mode with damping and rotation limits
58626
+ const wheel = new Circle(80, red).center().turn({
58627
+ damp: 0.1,
58628
+ factor: 1.5,
58629
+ mode: "relative",
58630
+ min: -90,
58631
+ max: 90,
58632
+ ready: (success, obj) => {
58633
+ if (!success) zog("Sensors denied");
58634
+ }
58635
+ });
58636
+ END EXAMPLE
58637
+
58638
+ PARAMETERS
58639
+ ** supports DUO - parameters or single object with properties below
58640
+ damp - (default 0.05) smoothing factor via ZIM Damp, or null / false for direct tracking
58641
+ factor - (default 1) sensitivity factor multiplier (use negative to invert rotation direction)
58642
+ mode - (default "relative") "relative" (offset from starting device orientation), "absolute" (compass heading), or "continuous" (continuous spin based on turn angle)
58643
+ min - (default null) minimum rotation angle limit in degrees, or null for unrestricted
58644
+ max - (default null) maximum rotation angle limit in degrees, or null for unrestricted
58645
+ type - (default "deviceorientation") the sensor event type ("deviceorientation")
58646
+ ready - (default null) callback function called when permission resolves, receiving (success:Boolean, obj:DisplayObject)
58647
+
58648
+ RETURNS obj for chaining
58649
+ --*///+34.93
58650
+ zim.turn = function(obj, damp, factor, mode, min, max, type, ready) {
58651
+ var sig = "obj, damp, factor, mode, min, max, type, ready";
58652
+ var duo; if (duo = zob(zim.turn, arguments, sig)) return duo;
58653
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("turn", arguments); return obj;}
58654
+ z_d("34.93");
58655
+
58656
+ // MONITOR
58657
+ var mID = "z~turn";
58658
+ if (obj && obj.mID && ((obj.mID[2] && obj.mID[2]=="-") || obj.mID[0]=="-")) mID = "z~-";
58659
+
58660
+ if (zot(obj)) return;
58661
+
58662
+ // Clean up any existing turn on this object first
58663
+ if (obj._turnTicker) zim.noTurn(obj);
58664
+
58665
+ var f = obj.frame || (typeof zdf != "undefined" ? zdf : WW.zdf);
58666
+ var s = obj.stage || (f ? f.stage : null);
58667
+
58668
+ if (zot(damp)) damp = 0.05;
58669
+ if (zot(factor)) factor = 1;
58670
+ if (zot(mode)) mode = "relative";
58671
+ if (zot(type)) type = "deviceorientation";
58672
+
58673
+ var dampRot = damp ? new zim.Damp(obj.rotation, damp) : null;
58674
+ var startDeviceAngle = null;
58675
+ var currentDeviceAngle = null;
58676
+ var lastMode = null;
58677
+
58678
+ function angleDiff(a, b) {
58679
+ var diff = (a - b) % 360;
58680
+ if (diff < -180) diff += 360;
58681
+ if (diff > 180) diff -= 360;
58682
+ return diff;
58683
+ }
58684
+
58685
+ function unwrap(target, current) {
58686
+ var diff = (target - current) % 360;
58687
+ if (diff < -180) diff += 360;
58688
+ if (diff > 180) diff -= 360;
58689
+ return current + diff;
58690
+ }
58691
+
58692
+ function updateTurn() {
58693
+ if (startDeviceAngle === null || currentDeviceAngle === null) return;
58694
+
58695
+ var orient = 0;
58696
+ if (typeof WW != "undefined") {
58697
+ if (WW.screen && WW.screen.orientation && WW.screen.orientation.angle != null) {
58698
+ orient = WW.screen.orientation.angle;
58699
+ } else if (typeof WW.orientation != "undefined") {
58700
+ orient = WW.orientation;
58701
+ }
58702
+ }
58703
+
58704
+ var startRot = obj._turnStartRot != null ? obj._turnStartRot : 0;
58705
+ var targetRot = obj.rotation;
58706
+
58707
+ if (mode == "relative") {
58708
+ var diff = angleDiff(currentDeviceAngle, startDeviceAngle);
58709
+ targetRot = startRot - diff * factor;
58710
+ } else if (mode == "absolute") {
58711
+ var absHeading = (currentDeviceAngle - orient + 360) % 360;
58712
+ targetRot = startRot - absHeading * factor;
58713
+ } else if (mode == "continuous") {
58714
+ var cDiff = angleDiff(currentDeviceAngle, startDeviceAngle);
58715
+ targetRot = obj.rotation - (cDiff * factor * 0.05);
58716
+ }
58717
+
58718
+ if (min != null || max != null) {
58719
+ targetRot = zim.constrain(targetRot, min != null ? min : -Infinity, max != null ? max : Infinity);
58720
+ }
58721
+
58722
+ if (dampRot) {
58723
+ var unwrapped = unwrap(targetRot, obj.rotation);
58724
+ obj.rotation = dampRot.convert(unwrapped);
58725
+ } else {
58726
+ obj.rotation = targetRot;
58727
+ }
58728
+
58729
+ if (s) s.update();
58730
+ }
58731
+
58732
+ function activate() {
58733
+ obj._turnStartRot = obj.rotation;
58734
+ startDeviceAngle = null;
58735
+ currentDeviceAngle = null;
58736
+ lastMode = null;
58737
+ if (dampRot) dampRot.immediate(obj.rotation);
58738
+
58739
+ obj._turnType = type;
58740
+ obj._turnListener = function(e) {
58741
+ var beta = e.rotation ? e.rotation.x : (e.beta || 0);
58742
+ var gamma = e.rotation ? e.rotation.y : (e.gamma || 0);
58743
+ var alpha = e.rotation && e.rotation.z != null ? e.rotation.z : (e.alpha != null ? (360 - e.alpha) : 0);
58744
+
58745
+ var isUpright = Math.abs(beta) > 20 || Math.abs(gamma) > 20;
58746
+ var curMode = isUpright ? "upright" : "flat";
58747
+ var ang;
58748
+
58749
+ if (isUpright) {
58750
+ var radB = beta * (Math.PI / 180);
58751
+ var radG = gamma * (Math.PI / 180);
58752
+ ang = Math.atan2(Math.sin(radG), Math.cos(radG) * Math.sin(radB)) * (180 / Math.PI);
58753
+ } else {
58754
+ ang = alpha;
58755
+ }
58756
+
58757
+ if (startDeviceAngle === null) {
58758
+ startDeviceAngle = ang;
58759
+ lastMode = curMode;
58760
+ if (dampRot) dampRot.immediate(obj.rotation);
58761
+ } else if (lastMode !== null && curMode !== lastMode) {
58762
+ var prevDiff = angleDiff(currentDeviceAngle, startDeviceAngle);
58763
+ startDeviceAngle = ang - prevDiff;
58764
+ lastMode = curMode;
58765
+ }
58766
+
58767
+ currentDeviceAngle = ang;
58768
+ };
58769
+ f.on(type, obj._turnListener);
58770
+
58771
+ obj._turnTicker = zim.Ticker.add(updateTurn);
58772
+ if (ready) ready(true, obj);
58773
+ }
58774
+
58775
+ // Shared Permission check & queueing
58776
+ if (f._permissionGranted) {
58777
+ activate();
58778
+ } else if (f._permissionPending) {
58779
+ f._permissionQueue.push({ activate: activate, reject: function() { if (ready) ready(false, obj); } });
58780
+ } else {
58781
+ f._permissionPending = true;
58782
+ f._permissionQueue = [{ activate: activate, reject: function() { if (ready) ready(false, obj); } }];
58783
+
58784
+ new zim.PermissionAsk(function(yes) {
58785
+ f._permissionPending = false;
58786
+ if (yes) {
58787
+ f._permissionGranted = true;
58788
+ zim.loop(f._permissionQueue, function(item) { item.activate(); });
58789
+ } else {
58790
+ zim.loop(f._permissionQueue, function(item) { item.reject(); });
58791
+ }
58792
+ f._permissionQueue = [];
58793
+ }, type);
58794
+ }
58795
+
58796
+ return obj;
58797
+ };//-34.93
58798
+
58799
+ /*--
58800
+ obj.noTurn = function()
58801
+
58802
+ noTurn
58803
+ zim DisplayObject method
58804
+
58805
+ DESCRIPTION
58806
+ Removes turn listeners and ticker updates from the object.
58807
+
58808
+ EXAMPLE
58809
+ const compass = new Triangle().center().turn();
58810
+
58811
+ // Stop turn tracking
58812
+ compass.noTurn();
58813
+ END EXAMPLE
58814
+
58815
+ RETURNS obj for chaining
58816
+ --*///+34.94
58817
+ zim.noTurn = function(obj) {
58818
+ var sig = "obj";
58819
+ var duo; if (duo = zob(zim.noTurn, arguments, sig)) return duo;
58820
+ z_d("34.94");
58821
+
58822
+ if (zot(obj) || !obj.on || !obj.zimTouch) return;
58823
+
58824
+ // MONITOR
58825
+ var mID = "z~noTurn";
58826
+ if (obj && obj.mID && ((obj.mID[2] && obj.mID[2]=="-") || obj.mID[0]=="-")) mID = "z~-";
58827
+
58828
+ var f = obj.frame || (typeof zdf != "undefined" ? zdf : WW.zdf);
58829
+
58830
+ if (obj._turnListener && f) {
58831
+ f.off(obj._turnType || "deviceorientation", obj._turnListener);
58832
+ obj._turnListener = null;
58833
+ }
58834
+ if (obj._turnTicker) {
58835
+ zim.Ticker.remove(obj._turnTicker);
58836
+ obj._turnTicker = null;
58837
+ }
58838
+
58839
+ return obj;
58840
+ };//-34.94
58841
+
58842
+
58843
+ /*--
58844
+ obj.shake = function(call, stopCall, threshold, wait, factor, type, ready)
58845
+
58846
+ shake
58847
+ zim DisplayObject method
58848
+
58849
+ DESCRIPTION
58850
+ Triggers a callback and dispatches a "shake" event whenever the device is shaken beyond a threshold acceleration force.
58851
+ Also triggers a stopCall and dispatches a "shakestop" event when the device stops shaking.
58852
+ Automatically manages user sensor permission via ZIM PermissionAsk if permission has not yet been requested.
58853
+
58854
+ NOTE: If permission has already been granted, shake activates immediately.
58855
+ If multiple objects call tilt(), turn(), or shake() before permission is granted, they are queued and activated together once the user accepts.
58856
+
58857
+ NOTE: To change the text of the Dialog set: F.sensorText = "OKAY?"; // BEFORE calling the shake()
58858
+ To change buttons of the Dialog set: F.sensorAsk.yes.text = "OUI"; F.sensorAsk.no.text = "NON"; // AFTER calling the shake()
58859
+
58860
+ ALSO: see noShake() to remove shake listeners.
58861
+
58862
+ EXAMPLE
58863
+ const color = series(red,green,blue);
58864
+ const bottle = new Rectangle(80, 160, purple).centerReg().shake({
58865
+ call: (total) => {
58866
+ bottle.color = color();
58867
+ S.update();
58868
+ },
58869
+ stopCall: (obj) => {
58870
+ emitter.spurt(20);
58871
+ obj.color = purple;
58872
+ }
58873
+ });
58874
+ const emitter = new Emitter({startPaused:true}).loc(bottle);
58875
+ END EXAMPLE
58876
+
58877
+ EXAMPLE
58878
+ // Custom sensitivity threshold with ready callback
58879
+ const circle = new Circle().center().shake(
58880
+ (total, x, y) => { circle.impulse(x * 10, y * 10); },
58881
+ () => { zog("Stopped shaking!"); },
58882
+ 12, // threshold
58883
+ 0.4, // wait
58884
+ 1, // factor
58885
+ "devicemotion",
58886
+ (success) => { if (!success) zog("Sensors unavailable"); }
58887
+ );
58888
+ END EXAMPLE
58889
+
58890
+ PARAMETERS
58891
+ ** supports DUO - parameters or single object with properties below
58892
+ call - (default null) callback function when shaken, receiving (total:Number, x:Number, y:Number, z:Number, obj:DisplayObject, event:Object)
58893
+ stopCall - (default null) callback function called when shaking stops after wait seconds of stillness, receiving (obj:DisplayObject)
58894
+ threshold - (default 10) minimum 3D acceleration magnitude delta required to trigger a shake
58895
+ wait - (default 0.5) stillness duration in seconds before triggering stopCall, and cooldown between repeat shake pulses
58896
+ factor - (default 1) sensitivity factor multiplier
58897
+ type - (default "devicemotion") the sensor event type ("devicemotion")
58898
+ ready - (default null) callback function called when permission resolves, receiving (success:Boolean, obj:DisplayObject)
58899
+
58900
+ EVENTS
58901
+ Dispatches a "shake" event on obj with event properties: total, x, y, z, and event.
58902
+ Dispatches a "shakestop" event on obj when shaking stops.
58903
+
58904
+ RETURNS obj for chaining
58905
+ --*///+34.95
58906
+ zim.shake = function(obj, call, stopCall, threshold, wait, factor, type, ready) {
58907
+ var sig = "obj, call, stopCall, threshold, wait, factor, type, ready";
58908
+ var duo; if (duo = zob(zim.shake, arguments, sig)) return duo;
58909
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("shake", arguments); return obj;}
58910
+ z_d("34.95");
58911
+
58912
+ // MONITOR
58913
+ var mID = "z~shake";
58914
+ if (obj && obj.mID && ((obj.mID[2] && obj.mID[2]=="-") || obj.mID[0]=="-")) mID = "z~-";
58915
+
58916
+ if (zot(obj)) return;
58917
+
58918
+ // Clean up any existing shake on this object first
58919
+ if (obj._shakeListener) zim.noShake(obj);
58920
+
58921
+ var f = obj.frame || (typeof zdf != "undefined" ? zdf : WW.zdf);
58922
+ var s = obj.stage || (f ? f.stage : null);
58923
+
58924
+ if (zot(threshold)) threshold = 10;
58925
+ if (zot(wait)) wait = 0.5;
58926
+ if (zot(factor)) factor = 1;
58927
+ if (zot(type)) type = "devicemotion";
58928
+
58929
+ var lastX = 0, lastY = 0, lastZ = 0;
58930
+ var lastTime = 0;
58931
+
58932
+ function handleMotion(e) {
58933
+ var acc = e.acceleration && (e.acceleration.x != null || e.acceleration.y != null) ?
58934
+ e.acceleration : (e.accelerationIncludingGravity || e);
58935
+
58936
+ var ax = acc.x || 0;
58937
+ var ay = acc.y || 0;
58938
+ var az = acc.z || 0;
58939
+
58940
+ var deltaX = ax - lastX;
58941
+ var deltaY = ay - lastY;
58942
+ var deltaZ = az - lastZ;
58943
+
58944
+ lastX = ax;
58945
+ lastY = ay;
58946
+ lastZ = az;
58947
+
58948
+ var mag = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) * factor;
58949
+
58950
+ if (mag >= threshold) {
58951
+ var now = Date.now();
58952
+
58953
+ if (obj._shakeStopTimeout) obj._shakeStopTimeout.clear();
58954
+
58955
+ obj._shakeStopTimeout = zim.timeout(wait, function() {
58956
+ obj._shakeStopTimeout = null;
58957
+ if (stopCall) stopCall(obj);
58958
+ obj.dispatchEvent({
58959
+ type: "shakestop",
58960
+ event: e
58961
+ });
58962
+ if (s) s.update();
58963
+ });
58964
+
58965
+ if (now - lastTime >= wait * 1000) {
58966
+ lastTime = now;
58967
+
58968
+ var orient = 0;
58969
+ if (typeof WW != "undefined") {
58970
+ if (WW.screen && WW.screen.orientation && WW.screen.orientation.angle != null) {
58971
+ orient = WW.screen.orientation.angle;
58972
+ } else if (typeof WW.orientation != "undefined") {
58973
+ orient = WW.orientation;
58974
+ }
58975
+ }
58976
+
58977
+ var shakeX, shakeY, shakeZ = deltaZ * factor;
58978
+ if (orient == 90) {
58979
+ shakeX = deltaY * factor;
58980
+ shakeY = -deltaX * factor;
58981
+ } else if (orient == -90 || orient == 270) {
58982
+ shakeX = -deltaY * factor;
58983
+ shakeY = deltaX * factor;
58984
+ } else if (orient == 180) {
58985
+ shakeX = -deltaX * factor;
58986
+ shakeY = -deltaY * factor;
58987
+ } else {
58988
+ shakeX = deltaX * factor;
58989
+ shakeY = deltaY * factor;
58990
+ }
58991
+
58992
+ if (call) call(mag, shakeX, shakeY, shakeZ, obj, e);
58993
+ obj.dispatchEvent({
58994
+ type: "shake",
58995
+ total: mag,
58996
+ x: shakeX,
58997
+ y: shakeY,
58998
+ z: shakeZ,
58999
+ event: e
59000
+ });
59001
+
59002
+ if (s) s.update();
59003
+ }
59004
+ }
59005
+ }
59006
+
59007
+ function activate() {
59008
+ obj._shakeType = type;
59009
+ obj._shakeListener = handleMotion;
59010
+ f.on(type, obj._shakeListener);
59011
+ if (ready) ready(true, obj);
59012
+ }
59013
+
59014
+ // Shared Permission check & queueing
59015
+ if (f._permissionGranted) {
59016
+ activate();
59017
+ } else if (f._permissionPending) {
59018
+ f._permissionQueue.push({ activate: activate, reject: function() { if (ready) ready(false, obj); } });
59019
+ } else {
59020
+ f._permissionPending = true;
59021
+ f._permissionQueue = [{ activate: activate, reject: function() { if (ready) ready(false, obj); } }];
59022
+
59023
+ new zim.PermissionAsk(function(yes) {
59024
+ f._permissionPending = false;
59025
+ if (yes) {
59026
+ f._permissionGranted = true;
59027
+ zim.loop(f._permissionQueue, function(item) { item.activate(); });
59028
+ } else {
59029
+ zim.loop(f._permissionQueue, function(item) { item.reject(); });
59030
+ }
59031
+ f._permissionQueue = [];
59032
+ }, type);
59033
+ }
59034
+
59035
+ return obj;
59036
+ };//-34.95
59037
+
59038
+
59039
+ /*--
59040
+ obj.noShake = function()
59041
+
59042
+ noShake
59043
+ zim DisplayObject method
59044
+
59045
+ DESCRIPTION
59046
+ Removes shake listeners and pending stop timers from the object.
59047
+
59048
+ EXAMPLE
59049
+ const box = new Rectangle(80, 80, red).center().shake(onShake);
59050
+
59051
+ // Stop shake listening
59052
+ box.noShake();
59053
+ END EXAMPLE
59054
+
59055
+ RETURNS obj for chaining
59056
+ --*///+34.96
59057
+ zim.noShake = function(obj) {
59058
+ var sig = "obj";
59059
+ var duo; if (duo = zob(zim.noShake, arguments, sig)) return duo;
59060
+ z_d("34.96");
59061
+
59062
+ if (zot(obj) || !obj.on || !obj.zimTouch) return;
59063
+
59064
+ // MONITOR
59065
+ var mID = "z~noShake";
59066
+ if (obj && obj.mID && ((obj.mID[2] && obj.mID[2]=="-") || obj.mID[0]=="-")) mID = "z~-";
59067
+
59068
+ var f = obj.frame || (typeof zdf != "undefined" ? zdf : WW.zdf);
59069
+
59070
+ if (obj._shakeListener && f) {
59071
+ f.off(obj._shakeType || "devicemotion", obj._shakeListener);
59072
+ obj._shakeListener = null;
59073
+ }
59074
+ if (obj._shakeStopTimeout) {
59075
+ obj._shakeStopTimeout.clear();
59076
+ obj._shakeStopTimeout = null;
59077
+ }
59078
+
59079
+ return obj;
59080
+ };//-34.96
59081
+
58558
59082
  // SUBSECTION HIT TESTS
58559
59083
 
58560
59084
  /*--
@@ -93079,6 +93603,10 @@ loadFailObj - the object that shows if images are broken - will be given a type
93079
93603
  startTime - datestamp of when frame was made - used internally
93080
93604
  retina - read-only Boolean as to whether stage (as opposed to the canvas) was scaled for pixelDensity during Frame creation
93081
93605
  reloaded - read-only Boolean as to whether page has been reloaded - uses window.performance.getEntriesByType
93606
+ sensorText - (default null) a String to customize the label inside the PermissionAsk popup for device sensors
93607
+ sensorAsk - reference to the PermissionAsk Pane instance created for device sensors
93608
+ camText - (default null) a String to customize the label inside the PermissionAsk popup for camera/mic
93609
+ camAsk - reference to the PermissionAsk Pane instance created for camera/mic
93082
93610
 
93083
93611
  ALSO see F, S, W, H, M global variables which reference the default frame, its stage and width and height, and if on mobile
93084
93612
 
@@ -93333,6 +93861,15 @@ zim.Frame = function(scaling, width, height, color, outerColor, ready, assets, p
93333
93861
  var tagID;
93334
93862
  var tag;
93335
93863
 
93864
+ // ZIM 020 Sensors Patch
93865
+ this.sensorText = null; // custom text for sensor PermissionAsk dialog
93866
+ this.sensorAsk = null; // reference to PermissionAsk instance for sensors
93867
+ this.camText = null; // custom text for camera/mic PermissionAsk dialog
93868
+ this.camAsk = null; // reference to PermissionAsk instance for camera/mic
93869
+ this._permissionGranted = false;
93870
+ this._permissionPending = false;
93871
+ this._permissionQueue = [];
93872
+
93336
93873
  // 0. part of TEN PATCH
93337
93874
  // need to keep check for resize and assets for dispatching ready
93338
93875
  var resizeReady = false;
@@ -98230,29 +98767,26 @@ NOTE: this started as SensorAsk but the class has been adjusted to handle other
98230
98767
 
98231
98768
  NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
98232
98769
 
98770
+ NOTE: sensor prompt text can be customized prior to calling with F.sensorText = "Custom message";
98771
+
98233
98772
  EXAMPLE
98234
98773
  // DEVICE ORIENTATION - gives angle of device in all 3 dimensions
98235
98774
  // See https://zimjs.com/zapp/Z_Q5UYS
98236
- // Note: this is NOT an orientation event to see if phone is portrait or landscape (see Frame orientation event)
98237
98775
  new PermissionAsk(yes=>{
98238
- if (yes) { // the user answered yes to PermissionAsk
98239
- // all code goes in here
98776
+ if (yes) {
98240
98777
  new Label("Tilt the device to move circle").alp(.3).pos(0,30,CENTER);
98241
98778
  const circle = new Circle().center();
98242
98779
  const amount = .5;
98243
- const compass = new Line(60, 4, light, "arrow").rot(90).centerReg(circle); // point up
98780
+ const compass = new Line(60, 4, light, "arrow").rot(90).centerReg(circle);
98244
98781
  F.on("deviceorientation", e=>{
98245
- // for tilt
98246
98782
  circle.mov(e.rotation.y*amount, e.rotation.x*amount);
98247
98783
  circle.x = constrain(circle.x, 0, W);
98248
98784
  circle.y = constrain(circle.y, 0, H);
98249
- // for compass use e.rotation.z
98250
- // which has 0 angle at device start rotation (not necessarily North)
98251
- compass.rot(90-e.rotation.z); // rotate opposite device rotation
98785
+ compass.rot(90-e.rotation.z);
98252
98786
  S.update();
98253
98787
  });
98254
- } else { // the user answered no to PermissionAsk
98255
- new Pane("SENSOR not available",yellow).show();
98788
+ } else {
98789
+ new Pane("SENSOR not available", yellow).show();
98256
98790
  }
98257
98791
  });
98258
98792
  END EXAMPLE
@@ -98262,13 +98796,11 @@ EXAMPLE
98262
98796
  // See https://zimjs.com/zapp/Z_XF8JM
98263
98797
  new PermissionAsk(init, "devicemotion");
98264
98798
  function init(yes) {
98265
- if (yes) { // the user answered yes to PermissionAsk
98266
- // all code goes in here
98799
+ if (yes) {
98267
98800
  new Label("Shake the device").center();
98268
98801
  S.update();
98269
98802
  let id;
98270
98803
  F.on("devicemotion", e=>{
98271
- // for shake
98272
98804
  if (
98273
98805
  Math.abs(e.acceleration.x) > 5 ||
98274
98806
  Math.abs(e.acceleration.y) > 5 ||
@@ -98285,36 +98817,12 @@ function init(yes) {
98285
98817
  });
98286
98818
  }
98287
98819
  });
98288
- } else { // the user answered no to PermissionAsk
98289
- new Pane("SENSOR not available",yellow).show();
98820
+ } else {
98821
+ new Pane("SENSOR not available", yellow).show();
98290
98822
  }
98291
98823
  }
98292
98824
  END EXAMPLE
98293
98825
 
98294
- EXAMPLE
98295
- // CAM
98296
- // on iOS, the app must be interacted with before using mic or cam
98297
- // goes right to permissions on computer and android
98298
- // pops up a PermissionAsk Pane on iOS then if yes, goes to permissions on iOS
98299
- new PermissionAsk(init, "cam");
98300
- function init(val) {
98301
- new Label(val).center(); // media stream if yes to permissions otherwise false
98302
- S.update();
98303
- }
98304
- END EXAMPLE
98305
-
98306
- EXAMPLE
98307
- // MIC
98308
- // on iOS, the app must be interacted with before using mic or cam
98309
- // this goes right to permissions on computer and android
98310
- // but pops up a PermissionAsk Pane on iOS then if yes, goes to permissions on iOS
98311
- new PermissionAsk(init, "mic"); // or "cam" or "miccam"
98312
- function init(val) {
98313
- new Label(val).center(); // media stream if yes to permissions otherwise false
98314
- S.update();
98315
- }
98316
- END EXAMPLE
98317
-
98318
98826
  PARAMETERS - accepts ZIM DUO regular parameters in order or a configuration object with parameters as properties
98319
98827
  callback - the function to callback when permission is accepted
98320
98828
  if the permissionType is deviceorientation or devicemotion this will receive true for accept or false for no permission
@@ -98344,13 +98852,6 @@ dispose() - dispose the PermissionAsk
98344
98852
  ALSO: see all the methods of a zim Pane()
98345
98853
  including hide()
98346
98854
 
98347
- ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
98348
- drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
98349
- addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
98350
- ALSO: see the CreateJS Easel Docs for Container methods, such as:
98351
- on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
98352
- addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
98353
-
98354
98855
  PROPERTIES
98355
98856
  type - name of class as a string
98356
98857
  permissionType - the type of permission requested
@@ -98358,17 +98859,6 @@ label - reference to the zim Label
98358
98859
  yes - reference to the zim Button with YES
98359
98860
  no - reference to the zim Button with NO
98360
98861
 
98361
- ALSO: see ZIM Pane for properties such as:
98362
- backdropColor, etc.
98363
-
98364
- ALSO: see ZIM Container for properties such as:
98365
- width, height, widthOnly, heightOnly, draggable, level, depth, group
98366
- blendMode, hue, saturation, brightness, contrast, etc.
98367
-
98368
- ALSO: see the CreateJS Easel Docs for Container properties, such as:
98369
- x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
98370
- alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
98371
-
98372
98862
  --*///+83.01
98373
98863
  zim.PermissionAsk = function(callback, permissionType, color, backgroundColor, style, group, inherit) {
98374
98864
  var sig = "callback, permissionType, color, backgroundColor, style, group, inherit";
@@ -98391,6 +98881,15 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
98391
98881
  this.mID = "z~"+(DS.monitor===false?"-":this.type);
98392
98882
 
98393
98883
  var that = this;
98884
+ var frame = WW.zdf;
98885
+
98886
+ if (frame) {
98887
+ if (permissionType == "mic" || permissionType == "cam" || permissionType == "miccam") {
98888
+ frame.camAsk = that;
98889
+ } else {
98890
+ frame.sensorAsk = that;
98891
+ }
98892
+ }
98394
98893
 
98395
98894
  Style.addGroup("PermissionAsk", {
98396
98895
  color:color,
@@ -98406,7 +98905,15 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
98406
98905
  var okay = false;
98407
98906
  that.yes = new zim.Button({label:"YES", width:100, group:"PermissionAsk"}).sca(.65).pos(0,30,CENTER,TOP,this);
98408
98907
  var words = {deviceorientation:"sensors", devicemotion:"sensors", mic:"mic", cam:"cam", miccam:"mic/cam"};
98409
- that.label = new zim.Label("Use " + (words[pt]?words[pt]:"feature") + "?", 30, null, color, null, null, null, "center").sca(.9).centerReg(this);
98908
+
98909
+ var defaultMsg = "Use " + (words[pt]?words[pt]:"feature") + "?";
98910
+ var promptMsg = defaultMsg;
98911
+ if (frame) {
98912
+ if ((pt == "mic" || pt == "cam" || pt == "miccam") && frame.camText) promptMsg = frame.camText;
98913
+ else if (frame.sensorText) promptMsg = frame.sensorText;
98914
+ }
98915
+
98916
+ that.label = new zim.Label(promptMsg, 30, null, color, null, null, null, "center").sca(.9).centerReg(this);
98410
98917
  that.no = new zim.Button({label:"NO", width:100, group:"PermissionAsk"}).sca(.65).pos(0,30,CENTER,BOTTOM,this);
98411
98918
 
98412
98919
  new zim.Circle(110, zim.clear, color, 1).center(this).alp(.8);
@@ -98414,7 +98921,6 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
98414
98921
  new zim.Circle(130, zim.clear, color, 1).center(this).alp(.2);
98415
98922
  if (style!==false) zim.styleTransforms(this, DS);
98416
98923
 
98417
- var frame = WW.zdf;
98418
98924
  if (pt == "mic" || pt == "cam" || pt == "miccam") {
98419
98925
  if (M=="ios") {
98420
98926
  setPane();
@@ -98432,40 +98938,55 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
98432
98938
  return;
98433
98939
  }
98434
98940
 
98435
- // sensors only
98941
+ // Sensors probe: iOS uses PermissionAsk popup; Android/Desktop probes hardware directly
98436
98942
  if (typeof DeviceOrientationEvent != "undefined" && DeviceOrientationEvent && typeof DeviceOrientationEvent.requestPermission == "function") {
98437
98943
  setPane();
98438
98944
  } else {
98439
- var called = false;
98440
- WW.addEventListener(permissionType, testMe);
98441
- // instead of testing for mobile - some laptops like chromebook have sensors so test for a reading
98945
+ var tested = false;
98946
+ var timer = setTimeout(function() {
98947
+ if (tested) return;
98948
+ tested = true;
98949
+ WW.removeEventListener(permissionType, testMe);
98950
+ callback(false, 3); // 3 - timeout / no sensor hardware (e.g. desktop)
98951
+ }, 1000);
98952
+
98442
98953
  function testMe(e) {
98443
- if (okay) return;
98444
- if (permissionType=="deviceorientation") {
98445
- if (e.alpha==null || (e.alpha==0&&e.beta==0&&e.gamma==0)) callback(false, 1);
98446
- else setEvents();
98954
+ if (tested || okay) return;
98955
+ if (permissionType == "deviceorientation") {
98956
+ if (e.alpha != null || e.beta != null || e.gamma != null) {
98957
+ tested = true;
98958
+ clearTimeout(timer);
98959
+ WW.removeEventListener(permissionType, testMe);
98960
+ setEvents();
98961
+ } else {
98962
+ tested = true;
98963
+ clearTimeout(timer);
98964
+ WW.removeEventListener(permissionType, testMe);
98965
+ callback(false, 1);
98966
+ }
98447
98967
  } else {
98448
- // if (!e.acceleration || e.acceleration.x==null || (e.acceleration.x==0&&e.acceleration.y==0&&e.acceleration.z==0)) callback(false);
98449
- if (!e.acceleration || e.acceleration.x==null) callback(false, 2);
98450
- else setEvents();
98451
- }
98452
- called = true;
98453
- WW.removeEventListener(permissionType, testMe);
98454
- }
98455
- setTimeout(function(){
98456
- if (!called) callback(false, 3);
98457
- }, 5000);
98968
+ var hasAcc = e.acceleration && (e.acceleration.x != null || e.acceleration.y != null || e.acceleration.z != null);
98969
+ var hasGrav = e.accelerationIncludingGravity && (e.accelerationIncludingGravity.x != null || e.accelerationIncludingGravity.y != null || e.accelerationIncludingGravity.z != null);
98970
+ if (hasAcc || hasGrav) {
98971
+ tested = true;
98972
+ clearTimeout(timer);
98973
+ WW.removeEventListener(permissionType, testMe);
98974
+ setEvents();
98975
+ } else {
98976
+ tested = true;
98977
+ clearTimeout(timer);
98978
+ WW.removeEventListener(permissionType, testMe);
98979
+ callback(false, 2);
98980
+ }
98981
+ }
98982
+ }
98983
+ WW.addEventListener(permissionType, testMe);
98458
98984
  }
98459
98985
 
98460
98986
  var lastZ = 0;
98461
98987
  var flip = 0;
98462
98988
  function deviceorientationEvent(e) {
98463
- // for some reason, reporting alpha as increasing going counter counterclockwise
98464
- // so this code makes it increase going clockwise
98465
98989
  var z = 360-e.alpha;
98466
- // compass is subtracting 180 if device screen is pointing down
98467
- // in a VR helmet this would be looking slightly up from the horizon...
98468
- // so removing this flip with the following code
98469
98990
  if (Math.abs(z-lastZ) > 180 - 45 && Math.abs(z-lastZ) < 180 + 45) flip = flip == 0 ? 180 : 0;
98470
98991
  lastZ = z;
98471
98992
  e.rotation = {x:e.beta, y:e.gamma, z:(z + flip) % 360};
@@ -98475,6 +98996,7 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
98475
98996
  frame.dispatchEvent(e);
98476
98997
  }
98477
98998
  function setEvents() {
98999
+ if (frame) frame._permissionGranted = true;
98478
99000
  if (permissionType=="deviceorientation") {
98479
99001
  frame.zimDeviceorientationEvent = deviceorientationEvent;
98480
99002
  WW.addEventListener("deviceorientation", frame.zimDeviceorientationEvent);
@@ -100320,25 +100842,40 @@ function zimify(obj, a, b, c, d, list) {
100320
100842
  gestureRect:function(boundary, update) {
100321
100843
  return zim.gestureBoundary(this, boundary, update);
100322
100844
  },
100323
-
100324
- tilt:function(boundary, damp, factor, mode, type, call) {
100845
+ addPhysics:function(dynamic, contract, shape, friction, linear, angular, density, restitution, maskBits, categoryBits, physics) {
100846
+ if (isDUO(arguments)) {arguments[0].obj = this; return zim.addPhysics(arguments[0]);}
100847
+ else {return zim.addPhysics(this, dynamic, contract, shape, friction, linear, angular, density, restitution, maskBits, categoryBits, physics);}
100848
+ },
100849
+ removePhysics:function() {
100850
+ return zim.removePhysics(this);
100851
+ },
100852
+ tilt:function(boundary, damp, factor, mode, type, ready) {
100325
100853
  if (isDUO(arguments)) {arguments[0].obj = this; return zim.tilt(arguments[0]);}
100326
- else {return zim.tilt(this, boundary, damp, factor, mode, type, call);}
100854
+ else {return zim.tilt(this, boundary, damp, factor, mode, type, ready);}
100327
100855
  },
100328
100856
  noTilt:function() {
100329
100857
  if (isDUO(arguments)) {arguments[0].obj = this; return zim.noTilt(arguments[0]);}
100330
100858
  else {return zim.noTilt(this);}
100331
100859
  },
100332
- tiltBoundary:function(boundary, update) {
100333
- return zim.tiltBoundary(this, boundary, update);
100860
+ tiltBoundary:function(boundary, y, width, height) {
100861
+ if (isDUO(arguments)) {arguments[0].obj = this; return zim.tiltBoundary(arguments[0]);}
100862
+ else {return zim.tiltBoundary(this, boundary, y, width, height);}
100334
100863
  },
100335
-
100336
- addPhysics:function(dynamic, contract, shape, friction, linear, angular, density, restitution, maskBits, categoryBits, physics) {
100337
- if (isDUO(arguments)) {arguments[0].obj = this; return zim.addPhysics(arguments[0]);}
100338
- else {return zim.addPhysics(this, dynamic, contract, shape, friction, linear, angular, density, restitution, maskBits, categoryBits, physics);}
100864
+ turn:function(damp, factor, mode, min, max, type, ready) {
100865
+ if (isDUO(arguments)) {arguments[0].obj = this; return zim.turn(arguments[0]);}
100866
+ else {return zim.turn(this, damp, factor, mode, min, max, type, ready);}
100339
100867
  },
100340
- removePhysics:function() {
100341
- return zim.removePhysics(this);
100868
+ noTurn:function() {
100869
+ if (isDUO(arguments)) {arguments[0].obj = this; return zim.noTurn(arguments[0]);}
100870
+ else {return zim.noTurn(this);}
100871
+ },
100872
+ shake:function(call, stopCall, threshold, wait, factor, type, ready) {
100873
+ if (isDUO(arguments)) {arguments[0].obj = this; return zim.shake(arguments[0]);}
100874
+ else {return zim.shake(this, call, stopCall, threshold, wait, factor, type, ready);}
100875
+ },
100876
+ noShake:function() {
100877
+ if (isDUO(arguments)) {arguments[0].obj = this; return zim.noShake(arguments[0]);}
100878
+ else {return zim.noShake(this);}
100342
100879
  },
100343
100880
  hitTestPoint:function(x, y, boundsCheck) {
100344
100881
  return zim.hitTestPoint(this, x, y, boundsCheck);
@@ -107367,14 +107904,18 @@ export let transform = zim.transform;
107367
107904
  export let gesture = zim.gesture;
107368
107905
  export let noGesture = zim.noGesture;
107369
107906
  export let gestureBoundary = zim.gestureBoundary;
107370
- export let tilt = zim.tilt;
107371
- export let noTilt = zim.noTilt;
107372
- export let tiltBoundary = zim.tiltBoundary;
107373
107907
  export let effect = zim.effect;
107374
107908
  export let updateEffects = zim.updateEffects;
107375
107909
  export let noEffect = zim.noEffect;
107376
107910
  export let addPhysics = zim.addPhysics;
107377
107911
  export let removePhysics = zim.removePhysics;
107912
+ export let tilt = zim.tilt;
107913
+ export let noTilt = zim.noTilt;
107914
+ export let tiltBoundary = zim.tiltBoundary;
107915
+ export let turn = zim.turn;
107916
+ export let noTurn = zim.noTurn;
107917
+ export let shake = zim.shake;
107918
+ export let noShake = zim.noShake;
107378
107919
  export let hitTestPoint = zim.hitTestPoint;
107379
107920
  export let hitTestReg = zim.hitTestReg;
107380
107921
  export let hitTestRect = zim.hitTestRect;