zimjs 20.0.1 → 20.0.3

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
@@ -5219,6 +5219,75 @@ zim.sortObject = function(obj,property,reverse) {
5219
5219
  return sorted;
5220
5220
  };//-12.1
5221
5221
 
5222
+ /*--
5223
+ zim.orderContainer = function(container, order)
5224
+
5225
+ orderContainer
5226
+ zim function
5227
+
5228
+ DESCRIPTION
5229
+ Arranges original indexed children of a Container to new positions based on provided array.
5230
+
5231
+ NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
5232
+
5233
+ EXAMPLE
5234
+ const holder = new Container().loc(20,20);
5235
+
5236
+ new Rectangle(120, 120, red).loc(0, 0, holder);
5237
+ new Rectangle(120, 120, blue).loc(40, 40, holder);
5238
+ new Rectangle(120, 120, green).loc(80, 80, holder);
5239
+ new Rectangle(120, 120, yellow).loc(120, 120, holder);
5240
+
5241
+ S.on("stagemousedown", () => {
5242
+ reorderByIndexes(holder, [3, 1, 0, 2]);
5243
+ // puts old index 3 as the lowest (0)
5244
+ // leaves old index 1 at 1
5245
+ // sets old index 0 to the third highest (2)
5246
+ // and puts old index 2 at the higest(3)
5247
+ S.update();
5248
+ });
5249
+ END EXAMPLE
5250
+
5251
+ PARAMETERS
5252
+ container - an Container
5253
+ order - an array showing the old index numbers in a new order
5254
+ beware, this can be confusing - this is NOT saying the first child will have this new index, etc.
5255
+ but rather which old index is moved to the first level, second level, etc.
5256
+
5257
+ RETURNS the container
5258
+ --*///+12.2
5259
+
5260
+ zim.orderContainer = function(container, order) {
5261
+ z_d("12.2");
5262
+
5263
+ var kids = container.children.slice();
5264
+ var used = {};
5265
+ var ordered = [];
5266
+ var valid = true;
5267
+
5268
+ if (!kids || kids.length !== order.length) return container;
5269
+
5270
+ loop(order, function(index) {
5271
+ if (index < 0 || index >= kids.length || used[index]) {
5272
+ valid = false;
5273
+ return true;
5274
+ }
5275
+ used[index] = true;
5276
+ ordered.push(kids[index]);
5277
+ });
5278
+
5279
+ if (!valid || ordered.length !== kids.length) return container;
5280
+
5281
+ loop(ordered, function(child) {
5282
+ child.top();
5283
+ });
5284
+
5285
+ return container;
5286
+
5287
+
5288
+
5289
+ };//-12.2
5290
+
5222
5291
  /*--
5223
5292
  zim.arraysEqual = function(a, b, strict)
5224
5293
 
@@ -13329,13 +13398,15 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
13329
13398
  if (prop=="stroke-opacity") aa = val;
13330
13399
  });
13331
13400
  return [f,s,ss,a,aa];
13332
- }
13401
+ }
13333
13402
 
13334
- function processShape(type, tag) {
13403
+ function processShape(type, tag) {
13404
+
13335
13405
  var shape;
13336
13406
  var g = processGeneral(tag); // want ES6
13337
13407
  var f = g[0], s = g[1], ss = g[2], x = g[5], y = g[6];
13338
13408
  // var a = g[3], aa = g[4];
13409
+
13339
13410
  if (type == "circle") {
13340
13411
  var r = Number(tag.getAttribute("r").trim());
13341
13412
  var d = r*.5523;
@@ -13370,6 +13441,7 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
13370
13441
  if (p.indexOf(",") != -1) {
13371
13442
  zim.loop(p.split(" "), function (point) {
13372
13443
  var pp = point.split(",");
13444
+ if (!pp || pp.length<2) return;
13373
13445
  points.push([Number(pp[0].trim()), Number(pp[1].trim()),0,0,0,0,0,0,"none"]);
13374
13446
  });
13375
13447
  } else {
@@ -13442,7 +13514,6 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
13442
13514
 
13443
13515
  // beatgammit on StackOverflow
13444
13516
  function ellipse(x, y, xDis, yDis) {
13445
- zog(x, y, xDis, yDis)
13446
13517
  var kappa = 0.5522848, // 4 * ((√(2) - 1) / 3)
13447
13518
  ox = xDis * kappa, // control point offset horizontal
13448
13519
  oy = yDis * kappa, // control point offset vertical
@@ -13503,6 +13574,8 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
13503
13574
 
13504
13575
  }
13505
13576
 
13577
+
13578
+
13506
13579
  function processGeneral(tag) {
13507
13580
  // any styles on the tag overwrites general styles or attributes
13508
13581
  var f,s,ss,a,aa;
@@ -13518,18 +13591,25 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
13518
13591
  // kv comments: need to apply string cleansing, application bugs when there is a semi colon character used in tags.
13519
13592
  // get rid of semi colon,
13520
13593
  // any attributes on the tag overwrites styles or general
13521
- f = tag.getAttribute("fill")?tag.getAttribute("fill"):!zot(f)?f:generalFill;
13522
- s = tag.getAttribute("stroke")?tag.getAttribute("stroke"):!zot(s)?s:generalStroke;
13523
- ss = tag.getAttribute("stroke-width")?tag.getAttribute("stroke-width"):!zot(ss)?ss:generalStrokeSize;
13594
+ // was defaulting to generalFill, generalStroke, generalStrokeSize - made null in 020 patch
13595
+ f = tag.getAttribute("fill")?tag.getAttribute("fill"):!zot(f)?f:null;
13596
+ s = tag.getAttribute("stroke")?tag.getAttribute("stroke"):!zot(s)?s:null;
13597
+ ss = tag.getAttribute("stroke-width")?tag.getAttribute("stroke-width"):!zot(ss)?ss:null;
13524
13598
  a = tag.getAttribute("fill-opacity")?tag.getAttribute("fill-opacity"):!zot(a)?a:generalAlpha;
13525
13599
  aa = tag.getAttribute("stroke-opacity")?tag.getAttribute("stroke-opacity"):!zot(aa)?aa:generalStrokeAlpha;
13526
13600
 
13601
+ f = parseGradients(f, tag);
13602
+ s = parseGradients(s, tag);
13527
13603
  var x = tag.getAttribute("x")?tag.getAttribute("x"):0;
13528
13604
  x = tag.getAttribute("cx")?tag.getAttribute("cx"):x;
13529
13605
  var y = tag.getAttribute("y")?tag.getAttribute("y"):0;
13530
13606
  y = tag.getAttribute("cy")?tag.getAttribute("cy"):y;
13531
- if (!zot(a) && !zot(f)) f = zim.convertColor(f, "rgba", Number(a));
13532
- if (!zot(aa) && !zot(s)) s = zim.convertColor(s, "rgba", Number(aa));
13607
+ if (f && !f.type=="RadialColor" && !f.type=="GradientColor") {
13608
+ if (!zot(a) && !zot(f)) f = zim.convertColor(f, "rgba", Number(a));
13609
+ }
13610
+ if (s && !s.type=="RadialColor" && !s.type=="GradientColor") {
13611
+ if (!zot(aa) && !zot(s)) s = zim.convertColor(s, "rgba", Number(aa));
13612
+ }
13533
13613
  return [f,s,Number(ss),Number(a),Number(aa),Number(x),Number(y)];
13534
13614
  }
13535
13615
 
@@ -14011,7 +14091,7 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
14011
14091
  if (points.length >= 2)
14012
14092
  // M 100 350 l 150 -300
14013
14093
  if (lastCommand == "z" || lastCommand == "Z") {type = "blob";}
14014
- //if (zot(shape)) {
14094
+ //if (zot(shape)) {
14015
14095
  if (type == "squiggle") shape = new zim.Squiggle(s, ss, points, null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, null, null, null, interactive);
14016
14096
  else shape = new zim.Blob(f, s, ss, points, null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, null, null, null, interactive);
14017
14097
  shape.loc(0,0,that);
@@ -14055,6 +14135,294 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
14055
14135
  return processPath(path,false);
14056
14136
  };
14057
14137
 
14138
+
14139
+ // AI converting svg gradients to createjs format
14140
+
14141
+ function svgGradientToArray(gradientNode, tag) {
14142
+ // Returns:
14143
+ // linear: [0, [colors, ratios, x0, y0, x1, y1]]
14144
+ // radial: [1, [colors, ratios, x0, y0, r0, x1, y1, r1]]
14145
+ //
14146
+ // Assumes:
14147
+ // - gradient coordinates are based on SVG top-left space
14148
+ // - ZIM shape uses same width/height but centered origin
14149
+ // - tag is the SVG element using the gradient
14150
+
14151
+ if (!gradientNode || !gradientNode.tagName || !tag) return null;
14152
+
14153
+ var type = gradientNode.tagName.toLowerCase();
14154
+ var box = tag.getBBox ? tag.getBBox() : {x:0, y:0, width:0, height:0};
14155
+ var width = box.width || 0;
14156
+ var height = box.height || 0;
14157
+
14158
+ function num(v, fallback) {
14159
+ var n;
14160
+ if (fallback == null) fallback = 0;
14161
+ if (v == null || v === "") return fallback;
14162
+ n = parseFloat(v);
14163
+ return isNaN(n) ? fallback : n;
14164
+ }
14165
+
14166
+ function trim(s) {
14167
+ return String(s).replace(/^\s+|\s+$/g, "");
14168
+ }
14169
+
14170
+ function getAttr(node, name, fallback) {
14171
+ var v;
14172
+ if (fallback == null) fallback = null;
14173
+ if (!node) return fallback;
14174
+ v = node.getAttribute(name);
14175
+ return v != null ? v : fallback;
14176
+ }
14177
+
14178
+ function parseStyle(styleText) {
14179
+ var data = {};
14180
+ var parts;
14181
+ var i;
14182
+ var bit;
14183
+ var key;
14184
+ var value;
14185
+
14186
+ if (!styleText) return data;
14187
+ parts = styleText.split(";");
14188
+
14189
+ for (i = 0; i < parts.length; i++) {
14190
+ bit = parts[i].split(":");
14191
+ if (bit.length < 2) continue;
14192
+ key = trim(bit[0]);
14193
+ value = trim(bit.slice(1).join(":"));
14194
+ data[key] = value;
14195
+ }
14196
+
14197
+ return data;
14198
+ }
14199
+
14200
+ function parseOffset(v) {
14201
+ var s;
14202
+ if (v == null || v === "") return 0;
14203
+ s = trim(v);
14204
+ if (s.charAt(s.length - 1) === "%") return Math.max(0, Math.min(1, num(s) / 100));
14205
+ return Math.max(0, Math.min(1, num(s)));
14206
+ }
14207
+
14208
+ function applyOpacityToColor(color, opacity) {
14209
+ var hex, short, full, r, g, b;
14210
+
14211
+ if (opacity >= 1) return color;
14212
+ hex = trim(color);
14213
+
14214
+ if (/^#([0-9a-f]{3})$/i.test(hex)) {
14215
+ short = hex.slice(1);
14216
+ r = parseInt(short.charAt(0) + short.charAt(0), 16);
14217
+ g = parseInt(short.charAt(1) + short.charAt(1), 16);
14218
+ b = parseInt(short.charAt(2) + short.charAt(2), 16);
14219
+ return "rgba(" + r + "," + g + "," + b + "," + opacity + ")";
14220
+ }
14221
+
14222
+ if (/^#([0-9a-f]{6})$/i.test(hex)) {
14223
+ full = hex.slice(1);
14224
+ r = parseInt(full.slice(0, 2), 16);
14225
+ g = parseInt(full.slice(2, 4), 16);
14226
+ b = parseInt(full.slice(4, 6), 16);
14227
+ return "rgba(" + r + "," + g + "," + b + "," + opacity + ")";
14228
+ }
14229
+
14230
+ return color;
14231
+ }
14232
+
14233
+ function parseStop(stopNode) {
14234
+ var style = parseStyle(getAttr(stopNode, "style", ""));
14235
+ var color = getAttr(stopNode, "stop-color", null) || style["stop-color"] || "#000000";
14236
+ var stopOpacity = getAttr(stopNode, "stop-opacity", null);
14237
+ var opacity;
14238
+ var offset;
14239
+
14240
+ if (stopOpacity == null && style["stop-opacity"] != null) stopOpacity = style["stop-opacity"];
14241
+ if (stopOpacity == null) stopOpacity = 1;
14242
+
14243
+ opacity = Math.max(0, Math.min(1, num(stopOpacity, 1)));
14244
+ offset = parseOffset(getAttr(stopNode, "offset", 0));
14245
+
14246
+ return {
14247
+ color: applyOpacityToColor(color, opacity),
14248
+ offset: offset
14249
+ };
14250
+ }
14251
+
14252
+ function resolveHref(node) {
14253
+ return getAttr(node, "href", null) || getAttr(node, "xlink:href", null) || null;
14254
+ }
14255
+
14256
+ function resolveLinkedGradient(node) {
14257
+ var href;
14258
+ if (!node || !node.ownerDocument) return null;
14259
+ href = resolveHref(node);
14260
+ if (!href || href.charAt(0) !== "#") return null;
14261
+ return node.ownerDocument.getElementById(href.slice(1));
14262
+ }
14263
+
14264
+ function inheritedAttr(node, name, fallback, seen) {
14265
+ var value;
14266
+ var linked;
14267
+
14268
+ if (fallback == null) fallback = null;
14269
+ if (!seen) seen = [];
14270
+ if (!node || seen.indexOf(node) !== -1) return fallback;
14271
+ seen.push(node);
14272
+
14273
+ value = getAttr(node, name, null);
14274
+ if (value != null) return value;
14275
+
14276
+ linked = resolveLinkedGradient(node);
14277
+ if (linked) return inheritedAttr(linked, name, fallback, seen);
14278
+
14279
+ return fallback;
14280
+ }
14281
+
14282
+ function collectStops(node, seen) {
14283
+ var linked;
14284
+ var inheritedStops;
14285
+ var ownStops = [];
14286
+ var children;
14287
+ var i;
14288
+ var child;
14289
+
14290
+ if (!seen) seen = [];
14291
+ if (!node || seen.indexOf(node) !== -1) return [];
14292
+ seen.push(node);
14293
+
14294
+ linked = resolveLinkedGradient(node);
14295
+ inheritedStops = linked ? collectStops(linked, seen) : [];
14296
+
14297
+ children = node.children || [];
14298
+ for (i = 0; i < children.length; i++) {
14299
+ child = children[i];
14300
+ if (child.tagName && child.tagName.toLowerCase() === "stop") {
14301
+ ownStops.push(parseStop(child));
14302
+ }
14303
+ }
14304
+
14305
+ return ownStops.length ? ownStops : inheritedStops;
14306
+ }
14307
+
14308
+ function coordX(v, units) {
14309
+ var s = trim(v);
14310
+ if (s.charAt(s.length - 1) === "%") return width * num(s) / 100 - width / 2;
14311
+ if (units === "objectBoundingBox") return width * num(s) - width / 2;
14312
+ return num(s) - box.x - width / 2;
14313
+ }
14314
+
14315
+ function coordY(v, units) {
14316
+ var s = trim(v);
14317
+ if (s.charAt(s.length - 1) === "%") return height * num(s) / 100 - height / 2;
14318
+ if (units === "objectBoundingBox") return height * num(s) - height / 2;
14319
+ return num(s) - box.y - height / 2;
14320
+ }
14321
+
14322
+ function radius(v, units) {
14323
+ var s = trim(v);
14324
+ var base = Math.min(width, height);
14325
+ if (s.charAt(s.length - 1) === "%") return base * num(s) / 100;
14326
+ if (units === "objectBoundingBox") return base * num(s);
14327
+ return num(s);
14328
+ }
14329
+
14330
+ function applyMatrix(x, y, matrixString) {
14331
+ var m;
14332
+ var vals;
14333
+
14334
+ if (!matrixString) return {x:x, y:y};
14335
+
14336
+ m = trim(matrixString).match(/^matrix\(([^)]+)\)$/i);
14337
+ if (!m) return {x:x, y:y};
14338
+
14339
+ vals = m[1].split(/[\s,]+/);
14340
+ if (vals.length < 6) return {x:x, y:y};
14341
+
14342
+ return {
14343
+ x: num(vals[0], 1) * x + num(vals[2], 0) * y + num(vals[4], 0),
14344
+ y: num(vals[1], 0) * x + num(vals[3], 1) * y + num(vals[5], 0)
14345
+ };
14346
+ }
14347
+
14348
+ var stops = collectStops(gradientNode);
14349
+ var colors = [];
14350
+ var ratios = [];
14351
+ var units = inheritedAttr(gradientNode, "gradientUnits", "objectBoundingBox");
14352
+ var transform = inheritedAttr(gradientNode, "gradientTransform", null);
14353
+ var i;
14354
+ var p0;
14355
+ var p1;
14356
+ var x0;
14357
+ var y0;
14358
+ var x1;
14359
+ var y1;
14360
+ var r0;
14361
+ var r1;
14362
+
14363
+ for (i = 0; i < stops.length; i++) {
14364
+ colors.push(stops[i].color);
14365
+ ratios.push(stops[i].offset);
14366
+ }
14367
+
14368
+ if (type === "lineargradient") {
14369
+ x0 = coordX(inheritedAttr(gradientNode, "x1", units === "objectBoundingBox" ? "0%" : "0"), units);
14370
+ y0 = coordY(inheritedAttr(gradientNode, "y1", units === "objectBoundingBox" ? "0%" : "0"), units);
14371
+ x1 = coordX(inheritedAttr(gradientNode, "x2", units === "objectBoundingBox" ? "100%" : "100"), units);
14372
+ y1 = coordY(inheritedAttr(gradientNode, "y2", units === "objectBoundingBox" ? "0%" : "0"), units);
14373
+
14374
+ p0 = applyMatrix(x0, y0, transform);
14375
+ p1 = applyMatrix(x1, y1, transform);
14376
+
14377
+ return [0, [colors, ratios, p0.x, p0.y, p1.x, p1.y]];
14378
+ }
14379
+
14380
+ x0 = coordX(inheritedAttr(gradientNode, "fx", inheritedAttr(gradientNode, "cx", units === "objectBoundingBox" ? "50%" : "0")), units);
14381
+ y0 = coordY(inheritedAttr(gradientNode, "fy", inheritedAttr(gradientNode, "cy", units === "objectBoundingBox" ? "50%" : "0")), units);
14382
+ x1 = coordX(inheritedAttr(gradientNode, "cx", units === "objectBoundingBox" ? "50%" : "0"), units);
14383
+ y1 = coordY(inheritedAttr(gradientNode, "cy", units === "objectBoundingBox" ? "50%" : "0"), units);
14384
+ r0 = 0;
14385
+ r1 = radius(inheritedAttr(gradientNode, "r", units === "objectBoundingBox" ? "50%" : "0"), units);
14386
+
14387
+ p0 = applyMatrix(x0, y0, transform);
14388
+ p1 = applyMatrix(x1, y1, transform);
14389
+
14390
+ return [1, [colors, ratios, p0.x, p0.y, r0, p1.x, p1.y, r1]];
14391
+ }
14392
+
14393
+ function parseGradients(f, tag) {
14394
+ var match;
14395
+ var id;
14396
+ var gradientTag;
14397
+ var data;
14398
+ var p;
14399
+
14400
+ if (f == null) return f;
14401
+ f = String(f).replace(/^\s+|\s+$/g, "");
14402
+
14403
+ if (!/^url\(/i.test(f)) return f;
14404
+
14405
+ match = f.match(/^url\(\s*#([^)]+)\s*\)$/i);
14406
+ if (!match) return f;
14407
+
14408
+ id = match[1];
14409
+ if (!svg || !svg.querySelector) return f;
14410
+
14411
+ gradientTag = svg.querySelector("#" + id);
14412
+ if (!gradientTag) return f;
14413
+
14414
+ data = svgGradientToArray(gradientTag, tag);
14415
+ if (!data) return f;
14416
+
14417
+ p = data[1];
14418
+
14419
+ if (data[0] === 1) {
14420
+ return new RadialColor(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
14421
+ }
14422
+
14423
+ return new GradientColor(p[0], p[1], p[2], p[3], p[4], p[5]);
14424
+ }
14425
+
14058
14426
 
14059
14427
 
14060
14428
  if (style!==false) zim.styleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
@@ -14337,7 +14705,7 @@ zim.extend(zim.Tag, zim.Container, ["clone", "dispose"], "zimContainer", false);
14337
14705
  // SUBSECTION SHADERS
14338
14706
 
14339
14707
  /*--
14340
- zim.Shader = function(width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, style, group, inherit)
14708
+ zim.Shader = function(width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, channels, dynamics, style, group, inherit)
14341
14709
 
14342
14710
  Shader
14343
14711
  zim class - extends a zim.Bitmap which extends a createjs.Bitmap
@@ -14348,6 +14716,9 @@ Shaders run on the GPU and are very fast for cool visual effects and are also th
14348
14716
  For 3D, we recommend using three.js with ZIM and the the Three helper module - overlayed or with TextureActive.
14349
14717
  BUT - shaders are also commonly used for amazing 2D effects.
14350
14718
 
14719
+ As of ZIM 020 - there are now 16 channels supported in one Shader instance
14720
+ see just past the numbered channels and dynamics to the channels and dynamics parameters that accept arrays
14721
+
14351
14722
  Also see ShaderOverlay() that overlays the raw WebGL Canvas on ZIM as a Tag() rather than converting to a Bitmap.
14352
14723
 
14353
14724
  The best way to see what shaders are about are to look at the many examples on ShaderToy, for instance:
@@ -14789,6 +15160,13 @@ channel0, channel1, channel2, channel3 - (default null) pass in a ZIM DisplayObj
14789
15160
  see the dynamic parameters below to set if this is a dynamic channel, default is true
14790
15161
  dynamic0, dynamic1, dynamic2, dynamic3 - (default true / false for Pic) if a channel is used, set its matching dynamic parameter to false
14791
15162
  if the channel does not change - for example a Container where nothing is moving.
15163
+ channels - (default null) an Array of up to 16 ZIM DisplayObjects (Container, Pic, Vid, Shader, etc.)
15164
+ used for iChannel0 through iChannel15 in the shader.
15165
+ Alternatively, channel0, channel1, channel2, etc. can be passed individually.
15166
+ Objects are cached and GPU textures are bound and updated automatically.
15167
+ dynamics - (default null) an Array of Booleans matching the channels Array.
15168
+ Set an index to false if that channel does not change (e.g. a static Container or Pic).
15169
+ Defaults to true (or false for Pic). Alternatively, dynamic0, dynamic1, etc. can be passed individually.
14792
15170
  style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
14793
15171
  group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
14794
15172
  inherit - (default null) used internally but can receive an {} of styles directly
@@ -14836,13 +15214,13 @@ EVENTS
14836
15214
  See the CreateJS Easel Docs for Bitmap events such as:
14837
15215
  added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
14838
15216
  --*///+50.96
14839
- zim.Shader = function(width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, style, group, inherit) {
14840
- var sig = "width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, style, group, inherit";
15217
+ zim.Shader = function(width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, channels, dynamics, style, group, inherit) {
15218
+ var sig = "width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, channels, dynamics, style, group, inherit";
14841
15219
  var duo; if (duo = zob(zim.Shader, arguments, sig, this)) return duo;
14842
- z_d("50.96");
15220
+ z_d("50.970");
14843
15221
  this.group = group;
14844
15222
  var DS = style===false?group!=null?zim.getStyle(null,null,inherit,this.group):{}:zim.getStyle("Shader", this.group, inherit);
14845
- var s = makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, this);
15223
+ var s = makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, channels, dynamics, this);
14846
15224
 
14847
15225
  this.zimBitmap_constructor(s.canvas);
14848
15226
  this.type = "Shader";
@@ -14850,7 +15228,7 @@ zim.Shader = function(width, height, fragment, uniforms, vertex, dynamic, preCal
14850
15228
  // MONITOR
14851
15229
  var mID = this.mID = "z~"+(DS.monitor===false?"-":this.type);
14852
15230
 
14853
- this.uniforms = s.uniforms; // now a Uniforms object - use uniforms.obj to see original
15231
+ this.uniforms = s.uniforms;
14854
15232
  this.canvas = s.canvas;
14855
15233
  this.gl = s.gl;
14856
15234
  this.setUniform = s.setUniform;
@@ -14878,47 +15256,27 @@ zim.Shader = function(width, height, fragment, uniforms, vertex, dynamic, preCal
14878
15256
  }
14879
15257
  });
14880
15258
 
14881
- // var gl = canvas.getContext('webgl2');
14882
- // that.updateChannel = function(index, obj) {
14883
-
14884
- // if (zot(index)) index = 0;
14885
- // if (!that.channels[i]) return that;
14886
- // var channel = that.channels[i];
14887
-
14888
- // channel.dynamic = that["dynamic" + i];
14889
- // if (channel.type && channel.type=="Pic") channel.dynamic = false;
14890
- // if (channel.cache) {
14891
- // if (!channel.cacheCanvas) channel.cache();
14892
- // channel.texture = createTexture(channel.cacheCanvas);
14893
- // } else {
14894
- // channel.texture = createTexture(channel);
14895
- // }
14896
- // gl.uniform1i(gl.getUniformLocation(program, 'iChannel' + i), i);
14897
- // }
14898
-
14899
15259
  if (style!==false) zim.styleTransforms(this, DS);
14900
15260
 
14901
15261
  this.clone = function() {
14902
- return that.cloneProps(new zim.Shader(width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, style, this.group, inherit));
15262
+ return that.cloneProps(new zim.Shader(width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, channels, dynamics, style, this.group, inherit));
14903
15263
  };
14904
15264
 
14905
15265
  this.dispose = function(temp, b, disposing) {
14906
15266
  if (this.ticker) zim.Ticker.remove(this.ticker, mID, that);
14907
- // if (this.uniforms) this.uniforms.dispose();
14908
15267
  this.canvas = null;
14909
15268
  this.gl = null;
14910
15269
  this.program = null;
14911
15270
  this.ticker = null;
14912
15271
  if (!disposing) this.zimBitmap_dispose(true);
14913
15272
  return true;
14914
- }
14915
-
14916
- }
15273
+ };
15274
+ };
14917
15275
  zim.extend(zim.Shader, zim.Bitmap, ["clone", "dispose"], "zimBitmap", false);
14918
15276
  //-50.96
14919
15277
 
14920
15278
  /*--
14921
- zim.ShaderOverlay = function(width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, style, group, inherit)
15279
+ zim.ShaderOverlay = function(width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, channels, dynamics, style, group, inherit)
14922
15280
 
14923
15281
  ShaderOverlay
14924
15282
  zim class - extends a zim.Tag
@@ -14963,13 +15321,13 @@ function ready() {
14963
15321
  END EXAMPLE
14964
15322
 
14965
15323
  --*///+50.962
14966
- zim.ShaderOverlay = function(width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, style, group, inherit) {
14967
- var sig = "width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, style, group, inherit";
15324
+ zim.ShaderOverlay = function(width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, channels, dynamics, style, group, inherit) {
15325
+ var sig = "width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, channels, dynamics, style, group, inherit";
14968
15326
  var duo; if (duo = zob(zim.ShaderOverlay, arguments, sig, this)) return duo;
14969
- z_d("50.962");
15327
+ z_d("50.970");
14970
15328
  this.group = group;
14971
15329
  var DS = style===false?group!=null?zim.getStyle(null,null,inherit,this.group):{}:zim.getStyle("ShaderOverlay", this.group, inherit);
14972
- var s = makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, this);
15330
+ var s = makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, channels, dynamics, this);
14973
15331
 
14974
15332
  this.zimTag_constructor(width, height);
14975
15333
  this.type = "ShaderOverlay";
@@ -14977,7 +15335,7 @@ zim.ShaderOverlay = function(width, height, fragment, uniforms, vertex, dynamic,
14977
15335
  // MONITOR
14978
15336
  var mID = this.mID = "z~"+(DS.monitor===false?"-":this.type);
14979
15337
 
14980
- this.uniforms = s.uniforms; // now a Uniforms object - use uniforms.obj to see original
15338
+ this.uniforms = s.uniforms;
14981
15339
  this.canvas = s.canvas;
14982
15340
  this.gl = s.gl;
14983
15341
  this.setUniform = s.setUniform;
@@ -15002,7 +15360,7 @@ zim.ShaderOverlay = function(width, height, fragment, uniforms, vertex, dynamic,
15002
15360
  if (value) {
15003
15361
  zim.Ticker.add(this.ticker, null, mID, that);
15004
15362
  } else {
15005
- if (this.ticker) zim.Ticker.remove(this.ticker, mID, that, that);
15363
+ if (this.ticker) zim.Ticker.remove(this.ticker, mID, that);
15006
15364
  }
15007
15365
  _dynamic = value?true:false;
15008
15366
  }
@@ -15011,7 +15369,7 @@ zim.ShaderOverlay = function(width, height, fragment, uniforms, vertex, dynamic,
15011
15369
  if (style!==false) zim.styleTransforms(this, DS);
15012
15370
 
15013
15371
  this.clone = function() {
15014
- return that.cloneProps(new zim.Shader(width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, style, this.group, inherit));
15372
+ return that.cloneProps(new zim.ShaderOverlay(width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, channels, dynamics, style, this.group, inherit));
15015
15373
  };
15016
15374
 
15017
15375
  this.dispose = function(temp, b, disposing) {
@@ -15023,14 +15381,13 @@ zim.ShaderOverlay = function(width, height, fragment, uniforms, vertex, dynamic,
15023
15381
  this.ticker = null;
15024
15382
  if (!disposing) this.zimTag_dispose(true);
15025
15383
  return true;
15026
- }
15027
-
15028
- }
15384
+ };
15385
+ };
15029
15386
  zim.extend(zim.ShaderOverlay, zim.Tag, ["clone", "dispose"], "zimTag", false);
15030
15387
  //-50.962
15031
15388
 
15032
15389
  /*--
15033
- makeShader = function(DS, width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, tether)
15390
+ makeShader = function(DS, width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, channels, dynamics, tether)
15034
15391
 
15035
15392
  makeShader
15036
15393
  function - used internally only
@@ -15048,13 +15405,13 @@ primarily to match default uniforms at ShaderToy https://www.shadertoy.com/
15048
15405
  Introduced in ZIM 016
15049
15406
 
15050
15407
  --*///+50.964
15051
- function makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, tether) {
15052
- z_d("50.964");
15408
+ function makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preCall, postCall, rate, version, canvas, vertexPosition, strip, log, channel0, channel1, channel2, channel3, dynamic0, dynamic1, dynamic2, dynamic3, channels, dynamics, tether) {
15409
+ z_d("50.970");
15053
15410
 
15054
15411
  var mID = "z~Shader";
15055
15412
 
15056
15413
  if (zot(width)) width = DS.width!=null?DS.width:500;
15057
- if (zot(height)) height = DS.radius!=null?DS.height:500;
15414
+ if (zot(height)) height = DS.height!=null?DS.height:500;
15058
15415
  if (zot(rate)) rate = DS.rate!=null?DS.rate:1;
15059
15416
  if (zot(version)) version = DS.version!=null?DS.version:"#version 300 es";
15060
15417
  var defaultV;
@@ -15073,46 +15430,108 @@ function makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preC
15073
15430
  if (zot(vertexPosition)) vertexPosition = DS.vertexPosition!=null?DS.vertexPosition:"vertexPosition";
15074
15431
  if (zot(strip)) strip = DS.strip!=null?DS.strip:true;
15075
15432
  if (zot(log)) log = DS.log!=null?DS.log:null;
15076
- if (zot(channel0)) channel0 = DS.channel0!=null?DS.channel0:null;
15077
- if (zot(channel1)) channel1 = DS.channel1!=null?DS.channel1:null;
15078
- if (zot(channel2)) channel2 = DS.channel2!=null?DS.channel2:null;
15079
- if (zot(channel3)) channel3 = DS.channel3!=null?DS.channel3:null;
15080
- if (zot(dynamic0)) dynamic0 = DS.dynamic0!=null?DS.dynamic0:true;
15081
- if (zot(dynamic1)) dynamic1 = DS.dynamic1!=null?DS.dynamic1:true;
15082
- if (zot(dynamic2)) dynamic2 = DS.dynamic2!=null?DS.dynamic2:true;
15083
- if (zot(dynamic3)) dynamic3 = DS.dynamic3!=null?DS.dynamic3:true;
15084
-
15085
15433
 
15086
15434
  if (zot(canvas)) {
15087
15435
  canvas = document.createElement("canvas");
15088
15436
  canvas.setAttribute("width", width);
15089
15437
  canvas.setAttribute("height", height);
15090
- canvas.setAttribute("id", "shaderCanvas");
15438
+ canvas.setAttribute("id", "shaderCanvas_" + zim.makeID());
15091
15439
  }
15092
15440
 
15093
- function createTexture(source) {
15441
+ function getSource(channel) {
15442
+ if (!channel) return null;
15443
+ if (channel.tagName === "VIDEO" || channel.tagName === "IMG" || channel.tagName === "CANVAS") return channel;
15444
+ if (channel.source && (channel.source.tagName === "VIDEO" || channel.source.tagName === "IMG")) return channel.source;
15445
+ if (channel.video && channel.video.tagName === "VIDEO") return channel.video;
15446
+ if (channel.tag && (channel.tag.tagName === "VIDEO" || channel.tag.tagName === "IMG" || channel.tag.tagName === "CANVAS")) return channel.tag;
15447
+ if (channel.bitmap && channel.bitmap.image) return channel.bitmap.image;
15448
+ if (channel.image) return channel.image;
15449
+ if (channel.cacheCanvas) return channel.cacheCanvas;
15450
+ return channel;
15451
+ }
15452
+
15453
+ function isVideo(source, channel) {
15454
+ if (source && source.tagName === "VIDEO") return true;
15455
+ if (channel && channel.type === "Vid") return true;
15456
+ return false;
15457
+ }
15458
+
15459
+ var gl = canvas.getContext('webgl2');
15460
+ gl.enable(gl.CULL_FACE);
15461
+ gl.cullFace(gl.BACK);
15462
+ gl.frontFace(gl.CCW);
15463
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
15464
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
15465
+
15466
+ function createTexture(source, unit) {
15467
+ if (zot(unit)) unit = 0;
15468
+ gl.activeTexture(gl["TEXTURE" + unit]);
15094
15469
  var tex = gl.createTexture();
15095
15470
  gl.bindTexture(gl.TEXTURE_2D, tex);
15096
15471
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
15097
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
15472
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
15473
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
15098
15474
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
15099
15475
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
15476
+ if (source && (source.readyState == null || source.readyState >= 2)) {
15477
+ try {
15478
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
15479
+ } catch(e) {
15480
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
15481
+ }
15482
+ } else {
15483
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
15484
+ }
15100
15485
  return tex;
15101
15486
  }
15102
15487
 
15103
- var channels = [channel0, channel1, channel2, channel3];
15104
- var dynamics = [dynamic0, dynamic1, dynamic2, dynamic3];
15488
+ // Build 16-Channel list from array or individual parameters
15489
+ var channelList = new Array(16).fill(null);
15490
+ var dynamicList = new Array(16).fill(true);
15491
+
15492
+ if (channels && Array.isArray(channels)) {
15493
+ for (var k = 0; k < Math.min(channels.length, 16); k++) channelList[k] = channels[k];
15494
+ } else if (DS.channels && Array.isArray(DS.channels)) {
15495
+ for (var k = 0; k < Math.min(DS.channels.length, 16); k++) channelList[k] = DS.channels[k];
15496
+ } else {
15497
+ channelList[0] = channel0 != null ? channel0 : DS.channel0;
15498
+ channelList[1] = channel1 != null ? channel1 : DS.channel1;
15499
+ channelList[2] = channel2 != null ? channel2 : DS.channel2;
15500
+ channelList[3] = channel3 != null ? channel3 : DS.channel3;
15501
+ for (var k = 4; k < 16; k++) {
15502
+ if (DS["channel" + k] != null) channelList[k] = DS["channel" + k];
15503
+ }
15504
+ }
15505
+
15506
+ if (dynamics && Array.isArray(dynamics)) {
15507
+ for (var k = 0; k < Math.min(dynamics.length, 16); k++) dynamicList[k] = dynamics[k];
15508
+ } else if (DS.dynamics && Array.isArray(DS.dynamics)) {
15509
+ for (var k = 0; k < Math.min(DS.dynamics.length, 16); k++) dynamicList[k] = DS.dynamics[k];
15510
+ } else {
15511
+ dynamicList[0] = dynamic0 != null ? dynamic0 : (DS.dynamic0 != null ? DS.dynamic0 : true);
15512
+ dynamicList[1] = dynamic1 != null ? dynamic1 : (DS.dynamic1 != null ? DS.dynamic1 : true);
15513
+ dynamicList[2] = dynamic2 != null ? dynamic2 : (DS.dynamic2 != null ? DS.dynamic2 : true);
15514
+ dynamicList[3] = dynamic3 != null ? dynamic3 : (DS.dynamic3 != null ? DS.dynamic3 : true);
15515
+ for (var k = 4; k < 16; k++) {
15516
+ if (DS["dynamic" + k] != null) dynamicList[k] = DS["dynamic" + k];
15517
+ }
15518
+ }
15519
+
15105
15520
  var channelOutput = "";
15106
- zim.loop(channels, function(channel, i) {
15107
- if (channel) channelOutput+="uniform sampler2D iChannel"+i+";\n";
15108
- });
15521
+ for (var i = 0; i < 16; i++) {
15522
+ if (channelList[i] || fragment.indexOf("iChannel" + i) !== -1) {
15523
+ var reg = new RegExp("uniform\\s+sampler2D\\s+iChannel" + i + "\\s*;", "g");
15524
+ if (!reg.test(fragment)) {
15525
+ channelOutput += "uniform sampler2D iChannel" + i + ";\n";
15526
+ }
15527
+ }
15528
+ }
15109
15529
 
15110
15530
  fragment = version + "\nprecision mediump float;\n\n// ZIM Default Uniforms\nuniform vec3 iResolution;\nuniform float iTime;\nuniform float iTimeDelta;\nuniform float iFrameRate;\nuniform float iFrame;\nuniform vec4 iMouse;\nuniform vec4 iDate;\nuniform float iChange;\n" + channelOutput + fragment;
15111
15531
  vertex = version + "\nprecision mediump float;\n\n// ZIM Default Uniforms\nprecision mediump float;\nuniform vec3 iResolution;\nuniform float iTime;\nuniform float iTimeDelta;\nuniform float iFrameRate;\nuniform float iFrame;\nuniform vec4 iMouse;\nuniform vec4 iDate;\nuniform float iChange;\n\n" + vertex;
15112
15532
 
15113
- // Replace ShaderToy mainImage
15114
15533
  var matches = fragment.match(/(void |.*)mainImage\(\s*(out\s*vec4\s*([^,]*)),\s*in\s*(vec[234]\s*[^)\s]*)\s*\)/i);
15115
- fragment = fragment.replace(/(void |.*)mainImage\(\s*(out\s*vec4\s*[^,]*),\s*in\s*(vec[234]\s*[^)\s]*)\s*\)/i, "$2;\nvoid main()");
15534
+ fragment = fragment.replace(/(void |.*)mainImage\(\s*(out\s*vec4\s*([^,]*)),\s*in\s*(vec[234]\s*[^)\s]*)\s*\)/i, "$2;\nvoid main()");
15116
15535
  if (matches && matches[4]) {
15117
15536
  var append = "main() {\n\t"+matches[4]+" = gl_FragCoord.xy; // ZIM shadertoy adjust";
15118
15537
  fragment = fragment.replace(/main\(\)\s*{/i, append);
@@ -15124,10 +15543,6 @@ function makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preC
15124
15543
  zogd("FRAGMENT SHADER:\n\n" + fragment);
15125
15544
  }
15126
15545
 
15127
- if (zot(canvas)) {
15128
- canvas = document.createElement("canvas");
15129
- canvas.setAttribute(id, "shaderCanvas_" + zim.makeID());
15130
- }
15131
15546
  if (!zot(uniforms)) {
15132
15547
  if (uniforms.type != "Uniforms") {
15133
15548
  uniforms = new zim.Uniforms(uniforms);
@@ -15138,24 +15553,16 @@ function makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preC
15138
15553
  tether.rate = zik(rate);
15139
15554
  tether.change = 0;
15140
15555
 
15141
- // base code from https://medium.com/@banksysan_10088/webgl-checkerboard-42e15490603c
15142
- var gl = canvas.getContext('webgl2');
15143
- gl.enable(gl.CULL_FACE);
15144
- gl.cullFace(gl.BACK);
15145
- gl.frontFace(gl.CCW);
15146
- gl.clearColor(1.0, 1.0, 1.0, 1.0);
15147
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
15148
-
15149
15556
  var program = createProgram(gl, vertex, fragment);
15150
- if (preCall && typeof preCall=="function") preCall(program, gl, canvas); // ZIM
15557
+ if (preCall && typeof preCall=="function") preCall(program, gl, canvas);
15151
15558
  gl.useProgram(program);
15152
15559
  var vertexData = [];
15153
- if (postCall && typeof postCall=="function") postCall(program, gl, canvas, vertexData); // ZIM
15560
+ if (postCall && typeof postCall=="function") postCall(program, gl, canvas, vertexData);
15154
15561
 
15155
15562
  if (strip) {
15156
- if (vertexData.length == 0) vertexData = [1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0]; // two triangles strips
15563
+ if (vertexData.length == 0) vertexData = [1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0];
15157
15564
  } else {
15158
- if (vertexData.length == 0) vertexData = [-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0]; // two triangles
15565
+ if (vertexData.length == 0) vertexData = [-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0];
15159
15566
  }
15160
15567
  var vertexBuffer = gl.createBuffer();
15161
15568
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
@@ -15164,79 +15571,113 @@ function makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preC
15164
15571
  gl.vertexAttribPointer(vertexAttributeLocation, 2, gl.FLOAT, false, 2 * Float32Array.BYTES_PER_ELEMENT, 0);
15165
15572
  gl.enableVertexAttribArray(vertexAttributeLocation);
15166
15573
 
15167
- // ZIM
15574
+ function initChannel(channel, i) {
15575
+ if (!channel) return;
15576
+ channel.dynamic = dynamicList[i];
15577
+ var source = getSource(channel);
15578
+ var isV = isVideo(source, channel);
15579
+ var isPic = (channel.type && channel.type=="Pic") || (source && source.tagName=="IMG");
15580
+ if (isPic) channel.dynamic = false;
15168
15581
 
15169
- zim.loop(channels, function(channel, i) {
15170
- if (channel) {
15171
- channel.dynamic = dynamics[i];
15172
- if (channel.type && channel.type=="Pic") channel.dynamic = false;
15173
- if (channel.cache) {
15174
- if (!channel.cacheCanvas) channel.cache();
15175
- channel.texture = createTexture(channel.cacheCanvas);
15176
- } else {
15177
- channel.texture = createTexture(channel);
15178
- }
15179
- gl.uniform1i(gl.getUniformLocation(program, 'iChannel' + i), i);
15582
+ if (!isV && !isPic && channel.cache && !channel.cacheCanvas) {
15583
+ channel.cache();
15584
+ source = channel.cacheCanvas;
15180
15585
  }
15181
- });
15182
15586
 
15183
- function replaceChannel(obj, i, dynamic) {
15184
- if (zot(dynamic)) dynamic = true;
15185
- channels[i] = obj;
15186
- var channel = obj;
15187
- channel.dynamic = dynamic;
15188
- if (channel.type && channel.type=="Pic") channel.dynamic = false;
15189
- dynamics[i] = channel.dynamic;
15190
- if (channel.cache) {
15191
- if (!channel.cacheCanvas) channel.cache();
15192
- channel.texture = createTexture(channel.cacheCanvas);
15193
- } else {
15194
- channel.texture = createTexture(channel);
15587
+ if (isV && source && source.requestVideoFrameCallback) {
15588
+ channel._hasNewFrame = true;
15589
+ var rVFC = function() {
15590
+ channel._hasNewFrame = true;
15591
+ if (source && source.requestVideoFrameCallback && !tether.disposed) {
15592
+ source.requestVideoFrameCallback(rVFC);
15593
+ }
15594
+ };
15595
+ source.requestVideoFrameCallback(rVFC);
15195
15596
  }
15597
+
15598
+ channel.texture = createTexture(source, i);
15599
+ gl.activeTexture(gl["TEXTURE" + i]);
15600
+ gl.bindTexture(gl.TEXTURE_2D, channel.texture);
15196
15601
  gl.uniform1i(gl.getUniformLocation(program, 'iChannel' + i), i);
15197
15602
  }
15198
15603
 
15604
+ for (var i = 0; i < 16; i++) {
15605
+ if (channelList[i]) {
15606
+ initChannel(channelList[i], i);
15607
+ } else if (fragment.indexOf("iChannel" + i) !== -1) {
15608
+ var blankTex = createTexture(null, i);
15609
+ gl.activeTexture(gl["TEXTURE" + i]);
15610
+ gl.bindTexture(gl.TEXTURE_2D, blankTex);
15611
+ gl.uniform1i(gl.getUniformLocation(program, 'iChannel' + i), i);
15612
+ }
15613
+ }
15614
+
15615
+ function replaceChannel(obj, i, dyn) {
15616
+ if (zot(i)) i = 0;
15617
+ if (zot(dyn)) dyn = true;
15618
+ channelList[i] = obj;
15619
+ dynamicList[i] = dyn;
15620
+ initChannel(obj, i);
15621
+ }
15622
+
15199
15623
  function setUniform(type, name, v1, v2, v3, v4) {
15200
15624
  if (zot(type)) type = "1f";
15201
15625
  if (zot(name)) {zogf("uniform - must have name"); return;}
15202
15626
  gl["uniform"+type](gl.getUniformLocation(program, name), v1, v2, v3, v4);
15203
15627
  }
15628
+
15204
15629
  var frameNum = 0;
15205
15630
  function update(e) {
15206
-
15207
- // process uniforms
15208
15631
  if (!zot(uniforms)) {
15209
- uniforms.update(); // takes from properties and updates obj
15632
+ uniforms.update();
15210
15633
  zim.loop(uniforms.obj, function(name,val) {
15211
15634
  var n = 1;
15212
15635
  if (Array.isArray(val)) n = val.length;
15213
15636
  else val = [val];
15214
- // if (name=="time") zog(val[0])
15215
15637
  setUniform(n+"f", name, val[0], val[1], val[2], val[3]);
15216
15638
  });
15217
15639
  }
15218
15640
 
15219
- // process channels
15220
- for (var i=0; i<4; i++) {
15221
- var channel = channels[i];
15222
- if (channel) {
15641
+ // Process up to 16 texture units
15642
+ for (var i = 0; i < 16; i++) {
15643
+ var channel = channelList[i];
15644
+ if (channel && channel.texture) {
15223
15645
  gl.activeTexture(gl["TEXTURE"+i]);
15224
15646
  gl.bindTexture(gl.TEXTURE_2D, channel.texture);
15225
15647
  if (channel.dynamic) {
15226
- if (channel.cacheCanvas) channel.updateCache();
15227
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, channel.cacheCanvas?channel.cacheCanvas:channel);
15648
+ var source = getSource(channel);
15649
+ var isV = isVideo(source, channel);
15650
+ var shouldUpload = false;
15651
+
15652
+ if (isV) {
15653
+ if (source && source.readyState >= 2 && !source.paused && !source.ended) {
15654
+ if (source.requestVideoFrameCallback) {
15655
+ shouldUpload = channel._hasNewFrame;
15656
+ channel._hasNewFrame = false;
15657
+ } else {
15658
+ shouldUpload = true;
15659
+ }
15660
+ }
15661
+ } else if (channel.cacheCanvas) {
15662
+ channel.updateCache();
15663
+ source = channel.cacheCanvas;
15664
+ shouldUpload = true;
15665
+ }
15666
+
15667
+ if (shouldUpload && source) {
15668
+ try {
15669
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
15670
+ } catch(err) {}
15671
+ }
15228
15672
  }
15229
15673
  }
15230
15674
  }
15231
-
15232
15675
 
15233
- // DEFAULT UNIFORMS
15234
15676
  var date = new Date();
15235
15677
  setUniform("3f", "iResolution", width, height);
15236
15678
  var time = zim.decimals(date.getHours()*60*60+date.getMinutes()*60+date.getSeconds()+date.getMilliseconds()/1000, 4);
15237
15679
  setUniform("4f", "iDate", date.getFullYear(), date.getMonth(), time);
15238
15680
  setUniform("1f", "iTime", e?zim.decimals(e.runTime/1000, 4):0);
15239
- setUniform("1f", "iChange", tether.rate);
15240
15681
  setUniform("1f", "iChange", tether.change+=tether.rate/60);
15241
15682
  setUniform("1f", "iTimeDelta", e?zim.decimals(e.delta/1000, 4):0);
15242
15683
  setUniform("1f", "iFrame", e?frameNum++:0);
@@ -15248,8 +15689,8 @@ function makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preC
15248
15689
  }
15249
15690
  if (strip) gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
15250
15691
  else gl.drawArrays(gl.TRIANGLES, 0, vertexData.length);
15251
-
15252
15692
  }
15693
+
15253
15694
  var downCheck = false;
15254
15695
  var clickCheck = false;
15255
15696
  setTimeout(function() {
@@ -15257,6 +15698,7 @@ function makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preC
15257
15698
  tether.on("pressup", function() {downCheck = false;}, null, null, null, null, mID);
15258
15699
  tether.tap({call:function() {clickCheck = true;}, cursor:false});
15259
15700
  }, 50);
15701
+
15260
15702
  update();
15261
15703
  var ticker = zim.Ticker.add(update, null, mID, tether);
15262
15704
  if (!dynamic) {
@@ -15264,81 +15706,66 @@ function makeShader(DS, width, height, fragment, uniforms, vertex, dynamic, preC
15264
15706
  setTimeout(update, 50);
15265
15707
  if (tether.stage) tether.stage.update();
15266
15708
  }
15267
- return {dynamic:dynamic, fragment:fragment, vertex:vertex, program:program, uniforms:uniforms, gl:gl, canvas:canvas, update:update, setUniform:setUniform, ticker:ticker, replaceChannel:replaceChannel};
15268
15709
 
15269
- // private
15710
+ return {
15711
+ dynamic: dynamic,
15712
+ fragment: fragment,
15713
+ vertex: vertex,
15714
+ program: program,
15715
+ uniforms: uniforms,
15716
+ gl: gl,
15717
+ canvas: canvas,
15718
+ update: update,
15719
+ setUniform: setUniform,
15720
+ ticker: ticker,
15721
+ replaceChannel: replaceChannel
15722
+ };
15723
+
15270
15724
  function createProgram(webGlContext, vertexShaderText, fragmentShaderText, verify) {
15271
15725
  if (zot(verify)) verify = true;
15272
- if (!webGlContext) {
15273
- console.error("This browser doesn't support WebGL");
15274
- }
15726
+ if (!webGlContext) console.error("This browser doesn't support WebGL");
15275
15727
 
15276
15728
  webGlContext.clearColor(0.0, 0.0, 0.0, 0.0);
15277
- webGlContext.clear(
15278
- webGlContext.COLOR_BUFFER_BIT | webGlContext.DEPTH_BUFFER_BIT
15279
- );
15729
+ webGlContext.clear(webGlContext.COLOR_BUFFER_BIT | webGlContext.DEPTH_BUFFER_BIT);
15280
15730
 
15281
15731
  var vertexShader = webGlContext.createShader(webGlContext.VERTEX_SHADER);
15282
- var fragmentShader = webGlContext.createShader(
15283
- webGlContext.FRAGMENT_SHADER
15284
- );
15732
+ var fragmentShader = webGlContext.createShader(webGlContext.FRAGMENT_SHADER);
15285
15733
 
15286
15734
  webGlContext.shaderSource(vertexShader, vertexShaderText);
15287
15735
  webGlContext.shaderSource(fragmentShader, fragmentShaderText);
15288
15736
 
15289
15737
  webGlContext.compileShader(vertexShader);
15290
- webGlContext.compileShader(fragmentShader);
15291
-
15292
- var compileStatus = {
15293
- vertexStatus:
15294
- webGlContext.getShaderParameter(
15295
- vertexShader,
15296
- webGlContext.COMPILE_STATUS
15297
- ) || webGlContext.getShaderInfoLog(vertexShader),
15298
- fragmentStatus:
15299
- webGlContext.getShaderParameter(
15300
- fragmentShader,
15301
- webGlContext.COMPILE_STATUS
15302
- ) || webGlContext.getShaderInfoLog(fragmentShader),
15303
- };
15738
+ if (!webGlContext.getShaderParameter(vertexShader, webGlContext.COMPILE_STATUS)) {
15739
+ var vLog = webGlContext.getShaderInfoLog(vertexShader);
15740
+ throw new Error("Vertex Shader Compile Error: " + vLog);
15741
+ }
15304
15742
 
15305
- if (
15306
- compileStatus.vertexStatus !== true ||
15307
- compileStatus.fragmentStatus !== true
15308
- ) {
15309
- throw new Error("Failed to compile. " + JSON.stringify(compileStatus, null, 2));
15743
+ webGlContext.compileShader(fragmentShader);
15744
+ if (!webGlContext.getShaderParameter(fragmentShader, webGlContext.COMPILE_STATUS)) {
15745
+ var fLog = webGlContext.getShaderInfoLog(fragmentShader);
15746
+ throw new Error("Fragment Shader Compile Error: " + fLog);
15310
15747
  }
15311
15748
 
15312
15749
  var program = webGlContext.createProgram();
15313
-
15314
15750
  webGlContext.attachShader(program, vertexShader);
15315
15751
  webGlContext.attachShader(program, fragmentShader);
15316
15752
  webGlContext.linkProgram(program);
15317
15753
 
15318
- var linkingStatus =
15319
- webGlContext.getProgramParameter(program, webGlContext.LINK_STATUS) ||
15320
- webGlContext.getProgramInfoLog(program);
15321
-
15322
- if (linkingStatus !== true) {
15323
- throw new Error("Linking filed:\n" + linkingStatus);
15754
+ if (!webGlContext.getProgramParameter(program, webGlContext.LINK_STATUS)) {
15755
+ var pLog = webGlContext.getProgramInfoLog(program);
15756
+ throw new Error("Shader Program Link Error: " + pLog);
15324
15757
  }
15325
15758
 
15326
15759
  if (verify) {
15327
15760
  webGlContext.validateProgram(program);
15328
- var validationStatus =
15329
- webGlContext.getProgramParameter(
15330
- program,
15331
- webGlContext.VALIDATE_STATUS
15332
- ) || webGlContext.getProgramInfoLog(program);
15333
-
15334
- if (validationStatus !== true) {
15335
- throw new Error("Validation failed.\n" + validationStatus);
15761
+ if (!webGlContext.getProgramParameter(program, webGlContext.VALIDATE_STATUS)) {
15762
+ var valLog = webGlContext.getProgramInfoLog(program);
15763
+ throw new Error("Shader Program Validate Error: " + valLog);
15336
15764
  }
15337
15765
  }
15338
-
15339
15766
  return program;
15340
15767
  }
15341
- } // end makeShader
15768
+ }
15342
15769
  //-50.964
15343
15770
 
15344
15771
  /*--
@@ -18082,6 +18509,7 @@ Note the points property has been split into points and pointObjects (and there
18082
18509
  // points is an array of [[setX, setY, ballX, ballY, handleX, handleY, handle2X, handle2Y, type], etc.]
18083
18510
 
18084
18511
  setInfo = points[i];
18512
+ if (!setInfo) setInfo = [0,0,0,0,0,0,0,0,null];
18085
18513
  type = setInfo[8] ? setInfo[8] : controlType;
18086
18514
  set.loc({x:setInfo[0], y:setInfo[1]});
18087
18515
  ball = new zim.Circle(ballS, that.circleColor, that.circleBorderColor, 2, null, null, null, null, null, false)
@@ -25908,18 +26336,22 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
25908
26336
 
25909
26337
 
25910
26338
  /*--
25911
- zim.Emoji = function(code, size, monochrome, italic, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backing, padding, paddingH, paddingV, shiftH, shiftV, style, group, inherit)
26339
+ zim.Emoji = function(code, size, monochrome, italic, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backing, padding, paddingH, paddingV, shiftH, shiftV, color, borderColor, order, style, group, inherit)
25912
26340
 
25913
26341
  Emoji
25914
- zim class - extends a zim.Label which extends a zim.Container
26342
+ zim class - extends a zim.Container
25915
26343
 
25916
26344
  DESCRIPTION
25917
- Shows an emoji in a Label - an emoji is just text.
25918
- This helps treat the emoji as an image and works in conjunction with ZIM EmojiPicker
26345
+ Shows an emoji. Emojis are usually just text so it will be a Label in the Container.
26346
+ Support has been added in ZIM 020 for Noto Color Emojis - which are then added to the Container as SVG
26347
+ If color or borderColor is provided, the SVG will be an SVGContainer so independent parts can be colored, dragged or animated
25919
26348
 
25920
26349
  SEE: ZIM EmojiPicker() in COMPONENTS below ColorPicker().
25921
26350
 
26351
+ SEE: https://zimjs.com/emoji/ - Emoji Picker Tool with added SVG Editor
25922
26352
  SEE: https://zimjs.com/nft/bubbling/emoji.html
26353
+ SEE: https://zimjs.com/020/noto.html
26354
+
25923
26355
 
25924
26356
  NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
25925
26357
 
@@ -25938,19 +26370,52 @@ new Emoji("\ud83c\udf47", 100) // grapes using UTF codes
25938
26370
  .drag();
25939
26371
  END EXAMPLE
25940
26372
 
26373
+ EXAMPLE
26374
+ // Go to https://emojipedia.org/ and find an emoji page
26375
+ // copy the emoji or use the copy link and paste into the string below
26376
+ // leave the noto_ at the start and paste the emoji icon right after the _
26377
+ // where icon is the actual emoji icon (or a unicode number, or a noto code)
26378
+ // this will create and SVG that is the same across platforms (Windows, Linux, Android, iOS)
26379
+ new Emoji("noto_icon")
26380
+ .center()
26381
+ .drag();
26382
+ // Note - if using with Tile() then preload the emoji in Frame assets of zapp_assets as "noto_icon"
26383
+ // where icon is the actual emoji icon (or a unicode number, or a noto code)
26384
+ END EXAMPLE
26385
+
26386
+ EXAMPLE
26387
+ // Go to https://zimjs.com/emoji/ and find press on an emoji
26388
+ // copy the emoji code and leave the noto_ at the start and paste the emoji code right after the _
26389
+ // setting color, will create an SVGContainer in the Emoji so individual parts can be colored
26390
+ new Emoji({code:"noto_\ud83e\udd51", color:series(red, blue, orange, purple, yellow)})
26391
+ .center()
26392
+ .expand(0) // blobs with interactive false do not get mouse, expand will give it a mouse for the drag
26393
+ .drag({all:true}); // without all:true would drag individual parts of the SVG
26394
+ END EXAMPLE
26395
+
25941
26396
  PARAMETERS
25942
26397
  ** supports DUO - parameters or single object with properties below
25943
26398
  ** supports OCT - parameter defaults can be set with STYLE control (like CSS)
25944
26399
  ** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
25945
26400
  Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
25946
26401
  code - |ZIM VEE| (default \ud83d\ude42") the Unicode Character or the Emoji from https://emojipedia.org/
25947
- or pass in UTF codes such as "\ud83d\ude42".
25948
- To convert from Unicode to UTF use https://zimjs.com/emoji/ (also see MORE link at bottom of page)
26402
+ or pass in UTF codes such as "\ud83d\ude42".
26403
+ To convert from Unicode to UTF use https://zimjs.com/emoji/
26404
+ This will add a ZIM Label with the character to the Emoji Container
26405
+ As of ZIM 020, this supports Noto (by Google) Color Emojis which stay consistent across platforms (Windows, Linux, Android, iOS)
26406
+ To turn the emoji into Noto emojis, use "noto_code" where code is the emoji character or a code described above
26407
+ This will lazy load a ZIM SVG of the character to the Emoji Container
26408
+ If color or borderColor parameters are used, the SVG will be in the form of an SVGContainer holding ZIM Blob and Squiggle objects
26409
+ then each part can be colored, dragged, wiggled, or animated
26410
+ If using the Emoji in a Tile() or Wrapper() then preload the emoji in the Frame assets or zapp_assets using "noto_code"
26411
+ This will preload the SVG from the Google GitHub repository - the location is set in ZIM (similar to using "gf_" for Google fonts)
26412
+ NOTE: many of the parameters below will not work on the SVG as they were made for text based emojis (but color and borderColor will)
26413
+ see https://symbl.cc/en/platforms/google/ to see all - not easily searched though
26414
+ see https://zimjs.com/020/dpad.html for examples of changing parts of the SVG emoji (hide, position, color)
26415
+ see https://zimjs.com/emoji and choose Noto Edit Tool to edit and save an SVG emoji
25949
26416
  size - |ZIM VEE| (default 36) the size of the font in pixels
25950
26417
  monochrome - (default false) set to true to make black outline - this is actually the bold version of the icon
25951
26418
  italic - (default false) set the font to italic
25952
- ** SEE Label for the rest of the definitions
25953
- backgroundColor, corner, backing, padding, paddingH, paddingV, shiftH, shiftV, style, group, inherit
25954
26419
  backgroundColor - (default null) set to CSS color to add a rectangular color around the label
25955
26420
  The background color will change size to match the text of the label
25956
26421
  Note: the backgroundColor is different than a backing which can be any Display Object
@@ -25968,6 +26433,12 @@ paddingH - (default padding) places border out at top bottom
25968
26433
  paddingV - (default padding) places border out at left and right
25969
26434
  shiftH - (default 0) move the emoji inside the container horizontally
25970
26435
  shiftV - (default 0) move the emoji inside the container vertically
26436
+ color - |ZIM VEE| (default null) for when color is set, set to a color or an array of colors to apply to fill of children - in order of the children
26437
+ usually a series() would be used here for colors in order, or an array for random colors
26438
+ setting this will make an SVG with bitmap:false - so blobs and squiggles so parts of SVG can be colored
26439
+ borderColor - |ZIM VEE| (default null) for when borderColor is set to a color or an array of colors to apply to border of children - in order of the children
26440
+ order - and array showing a new order of the old index numbers
26441
+ eg [3,1,2,0] means the old index 3 is now at level 0, old index 1 stays the same, old index 2 is now third, and old index 0 is at the top
25971
26442
  style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
25972
26443
  group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
25973
26444
  inherit - (default null) used internally but can receive an {} of styles directly
@@ -25987,6 +26458,8 @@ PROPERTIES
25987
26458
  type - the name of the class as a String
25988
26459
  veeObj - an object with ZIM VEE original parameters:value allowing the ZIM VEE values to be referenced
25989
26460
  for instance, obj.prop = Pick.choose(obj.veeObj.prop); will reset the the prop to the result of the original ZIM VEE value
26461
+ label - reference to the ZIM Label if emoji is a string
26462
+ svg - reference to the SVG if the emoji is SVG or SVGContainer (color set) - if emoji is an SVGContainer then it has children
25990
26463
 
25991
26464
  ALSO: see ZIM Container for properties such as:
25992
26465
  width, height, widthOnly, heightOnly, draggable, level, depth, group
@@ -26001,8 +26474,8 @@ See the CreateJS Easel Docs for Container events such as:
26001
26474
  added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
26002
26475
  --*///+54.58
26003
26476
 
26004
- zim.Emoji = function(code, size, monochrome, italic, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backing, padding, paddingH, paddingV, shiftH, shiftV, style, group, inherit) {
26005
- var sig = "code, size, monochrome, italic, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backing, padding, paddingH, paddingV, shiftH, shiftV, style, group, inherit";
26477
+ zim.Emoji = function(code, size, monochrome, italic, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backing, padding, paddingH, paddingV, shiftH, shiftV, color, borderColor, order, style, group, inherit) {
26478
+ var sig = "code, size, monochrome, italic, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backing, padding, paddingH, paddingV, shiftH, shiftV, color, borderColor, order, style, group, inherit";
26006
26479
  var duo; if (duo = zob(zim.Emoji, arguments, sig, this)) return duo;
26007
26480
  z_d("54.58");
26008
26481
 
@@ -26021,17 +26494,34 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
26021
26494
  if (zot(paddingV)) paddingV = DS.paddingV!=null?DS.paddingV:padding;
26022
26495
  if (zot(shiftH)) shiftH = DS.shiftH!=null?DS.shiftH:0;
26023
26496
  if (zot(shiftV)) shiftV = DS.shiftV!=null?DS.shiftV:0;
26497
+ if (zot(color)) color = DS.color!=null?DS.color:null;
26498
+ if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
26499
+ if (zot(order)) order = DS.order!=null?DS.order:null;
26024
26500
 
26025
26501
  // PICK
26026
26502
  var oa = remember(code, size);
26027
26503
  this.veeObj = {code:oa[0], size:oa[1]};
26028
26504
  function remember() {return arguments;} // for cloning PICK
26029
26505
  code = zim.Pick.choose(code);
26030
- size = zim.Pick.choose(size);
26506
+ size = zim.Pick.choose(size);
26031
26507
 
26032
- if (code.substring(0,2) == "U+") code = zim.unicodeToUTF(code);
26508
+ if (code.substring && code.substring(0,2) == "U+") code = zim.unicodeToUTF(code);
26509
+ this.zimContainer_constructor();
26510
+ // this.zimLabel_constructor(code, size, null, null, null, null, null, null, null, null, italic, null, null, null, backing, null, null, backgroundColor, null, null, corner, null, padding, paddingH, paddingV, shiftH, shiftV);
26511
+
26512
+ var that = this;
26513
+
26514
+ // SVG TEST
26515
+ var match;
26516
+ if (code.match) match = code.match(/^noto_(.*)/);
26517
+ if (match) {
26518
+ var svg = that.svg = new zim.SVG({svg:code, interactive:!(color||borderColor), bitmap:!(color||borderColor), color:color, borderColor:borderColor, order:order});
26519
+ svg.addTo(this);
26520
+ } else {
26521
+ var label = this.label = new zim.Label(code, size, null, null, null, null, null, null, null, null, italic, null, null, null, backing, null, null, backgroundColor, null, null, corner, null, padding, paddingH, paddingV, shiftH, shiftV);
26522
+ label.addTo(this);
26523
+ }
26033
26524
 
26034
- this.zimLabel_constructor(code, size, null, null, null, null, null, null, null, null, italic, null, null, null, backing, null, null, backgroundColor, null, null, corner, null, padding, paddingH, paddingV, shiftH, shiftV);
26035
26525
  this.type = "Emoji";
26036
26526
 
26037
26527
  // MONITOR
@@ -26039,12 +26529,12 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
26039
26529
 
26040
26530
  this.code = code;
26041
26531
  this.size = size;
26042
- var that = this;
26532
+
26043
26533
 
26044
26534
  var b = this.getBounds();
26045
26535
  var h = 5;
26046
26536
  var w = 3
26047
- this.bounds = this.setBounds(b.x+w,b.y-h+1,b.width-w*2,b.height+h);
26537
+ if (b) this.bounds = this.setBounds(b.x+w,b.y-h+1,b.width-w*2,b.height+h);
26048
26538
 
26049
26539
  if (monochrome) {
26050
26540
  this.saturation = -100;
@@ -26078,11 +26568,11 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
26078
26568
 
26079
26569
  if (style!==false) zim.styleTransforms(this, DS);
26080
26570
  this.clone = function (exact) {
26081
- return that.cloneProps(new zim.Emoji((exact||!zim.isPick(oa[0]))?code:oa[0], (exact||!zim.isPick(oa[1]))?that.size:oa[1], monochrome, italic, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backing, padding, paddingH, paddingV, shiftH, shiftV, style, that.group, inherit));
26571
+ return that.cloneProps(new zim.Emoji((exact||!zim.isPick(oa[0]))?code:oa[0], (exact||!zim.isPick(oa[1]))?that.size:oa[1], monochrome, italic, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backing, padding, paddingH, paddingV, shiftH, shiftV, color, borderColor, order, style, that.group, inherit));
26082
26572
  };
26083
26573
 
26084
26574
  };
26085
- zim.extend(zim.Emoji, zim.Label, ["clone","cache"], "zimLabel", false);
26575
+ zim.extend(zim.Emoji, zim.Container, ["clone","cache"], "zimContainer", false);
26086
26576
  //-54.58
26087
26577
 
26088
26578
  /*--
@@ -26896,9 +27386,8 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
26896
27386
  that.pressed = onCheck = pressCheck = false;
26897
27387
 
26898
27388
  if (reallyOn) buttonOn(); // will recall the roll ZIM01
26899
- else if (that.rollPersist) removeRoll();
26900
-
26901
- if (e.nativeEvent && (e.nativeEvent.type == "touchend" || e.nativeEvent == "touchcancel")) { // touch screen
27389
+ else if (that.rollPersist) removeRoll();
27390
+ if (WW.M || (e.nativeEvent && (e.nativeEvent.type == "touchend" || e.nativeEvent.type == "touchcancel"))) { // Mobile or touch screen
26902
27391
  buttonOff();
26903
27392
  }
26904
27393
  }, null, null, null, null, mID);
@@ -41567,7 +42056,7 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
41567
42056
  //-66.1
41568
42057
 
41569
42058
  /*--
41570
- zim.DPad = function(axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, style, group, inherit)
42059
+ zim.DPad = function(axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, useBubble, style, group, inherit)
41571
42060
 
41572
42061
  DPad
41573
42062
  zim class - extends a zim.Container which extends a createjs.Container
@@ -41577,8 +42066,10 @@ A DPad (Directional Pad) can be used to control x and y values
41577
42066
  This is primarily handy on mobile where a substitute for keypresses is needed
41578
42067
  The DPad can be set up for all directions, horizontal or vertical
41579
42068
  The DPad can be passed in to a ZIM MotionController to control an object
42069
+ There are default arrows but in ZIM 020 we added useBubble for a joystick like effect
41580
42070
 
41581
42071
  See: https://zimjs.com/ten/dpad.html
42072
+ See: https://zimjs.com/020/dpad.html
41582
42073
 
41583
42074
  NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
41584
42075
 
@@ -41615,6 +42106,7 @@ innerScale - (default .5) the scale relative to the indicator
41615
42106
  activeRadius - (default width*2) radius at which the DPad works
41616
42107
  clamp - (default true) set to false to not limit the value between -1 and 1
41617
42108
  logo - (default false) set to true to show the letter D in the DPad - or add your own
42109
+ useBubble - (default false) set to true to use a joystick like effect (removes arrows)
41618
42110
  style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
41619
42111
  group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
41620
42112
  inherit - (default null) used internally but can receive an {} of styles directly
@@ -41636,6 +42128,7 @@ type - holds the class name as a String
41636
42128
  dirX, dirY - the x and y values for the DPad - between -1 and 1 if clamp is set
41637
42129
  these can be multiplied by a factor to adjust speed - or use speed parameter of associated MotionController
41638
42130
  blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
42131
+ bubble - reference to the ZIM Circle if useBubble is set to true
41639
42132
  enabled - default is true - set to false to disable
41640
42133
 
41641
42134
  ALSO: see ZIM Container for properties such as:
@@ -41652,8 +42145,8 @@ dispatches a "change" event with dirX and dirY provided as well on the event obj
41652
42145
  ALSO: see the CreateJS Easel Docs for Container events such as:
41653
42146
  added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
41654
42147
  --*///+66.2
41655
- zim.DPad = function(axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, style, group, inherit) {
41656
- var sig = "axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, style, group, inherit";
42148
+ zim.DPad = function(axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, useBubble, style, group, inherit) {
42149
+ var sig = "axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, useBubble, style, group, inherit";
41657
42150
  var duo; if (duo = zob(zim.DPad, arguments, sig, this)) return duo;
41658
42151
  z_d("66.2");
41659
42152
 
@@ -41682,11 +42175,12 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
41682
42175
  if (zot(activeRadius)) activeRadius = DS.activeRadius!=null?DS.activeRadius:width; // note, twice diameter
41683
42176
  if (zot(clamp)) clamp = DS.clamp!=null?DS.clamp:true;
41684
42177
  if (zot(logo)) logo = DS.logo!=null?DS.logo:false;
42178
+ if (zot(useBubble)) useBubble = DS.useBubble!=null?DS.useBubble:false;
41685
42179
 
41686
42180
  var that = this;
41687
42181
 
41688
42182
  this.axis = axis;
41689
- this.outer = new zim.Circle(width/2, backgroundColor, borderColor, borderWidth).addTo(this);
42183
+ var outer = this.outer = new zim.Circle(width/2, backgroundColor, borderColor, borderWidth).addTo(this);
41690
42184
  var inner = this.inner = new zim.Circle(width*innerScale/2, "rgba(0,0,0,.2)").center(this);
41691
42185
  if (logo) this.logo = new zim.Label({text:"D", bold:true}).center(inner).mov(1,2).alp(.3);
41692
42186
  var arrows = new zim.Container().addTo(this);
@@ -41700,6 +42194,41 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
41700
42194
  } else if (axis == "both") {
41701
42195
  numArrows = 4;
41702
42196
  }
42197
+ if (useBubble) {
42198
+ numArrows = 0;
42199
+ var bubble = that.bubble = new zim.Circle((outer.radius-inner.radius)/2-4, indicatorColor.toAlpha(.2), indicatorColor, 2).center(that);
42200
+ that.bubbleDampX = new zim.Damp();
42201
+ that.bubbleDampY = new zim.Damp();
42202
+ var r = outer.radius - bubble.radius - 4;
42203
+ that.down = false;
42204
+ that.bubbleDown = that.on("mousedown", function() {
42205
+ that.down = true;
42206
+ });
42207
+ that.bubbleUp = that.on("pressup", function() {
42208
+ that.down = false;
42209
+ });
42210
+
42211
+ // TODO - handle axis
42212
+
42213
+ that.bubbleTicker = zim.Ticker.add(function() {
42214
+ if (that.down) {
42215
+ var point = that.globalToLocal(that.stage.frame.mouseX, that.stage.frame.mouseY);
42216
+ bubble.loc(that.bubbleDampX.convert(point.x), that.bubbleDampY.convert(point.y));
42217
+ if (dist(0,0,bubble.x,bubble.y) > r) {
42218
+ var a = angle(bubble.x,bubble.y)*RAD
42219
+ var x = r*Math.cos(a);
42220
+ var y = r*Math.sin(a);
42221
+ that.bubbleDampX.immediate(x);
42222
+ that.bubbleDampY.immediate(y);
42223
+ bubble.loc(x,y)
42224
+ }
42225
+ } else {
42226
+ bubble.loc(that.bubbleDampX.convert(0), that.bubbleDampY.convert(0));
42227
+ }
42228
+ if (axis==HORIZONTAL) bubble.y = 0;
42229
+ else if (axis==VERTICAL) bubble.x = 0;
42230
+ });
42231
+ }
41703
42232
  zim.loop(numArrows, function (i, total) {
41704
42233
  new zim.Triangle(arrowSize, arrowSize, arrowSize, indicatorColor).addTo(arrows).reg(null, zot(indicatorRadius)?(width-borderWidth)*.475:indicatorRadius).rot(i*360/total);
41705
42234
  });
@@ -41766,7 +42295,7 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
41766
42295
 
41767
42296
  if (style!==false) zim.styleTransforms(this, DS);
41768
42297
  this.clone = function() {
41769
- return that.cloneProps(new zim.DPad(axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, style, this.group, inherit));
42298
+ return that.cloneProps(new zim.DPad(axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, useBubble, style, this.group, inherit));
41770
42299
  };
41771
42300
 
41772
42301
  this.dispose = function(a,b,disposing) {
@@ -51155,7 +51684,7 @@ RETURNS obj for chaining
51155
51684
  zim.addTo = function(obj, container, index, still) {
51156
51685
  var sig = "obj, container, index, still";
51157
51686
  var duo; if (duo = zob(zim.addTo, arguments, sig)) return duo;
51158
- // if (obj.type=="AC"&&zdf) {zdf.ac("addTo", arguments); return obj;}
51687
+ // if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&zdf) {zdf.ac("addTo", arguments); return obj;}
51159
51688
  z_d("47.5");
51160
51689
  if (zot(obj)) {zogy("zim methods - addTo(): please provide object"); return;}
51161
51690
  if (zot(container)) {
@@ -51329,7 +51858,7 @@ RETURNS obj for chaining
51329
51858
  zim.centerReg = function(obj, container, index, add) {
51330
51859
  var sig = "obj, container, index, add";
51331
51860
  var duo; if (duo = zob(zim.centerReg, arguments, sig)) return duo;
51332
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("centerReg", arguments); return obj.addTo(container, index);}
51861
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("centerReg", arguments); return obj.addTo(container, index);}
51333
51862
  z_d("48");
51334
51863
  if (zot(obj) || !obj.getBounds || !obj.getBounds()) {zogy("zim methods - centerReg(): please provide object with bounds set"); return obj;}
51335
51864
  if (zot(add)) add = true;
@@ -51385,7 +51914,7 @@ RETURNS obj for chaining
51385
51914
  zim.center = function(obj, container, index, add) {
51386
51915
  var sig = "obj, container, index, add";
51387
51916
  var duo; if (duo = zob(zim.center, arguments, sig)) return duo;
51388
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("center", arguments); return obj.addTo(container, index);}
51917
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("center", arguments); return obj.addTo(container, index);}
51389
51918
  if (!zim.centerCheck) {z_d("48.1"); zim.centerCheck=true;}
51390
51919
  if (zot(obj) || !obj.getBounds) {zogy("zim.center(): please provide object with bounds"); return obj;}
51391
51920
  if (zot(container)) {
@@ -51655,7 +52184,7 @@ RETURNS obj for chaining
51655
52184
  zim.pos = function(obj, x, y, horizontal, vertical, container, index, add, reg, regX, regY) {
51656
52185
  var sig = "obj, x, y, horizontal, vertical, container, index, add, reg, regX, regY";
51657
52186
  var duo; if (duo = zob(zim.pos, arguments, sig)) return duo;
51658
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("pos", arguments); return obj.addTo(container, index);}
52187
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("pos", arguments); return obj.addTo(container, index);}
51659
52188
  z_d("41.5");
51660
52189
 
51661
52190
  // handle DIR effect
@@ -51902,7 +52431,7 @@ RETURNS obj for chaining
51902
52431
  zim.loc = function(obj, target, y, container, index, add, localToLocal, x) {
51903
52432
  var sig = "obj, target, y, container, index, add, localToLocal, x";
51904
52433
  var duo; if (duo = zob(zim.loc, arguments, sig)) return duo;
51905
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("loc", arguments); return obj.addTo(container, index);}
52434
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("loc", arguments); return obj.addTo(container, index);}
51906
52435
  z_d("41.55");
51907
52436
  if (zot(obj)) return;
51908
52437
  if (typeof target == "number") {
@@ -51974,7 +52503,7 @@ RETURNS obj for chaining
51974
52503
  zim.mov = function(obj, x, y) {
51975
52504
  var sig = "obj, x, y";
51976
52505
  var duo; if (duo = zob(zim.mov, arguments, sig)) return duo;
51977
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("mov", arguments); return obj;}
52506
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("mov", arguments); return obj;}
51978
52507
  z_d("41.6");
51979
52508
  if (zot(obj)) return;
51980
52509
  if (!zot(x)) obj.x += x;
@@ -52006,7 +52535,7 @@ scaleY - (default null) pass this in to scale x and y independently
52006
52535
  RETURNS obj for chaining
52007
52536
  --*///+41.97
52008
52537
  zim.sca = function(obj, scale, scaleY) {
52009
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("sca", arguments); return obj;}
52538
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("sca", arguments); return obj;}
52010
52539
  z_d("41.97");
52011
52540
  if (zot(obj) || zot(obj.scaleX)) return obj;
52012
52541
  if (zot(scale)) scale = obj.scaleX;
@@ -52241,7 +52770,7 @@ RETURNS obj for chaining
52241
52770
  zim.rot = function(obj, rotation, x, y) {
52242
52771
  z_d("41.8");
52243
52772
  if (zot(obj)) return;
52244
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("rot", arguments); return obj;}
52773
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("rot", arguments); return obj;}
52245
52774
  if (!zot(rotation)) {
52246
52775
  if (obj.parent && (!zot(x) || !zot(y))) {
52247
52776
  if (zot(x)) x = obj.x;
@@ -52299,7 +52828,7 @@ RETURNS obj for chaining
52299
52828
  zim.siz = function(obj, width, height, only) {
52300
52829
  z_d("41.85");
52301
52830
  if (zot(obj)) return;
52302
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("siz", arguments); return obj;}
52831
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("siz", arguments); return obj;}
52303
52832
  if (zot(only)) only = false;
52304
52833
  if (!zot(width) && !zot(height)) {
52305
52834
  obj.widthOnly = width; obj.heightOnly = height;
@@ -52334,7 +52863,7 @@ RETURNS obj for chaining
52334
52863
  zim.ske = function(obj, skewX, skewY) {
52335
52864
  z_d("41.9");
52336
52865
  if (zot(obj)) return;
52337
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("ske", arguments); return obj;}
52866
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("ske", arguments); return obj;}
52338
52867
  if (!zot(skewX)) obj.skewX = skewX;
52339
52868
  if (!zot(skewY)) obj.skewY = skewY;
52340
52869
  return obj;
@@ -52382,7 +52911,7 @@ RETURNS obj for chaining
52382
52911
  zim.reg = function(obj, regX, regY, still) {
52383
52912
  z_d("41.95");
52384
52913
  if (zot(obj)) return;
52385
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("reg", arguments); return obj;}
52914
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("reg", arguments); return obj;}
52386
52915
  var lastRegX = obj.regX;
52387
52916
  var lastRegY = obj.regY;
52388
52917
  var originalX = regX;
@@ -53419,7 +53948,7 @@ RETURNS obj for chaining
53419
53948
  zim.drag = function(obj, boundary, axis, overCursor, dragCursor, all, swipe, localBoundary, onTop, surround, slide, slideFactor, slideSnap, slideSnapDamp, reg, removeTweens, startBounds, rect, currentTarget, offStage, immediateBoundary, singleTouch, dropTargets, dropCopy, dropSnap, dropBack, dropEnd, dropFull, dropHitTest, dropScale, dropWidth, dropHeight, dropOriginal, style, group) {
53420
53949
  var sig = "obj, boundary, axis, overCursor, dragCursor, all, swipe, localBoundary, onTop, surround, slide, slideFactor, slideSnap, slideSnapDamp, reg, removeTweens, startBounds, rect, currentTarget, offStage, immediateBoundary, singleTouch, dropTargets, dropCopy, dropSnap, dropBack, dropEnd, dropFull, dropHitTest, dropScale, dropWidth, dropHeight, dropOriginal, style, group";
53421
53950
  var duo; if (duo = zob(zim.drag, arguments, sig)) return duo;
53422
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("drag", arguments); return obj;}
53951
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("drag", arguments); return obj;}
53423
53952
  z_d("31");
53424
53953
 
53425
53954
  var DS = style===false?group!=null?zim.getStyle(null,null,inherit,this.group):{}:zim.getStyle("Drag", group);
@@ -55102,7 +55631,7 @@ RETURNS obj for chaining
55102
55631
  zim.transform = function(obj, move, stretchX, stretchY, scale, rotate, allowToggle, visible, onTop, showStretch, showRotate, showScale, showReg, showBorder, borderColor, borderWidth, dashed, customCursors, handleSize, regSize, snapDistance, snapRotation, cache, events, ghostColor, ghostWidth, ghostDashed, ghostHidden, frame, container, minScaleX, maxScaleX, minScaleY, maxScaleY, sliceX, sliceY) {
55103
55632
  var sig = "obj, move, stretchX, stretchY, scale, rotate, allowToggle, visible, onTop, showStretch, showRotate, showScale, showReg, showBorder, borderColor, borderWidth, dashed, customCursors, handleSize, regSize, snapDistance, snapRotation, cache, events, ghostColor, ghostWidth, ghostDashed, ghostHidden, frame, container, minScaleX, maxScaleX, minScaleY, maxScaleY, sliceX, sliceY";
55104
55633
  var duo; if (duo = zob(zim.transform, arguments, sig)) return duo;
55105
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("transform", arguments); return obj;}
55634
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("transform", arguments); return obj;}
55106
55635
  z_d("33.5");
55107
55636
 
55108
55637
  // MONITOR
@@ -56293,7 +56822,9 @@ NOTE: gesture() only works on the currentTarget - not a container's children (li
56293
56822
  ZIM Frame should have touch set to true (which is the default for mobile)
56294
56823
 
56295
56824
  NOTE: as of ZIM 020 - trackpad support has been added - pinch to zoom, swipe both fingers horizontally for rotate
56296
-
56825
+ ignores pinch point and operates from registration point no matter what the regControl is set at
56826
+ regControl is still used for touch screen
56827
+
56297
56828
  ALSO: see the noGesture() method to remove some or all gestures
56298
56829
 
56299
56830
  ALSO: see the gestureBoundary() method to set or reset the boundary rectangle dynamically
@@ -56334,6 +56865,7 @@ rect - (depreciated) same as boundary - kept for backwards compatibility
56334
56865
  trackPad - (default true) set to false to not handle trackpad on laptop
56335
56866
  trackpad supports pinch for zoom
56336
56867
  trackpad supports swipe horizontally with both fingers (the same way) for rotate
56868
+ Ignores regControl and operates from registration point
56337
56869
 
56338
56870
  EVENTS
56339
56871
  Adds move, scale and rotate events to obj (when associated gesture parameters are set to true)
@@ -56344,7 +56876,7 @@ RETURNS obj for chaining
56344
56876
  zim.gesture = function(obj, move, scale, rotate, boundary, minScale, maxScale, snapRotate, localBoundary, slide, slideFactor, regControl, onTop, surround, circularBounds, rect, trackpad) {
56345
56877
  var sig = "obj, move, scale, rotate, boundary, minScale, maxScale, snapRotate, localBoundary, slide, slideFactor, regControl, onTop, surround, circularBounds, rect, trackpad";
56346
56878
  var duo; if (duo = zob(zim.gesture, arguments, sig)) return duo;
56347
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("gesture", arguments); return obj;}
56879
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("gesture", arguments); return obj;}
56348
56880
  z_d("34.5");
56349
56881
 
56350
56882
  // MONITOR
@@ -56710,17 +57242,15 @@ zim.gesture = function(obj, move, scale, rotate, boundary, minScale, maxScale, s
56710
57242
  // Handles laptop trackpad two-finger gestures via wheel and gesturechange events.
56711
57243
  // Completely separate from the touch block above - own state, own canvas listeners.
56712
57244
  // Does not interfere with touchscreen gesture() behaviour.
57245
+ // Always transforms around the object's own (unaltered) registration point -
57246
+ // regControl is intentionally ignored here.
56713
57247
  // -----------------------------------------------------------------------
56714
57248
  if (trackpad && !obj.zimTouch.tpAttached) {
56715
57249
 
56716
57250
  // Separate matrix state - never shares with the touch block vars above
56717
- var tpMatrixStart;
56718
57251
  var tpStartScaleX;
56719
57252
  var tpStartScaleY;
56720
57253
  var tpStartRotation;
56721
- var tpStartRegX;
56722
- var tpStartRegY;
56723
- var tpLastPoint;
56724
57254
  var tpActive = false;
56725
57255
  var tpEndTimeout = null;
56726
57256
 
@@ -56729,10 +57259,6 @@ zim.gesture = function(obj, move, scale, rotate, boundary, minScale, maxScale, s
56729
57259
  var tpAccumScale = 1; // multiplicative accumulator, applied to tpStartScaleX/Y
56730
57260
  var tpAccumRot = 0; // degrees accumulator, applied to tpStartRotation
56731
57261
 
56732
- // Pivot in global stage coords - set once per session at first wheel event
56733
- var tpPivotGX = 0;
56734
- var tpPivotGY = 0;
56735
-
56736
57262
  // Safari GestureEvent state
56737
57263
  var tpGestureBaseScale = 1; // e.scale at gesturestart (always 1 per spec, but captured for safety)
56738
57264
  var tpGestureBaseRot = 0; // e.rotation at gesturestart (always 0 per spec)
@@ -56740,29 +57266,19 @@ zim.gesture = function(obj, move, scale, rotate, boundary, minScale, maxScale, s
56740
57266
  var tpGestureLastRot = 0; // e.rotation at previous gesturechange, for delta
56741
57267
  var tpGestureActive = false;
56742
57268
 
56743
- // Begin a trackpad gesture session: snapshot current object state
56744
- function tpBeginSession(pivotGX, pivotGY) {
57269
+ // Begin a trackpad gesture session: snapshot current object state.
57270
+ // No registration point manipulation - obj keeps whatever regX/regY it already has.
57271
+ function tpBeginSession() {
56745
57272
  tpActive = true;
56746
- tpPivotGX = pivotGX;
56747
- tpPivotGY = pivotGY;
56748
57273
  tpAccumScale = 1;
56749
57274
  tpAccumRot = 0;
56750
- tpStartScaleX = obj.scaleX;
56751
- tpStartScaleY = obj.scaleY;
57275
+ tpStartScaleX = obj.scaleX;
57276
+ tpStartScaleY = obj.scaleY;
56752
57277
  tpStartRotation = obj.rotation;
56753
- tpStartRegX = obj.regX;
56754
- tpStartRegY = obj.regY;
56755
- tpLastPoint = null;
56756
- if (!regControl) {
56757
- obj.reg(0,0);
56758
- tpMatrixStart = obj.getMatrix();
56759
- obj.regX = tpStartRegX;
56760
- obj.regY = tpStartRegY;
56761
- }
56762
57278
  }
56763
57279
 
56764
- // Apply accumulated scale + rotation to the object using the same
56765
- // matrix technique as the touch block's pressmove pair path
57280
+ // Apply accumulated scale + rotation to the object.
57281
+ // Always transforms around obj's current registration point - regControl is ignored.
56766
57282
  function tpApply() {
56767
57283
  if (!tpActive) return;
56768
57284
 
@@ -56781,35 +57297,12 @@ zim.gesture = function(obj, move, scale, rotate, boundary, minScale, maxScale, s
56781
57297
 
56782
57298
  var newRotation = tpStartRotation + tpAccumRot;
56783
57299
 
56784
- if (regControl) {
56785
- if (obj.zimTouch.scale) {
56786
- obj.scaleX = newScaleX;
56787
- obj.scaleY = newScaleY;
56788
- }
56789
- if (obj.zimTouch.rotate) {
56790
- obj.rotation = newRotation;
56791
- }
56792
- } else {
56793
- obj.reg(0,0);
56794
-
56795
- // Pivot point in global coords -> local to obj
56796
- var point = zot(tpLastPoint)
56797
- ? obj.globalToLocal(tpPivotGX, tpPivotGY)
56798
- : obj.globalToLocal(tpLastPoint.x, tpLastPoint.y);
56799
-
56800
- var matrix = tpMatrixStart.clone()
56801
- .translate(point.x, point.y)
56802
- .rotate(newRotation - tpStartRotation)
56803
- .scale(newScaleX / tpStartScaleX, newScaleY / tpStartScaleY)
56804
- .translate(-point.x, -point.y);
56805
-
56806
- matrix.decompose(obj);
56807
-
56808
- // Correct minor drift - same technique as touch block
56809
- tpLastPoint = obj.localToGlobal(point.x, point.y);
56810
-
56811
- obj.regX = tpStartRegX;
56812
- obj.regY = tpStartRegY;
57300
+ if (obj.zimTouch.scale) {
57301
+ obj.scaleX = newScaleX;
57302
+ obj.scaleY = newScaleY;
57303
+ }
57304
+ if (obj.zimTouch.rotate) {
57305
+ obj.rotation = newRotation;
56813
57306
  }
56814
57307
 
56815
57308
  if (obj.zimTouch.scale) obj.dispatchEvent("scale");
@@ -56820,6 +57313,7 @@ zim.gesture = function(obj, move, scale, rotate, boundary, minScale, maxScale, s
56820
57313
  if (obj.getStage && obj.stage) obj.stage.update();
56821
57314
  }
56822
57315
 
57316
+
56823
57317
  // End session: apply snapRotate and clean up
56824
57318
  function tpEndSession() {
56825
57319
  if (!tpActive) return;
@@ -56881,7 +57375,7 @@ zim.gesture = function(obj, move, scale, rotate, boundary, minScale, maxScale, s
56881
57375
  if (!obj.zimTouch.scale) return;
56882
57376
  e.preventDefault();
56883
57377
 
56884
- if (!tpActive) tpBeginSession(stagePos.x, stagePos.y);
57378
+ if (!tpActive) tpBeginSession();
56885
57379
  else if (tpEndTimeout) { clearTimeout(tpEndTimeout); tpEndTimeout = null; }
56886
57380
 
56887
57381
  // deltaY: negative = fingers spreading (zoom in), positive = fingers closing (zoom out)
@@ -56912,7 +57406,7 @@ zim.gesture = function(obj, move, scale, rotate, boundary, minScale, maxScale, s
56912
57406
  // rotates the way two physical fingers would twist a dial - counter-clockwise.
56913
57407
  e.preventDefault();
56914
57408
 
56915
- if (!tpActive) tpBeginSession(stagePos.x, stagePos.y);
57409
+ if (!tpActive) tpBeginSession();
56916
57410
  else if (tpEndTimeout) { clearTimeout(tpEndTimeout); tpEndTimeout = null; }
56917
57411
 
56918
57412
  tpAccumRot -= dx * 0.3; // degrees per CSS pixel - negative so direction matches natural two-finger twist
@@ -56926,8 +57420,15 @@ zim.gesture = function(obj, move, scale, rotate, boundary, minScale, maxScale, s
56926
57420
  // Applied incrementally so it tracks the finger naturally.
56927
57421
  e.preventDefault();
56928
57422
 
57423
+ // var newX = obj.x - dx / (zim.scaX || 1);
57424
+ // var newY = obj.y - dy / (zim.scaY || 1);
57425
+
57426
+ // Chromebook adjust
57427
+ var isChromeOS = /CrOS/i.test(navigator.userAgent);
56929
57428
  var newX = obj.x - dx / (zim.scaX || 1);
56930
- var newY = obj.y - dy / (zim.scaY || 1);
57429
+ var newY = isChromeOS
57430
+ ? obj.y + dy / (zim.scaY || 1)
57431
+ : obj.y - dy / (zim.scaY || 1);
56931
57432
 
56932
57433
  var panResult = obj.zimTouch.checkBounds(newX, newY);
56933
57434
  obj.x = panResult.x;
@@ -56953,7 +57454,7 @@ zim.gesture = function(obj, move, scale, rotate, boundary, minScale, maxScale, s
56953
57454
  tpGestureLastScale = e.scale;
56954
57455
  tpGestureLastRot = e.rotation;
56955
57456
  var stagePos = tpEventToStage(e);
56956
- if (!tpActive) tpBeginSession(stagePos.x, stagePos.y);
57457
+ if (!tpActive) tpBeginSession();
56957
57458
  if (tpEndTimeout) { clearTimeout(tpEndTimeout); tpEndTimeout = null; }
56958
57459
  };
56959
57460
 
@@ -62696,7 +63197,7 @@ RETURNS obj for chaining
62696
63197
  zim.scaleTo = function(obj, boundObj, percentX, percentY, type, boundsOnly, simple) {
62697
63198
  var sig = "obj, boundObj, percentX, percentY, type, boundsOnly, simple";
62698
63199
  var duo; if (duo = zob(zim.scaleTo, arguments, sig)) return duo;
62699
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("scaleTo", arguments); return obj;}
63200
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("scaleTo", arguments); return obj;}
62700
63201
  z_d("43");
62701
63202
  if (zot(boundObj)) boundObj = WW.zdf&&WW.zdf.stage?WW.zdf.stage:null;
62702
63203
  if (zot(obj) || !obj.getBounds || !obj.getBounds()) {zog ("zim methods - scaleTo(): please provide an object (with setBounds) to scale"); return obj;}
@@ -62788,7 +63289,7 @@ RETURNS an Object literal with the new and old details (bX is rectangle x, etc.)
62788
63289
  zim.fit = function(obj, left, top, width, height, type) {
62789
63290
  var sig = "obj, left, top, width, height, type";
62790
63291
  var duo; if (duo = zob(zim.fit, arguments, sig)) return duo;
62791
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("fit", arguments); return obj;}
63292
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("fit", arguments); return obj;}
62792
63293
  z_d("46");
62793
63294
  if (zot(obj) || !obj.getBounds) return;
62794
63295
  if (!obj.getBounds()) {
@@ -63131,7 +63632,7 @@ RETURNS obj for chaining
63131
63632
  zim.expand = function(obj, padding, paddingV, paddingRight, paddingBottom) {
63132
63633
  var sig = "obj, padding, paddingV, paddingRight, paddingBottom";
63133
63634
  var duo; if (duo = zob(zim.expand, arguments, sig)) return duo;
63134
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("expand", arguments); return obj;}
63635
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("expand", arguments); return obj;}
63135
63636
  z_d("50");
63136
63637
  if (zot(obj) || !obj.getBounds || !obj.getBounds()) {zogy("zim methods - expand(): please provide object with bounds set"); return obj;}
63137
63638
  if (zot(padding)) padding = 20;
@@ -63397,7 +63898,7 @@ RETURNS the obj for chaining;
63397
63898
  zim.outline = function(obj, color, size, boundsOnly, reg, origin, whiteSize) {
63398
63899
  var sig = "obj, color, size, boundsOnly, reg, origin, whiteSize";
63399
63900
  var duo; if (duo = zob(zim.outline, arguments, sig)) return duo;
63400
- if (obj.type=="AC"&&WW.zdf) {WW.zdf.ac("outline", arguments); return obj;}
63901
+ if ((obj.type=="AC"||(obj.type=="Emoji"&&obj.svg&&obj.svg.type=="AC"))&&WW.zdf) {WW.zdf.ac("outline", arguments); return obj;}
63401
63902
  z_d("47");
63402
63903
  if (obj.type && obj.type == "zimOultineShape") {
63403
63904
  if (zon) zogy ("zim.outline() - warning, you are trying to outline an outline - do not outline in a loop");
@@ -70483,7 +70984,7 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
70483
70984
 
70484
70985
 
70485
70986
  /*--
70486
- zim.Bullets(list, bulletType, size, color, cols, font, italic, bold, variant, shiftH, shiftV, spacing, spacingH, spacingV, colSpacing, bulletAlign, style, group, inherit)
70987
+ zim.Bullets(list, bulletType, size, color, cols, font, italic, bold, variant, shiftH, shiftV, spacing, spacingH, spacingV, colSpacing, bulletAlign, rtl, style, group, inherit)
70487
70988
 
70488
70989
  Bullets
70489
70990
  zim class - extends a zim.Tile which extends a zim.Container
@@ -70548,6 +71049,7 @@ spacingH - (default spacing) horizontal spacing between bullet and text
70548
71049
  spacingV - (default spacing) vertical spacing
70549
71050
  colSpacing - (default spacingH) spacing between columns
70550
71051
  bulletAlign - (default LEFT) alignment of bullets
71052
+ rtl - (default false (unless zim.DIR=true)) set to true to put bullets on the right
70551
71053
  style - (default true) set to false to ignore styles set with the STYLE
70552
71054
  group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s)
70553
71055
  inherit - (default null) used internally but can receive an {} of styles directly
@@ -70582,8 +71084,8 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
70582
71084
 
70583
71085
  --*///+67.8
70584
71086
 
70585
- zim.Bullets = function(list, bulletType, size, color, cols, font, italic, bold, variant, shiftH, shiftV, spacing, spacingH, spacingV, colSpacing, bulletAlign, style, group, inherit) {
70586
- var sig = "list, bulletType, size, color, cols, font, italic, bold, variant, shiftH, shiftV, spacing, spacingH, spacingV, colSpacing, bulletAlign, style, group, inherit";
71087
+ zim.Bullets = function(list, bulletType, size, color, cols, font, italic, bold, variant, shiftH, shiftV, spacing, spacingH, spacingV, colSpacing, bulletAlign, rtl, style, group, inherit) {
71088
+ var sig = "list, bulletType, size, color, cols, font, italic, bold, variant, shiftH, shiftV, spacing, spacingH, spacingV, colSpacing, bulletAlign, rtl, style, group, inherit";
70587
71089
  var duo; if (duo = zob(zim.Bullets, arguments, sig, this)) return duo;
70588
71090
  z_d("67.8");
70589
71091
 
@@ -70609,26 +71111,44 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
70609
71111
  if (zot(spacingH)) spacingH = DS.spacingH!=null?DS.spacingH:spacing;
70610
71112
  if (zot(spacingV)) spacingV = DS.spacingV!=null?DS.spacingV:spacing;
70611
71113
  if (zot(colSpacing)) colSpacing = DS.colSpacing!=null?DS.colSpacing:spacingH;
70612
- if (zot(bulletAlign)) bulletAlign = DS.bulletAlign!=null?DS.bulletAlign:LEFT;
71114
+ if (zot(rtl)) rtl = DS.rtl!=null?DS.rtl:WW.DIR=="rtl"||zim.DIR=="rtl";
71115
+ if (zot(bulletAlign)) bulletAlign = DS.bulletAlign!=null?DS.bulletAlign:rtl?RIGHT:LEFT;
70613
71116
  var tileList = [];
70614
71117
  var num = 1;
70615
71118
  this.list = list;
70616
71119
  var icons = [];
70617
- zim.loop(list, function(words, i) {
70618
- if (words.type=="Bullets") { // nested Bullets
70619
- tileList.push(new zim.Container(1,1));
70620
- tileList.push(words);
70621
- return;
70622
- }
71120
+ zim.loop(list, function(words, i) {
70623
71121
  const bt = zik(bulletType);
70624
71122
  icons.push(bt);
71123
+ if (rtl) {
71124
+ if (words.type=="Bullets") { // nested Bullets
71125
+ tileList.push(words);
71126
+ tileList.push(new zim.Container(1,1));
71127
+ } else {
71128
+ makeLabel(words);
71129
+ makeIcon(bt);
71130
+ }
71131
+ } else {
71132
+ if (words.type=="Bullets") { // nested Bullets
71133
+ tileList.push(new zim.Container(1,1));
71134
+ tileList.push(words);
71135
+ return;
71136
+ }
71137
+ makeIcon(bt);
71138
+ makeLabel(words);
71139
+ }
71140
+ });
71141
+
71142
+ function makeIcon(bt) {
70625
71143
  if (bt.type && bt.clone) tileList.push(bt.clone());
70626
71144
  else if (bt == "circle") tileList.push(new zim.Circle(5, color));
70627
71145
  else if (bt == "square") tileList.push(new zim.Rectangle(10, 10, color));
70628
71146
  else if (bt == "dash") tileList.push(new zim.Label({text:"-", size:size, font:font, color:color, italic:italic, bold:bold, variant:variant, shiftH:shiftH, shiftV:shiftV-2}));
70629
71147
  else if (bt == "number" || bt == "numbers") tileList.push(new zim.Label({text:(num++)+".", size:size, font:font, color:color, italic:italic, bold:bold, variant:variant, shiftH:shiftH, shiftV:shiftV}));
71148
+ }
71149
+ function makeLabel(words) {
70630
71150
  tileList.push(new zim.Label({text:words, size:size, font:font, color:color, italic:italic, bold:bold, variant:variant, shiftH:shiftH, shiftV:shiftV}));
70631
- })
71151
+ }
70632
71152
  if (cols > 1 ) {
70633
71153
  // need to shift pairs
70634
71154
  // [b1, w1, b2, w2, b3, w3, b4, w4, b5, w5]
@@ -70646,6 +71166,7 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
70646
71166
  })
70647
71167
  }, null, null, 2); // steps of 2
70648
71168
  }
71169
+
70649
71170
  this.zimTile_constructor(tileList, cols*2, Math.ceil(list.length/cols), series(spacingH,colSpacing), spacingV, true, null, null, null, null, null, null, series(bulletAlign, LEFT), CENTER);
70650
71171
  this.type = "Bullets";
70651
71172
 
@@ -70657,7 +71178,7 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
70657
71178
  exactItems.push(icon.clone?icon.clone(true):icon);
70658
71179
  }
70659
71180
  }
70660
- return that.cloneProps(new zim.Bullets(list, exact?zim.series(exactItems):bulletType, size, color, cols, font, italic, bold, variant, shiftH, shiftV, spacing, spacingH, spacingV, colSpacing, bulletAlign, this.style, this.group));
71181
+ return that.cloneProps(new zim.Bullets(list, exact?zim.series(exactItems):bulletType, size, color, cols, font, italic, bold, variant, shiftH, shiftV, spacing, spacingH, spacingV, colSpacing, bulletAlign, rtl, this.style, this.group));
70661
71182
  };
70662
71183
  };
70663
71184
  zim.extend(zim.Bullets, zim.Tile, ["clone"], "zimTile", false);
@@ -76663,6 +77184,7 @@ dispatches a "moving" event if target is moving and "startmoving" and "stopmovin
76663
77184
  var frame = stage.frame;
76664
77185
 
76665
77186
  if (!zot(orient)) rotate = orient; // renamed parameter to orient
77187
+ if (zot(firstPerson)) firstPerson = false;
76666
77188
 
76667
77189
  if (zot(target)) {target = new zim.Container(1,1, null, null, false);} // make a surrogate if only wanting controller data
76668
77190
  var accelerator = target.type == "Accelerator";
@@ -76672,9 +77194,10 @@ dispatches a "moving" event if target is moving and "startmoving" and "stopmovin
76672
77194
  type = "manual";
76673
77195
  if (zot(axis)) axis = dPad.axis;
76674
77196
  if (axis == "all") axis = "both";
76675
-
77197
+ first = {rotation:0, speedX:that.speed, speedY:that.speed};
76676
77198
  dPad.on("change", function() {
76677
77199
  var d = {dirX:dPad.dirX, dirY:dPad.dirY};
77200
+ if (firstPerson) {doFirstPerson(d); return;}
76678
77201
  if (tileObj) {
76679
77202
  down = [0,0,0,0];
76680
77203
  var dC = false;
@@ -76695,6 +77218,7 @@ dispatches a "moving" event if target is moving and "startmoving" and "stopmovin
76695
77218
  that.convert(target.x+dPad.dirX*speed, target.y+dPad.dirY*speed);
76696
77219
  }
76697
77220
  }, null, null, null, null, mID);
77221
+
76698
77222
  if (tileObj) {
76699
77223
  dPad.on("pressup", function() {
76700
77224
  down = [0,0,0,0];
@@ -76723,8 +77247,7 @@ dispatches a "moving" event if target is moving and "startmoving" and "stopmovin
76723
77247
  if (zot(diagonal)) diagonal = true;
76724
77248
  if (axis == "horizontal" || axis == "vertical") diagonal = false;
76725
77249
  if (zot(damp) || damp===true) damp = (type=="keydown" || type=="gamebutton") ? 1: (type=="pressmove"?.5:.1);
76726
- if (damp === false) damp = 1;
76727
- if (zot(firstPerson)) firstPerson = false;
77250
+ if (damp === false) damp = 1;
76728
77251
  if (zot(turnSpeed)) turnSpeed = speed * .4;
76729
77252
  if (zot(moveThreshold)) moveThreshold = 4;
76730
77253
  if (zot(stickThreshold)) stickThreshold = tileObj?.3:.2;
@@ -80695,7 +81218,7 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
80695
81218
  //-69.9747
80696
81219
 
80697
81220
  /*--
80698
- zim.Perspective = function(obj, points, interactive, showControls, allowToggle, move, borderColor, borderWidth, dashed, plane, fade, dynamic, frame, style, group, inherit)
81221
+ zim.Perspective = function(obj, points, interactive, showControls, allowToggle, move, borderColor, borderWidth, dashed, plane, fade, dynamic, frame, resolution, maskShape, feather, onTop, overlay, clipping, passthrough, passthroughScale, passthroughShiftX, passthroughShiftY, style, group, inherit)
80699
81222
 
80700
81223
  Perspective
80701
81224
  zim class extends ZIM Container which extends CreateJS Container
@@ -80833,6 +81356,22 @@ plane - (default false) set to true to repeat the object making a plane to infin
80833
81356
  fade - (default true) if a plane is set, this will fade the distance
80834
81357
  dynamic - (default true unless obj is Pic, then false) set to false if a Container, etc. does not change or animate
80835
81358
  frame - (default zimDefaultFrame) set the zim Frame the perspective is in if in a different frame than the default frame
81359
+ resolution - (default 1) the resolution multiplier for the internal WebGL shader canvas (e.g. 0.5 for half-resolution to boost GPU performance on laptops and mobile).
81360
+ maskShape - (default "rect") the cutout mask shape: "rect" (standard 4-corner quad), "circle" (1:1 true circle with aspect-ratio correction), or "ellipse" (stretches to the quad bounds)
81361
+ or a ZIM DisplayObject (such as a Blob, Circle, or Container) to use as a dynamic GPU alpha mask texture (passed into iChannel1 with multi-tap blur spread).
81362
+ feather - (default 0) edge softness from 0 to 1 applied to the quad edges, circle/ellipse borders, or texture mask in the GPU shader.
81363
+ onTop - (default true) set to false to not bring the object to the top of its container when pressed
81364
+ overlay - (default false) set to true to use a DOM ShaderOverlay (Tag) rather than an in-canvas Shader (Bitmap)
81365
+ this bypasses 2D canvas blitting for maximum GPU performance and automatically
81366
+ hides controls for presentation mode.
81367
+ By default, this overlays above the stage canvas z-index = 100
81368
+ can be adjusted with perspective.shader.tag.style.zIndex
81369
+ if placed under the canvas, ensure the Frame color is set to clear (also see overlay property)
81370
+ clipping - (default true) when overlay is true, clamps the shader canvas to the stage bounds to optimize GPU fill rate by trimming off-stage pixels - set to false if animating or moving across stage boundaries to avoid edge clipping
81371
+ passthrough - (default false) set to true to display the asset unwarped (at original 1:1 aspect ratio), centered at the 4-point centroid and cropped by the perspective boundary.
81372
+ passthroughScale - (default 1) scale multiplier for the asset when passthrough is true, scaling from the center of the asset.
81373
+ passthroughShiftX - (default 0) horizontal pixel offset for the asset beneath the crop window when passthrough is true.
81374
+ passthroughShiftY - (default 0) vertical pixel offset for the asset beneath the crop window when passthrough is true.
80836
81375
  style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
80837
81376
  group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
80838
81377
  inherit - (default null) used internally but can receive an {} of styles directly
@@ -80875,6 +81414,17 @@ uniforms - refernce to the ZIM Uniforms for the Shader
80875
81414
  use perspective.uniforms.plane to get or set the plane setting of the perspective
80876
81415
  use perspective.uniforms.fade to get or set the fade setting of plane
80877
81416
  toggled - get control state - true if showing and false if not - see toggle() method to set toggled
81417
+ maskShape - get or set the cutout shape "rect", "circle", "ellipse", or the DisplayObject provided
81418
+ feather - get or set the edge softness / feathering amount (0 to 1).
81419
+ resolution - the resolution multiplier of the shader canvas.
81420
+ mask - reference to the mask DisplayObject container if a mask was provided.
81421
+ onTop - get or set whether the perspective comes to the top of its container when pressed
81422
+ overlay - get or set whether to render as a DOM ShaderOverlay - see overlay parameter
81423
+ clipping - get or set whether the overlay canvas bounding box is clamped to the stage boundaries
81424
+ passthrough - get or set whether the asset is displayed unwarped and cropped by the quad boundary.
81425
+ passthroughScale - get or set the scale of the asset when passthrough is true.
81426
+ passthroughShiftX - get or set the horizontal pixel offset of the asset beneath the crop window when passthrough is true.
81427
+ passthroughShiftY - get or set the vertical pixel offset of the asset beneath the crop window when passthrough is true.
80878
81428
 
80879
81429
  ALSO: see ZIM Container for properties such as:
80880
81430
  width, height, widthOnly, heightOnly, draggable, level, depth, group
@@ -80885,463 +81435,872 @@ x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
80885
81435
  alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, etc.
80886
81436
 
80887
81437
  --*///+69.9748
80888
- zim.Perspective = function(obj, points, interactive, showControls, allowToggle, move, borderColor, borderWidth, dashed, plane, fade, dynamic, frame, style, group, inherit) {
80889
- var sig = "obj, points, interactive, showControls, allowToggle, move, borderColor, borderWidth, dashed, plane, fade, dynamic, frame, style, group, inherit";
80890
- var duo; if (duo = zob(zim.Perspective, arguments, sig, this)) return duo;
80891
- z_d("69.9748");
80892
- this.group = group;
80893
- var DS = style === false ? {} : zim.getStyle("Perspective", group, inherit);
81438
+ zim.Perspective = function(obj, points, interactive, showControls, allowToggle, move, borderColor, borderWidth, dashed, plane, fade, dynamic, frame, resolution, maskShape, feather, onTop, overlay, clipping, passthrough, passthroughScale, passthroughShiftX, passthroughShiftY, style, group, inherit) {
81439
+ var sig = "obj, points, interactive, showControls, allowToggle, move, borderColor, borderWidth, dashed, plane, fade, dynamic, frame, resolution, maskShape, feather, onTop, overlay, clipping, passthrough, passthroughScale, passthroughShiftX, passthroughShiftY, style, group, inherit";
81440
+ var duo; if (duo = zob(zim.Perspective, arguments, sig, this)) return duo;
81441
+ z_d("69.9770");
81442
+ this.group = group;
81443
+ var DS = style === false ? {} : zim.getStyle("Perspective", group, inherit);
81444
+
81445
+ if (zot(obj)) obj = DS.obj != null ? DS.obj : new zim.Tile(new zim.Rectangle(50, 50, [purple, pink, white]), 5, 5, 10, 10);
81446
+ if (zot(points)) points = DS.points != null ? DS.points : null;
81447
+ if (zot(interactive)) interactive = DS.interactive != null ? DS.interactive : true;
81448
+ if (zot(showControls)) showControls = DS.showControls != null ? DS.showControls : true;
81449
+ if (zot(allowToggle)) allowToggle = DS.allowToggle != null ? DS.allowToggle : true;
81450
+ if (zot(move)) move = DS.move != null ? DS.move : true;
81451
+ if (zot(borderColor)) borderColor = DS.borderColor != null ? DS.borderColor : red;
81452
+ if (zot(borderWidth)) borderWidth = DS.borderWidth != null ? DS.borderWidth : 2;
81453
+ if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
81454
+ else if (borderColor != null && borderWidth == null) borderWidth = 2;
81455
+ if (zot(dashed)) dashed = DS.dashed != null ? DS.dashed : false;
81456
+ if (zot(plane)) plane = DS.plane != null ? DS.plane : false;
81457
+ if (zot(fade)) fade = DS.fade != null ? DS.fade : true;
81458
+ if (zot(dynamic)) dynamic = DS.dynamic != null ? DS.dynamic : true;
81459
+ if (zot(frame)) frame = DS.frame != null ? DS.frame : zdf;
81460
+ if (zot(resolution)) resolution = DS.resolution != null ? DS.resolution : 1;
81461
+ if (zot(maskShape)) maskShape = DS.maskShape != null ? DS.maskShape : "rect";
81462
+ if (zot(feather)) feather = DS.feather != null ? DS.feather : 0;
81463
+ if (zot(onTop)) onTop = DS.onTop != null ? DS.onTop : true;
81464
+ if (zot(overlay)) overlay = DS.overlay != null ? DS.overlay : false;
81465
+ if (zot(clipping)) clipping = DS.clipping != null ? DS.clipping : true;
81466
+ if (zot(passthrough)) passthrough = DS.passthrough != null ? DS.passthrough : false;
81467
+ if (zot(passthroughScale)) passthroughScale = DS.passthroughScale != null ? DS.passthroughScale : 1;
81468
+ if (zot(passthroughShiftX)) passthroughShiftX = DS.passthroughShiftX != null ? DS.passthroughShiftX : 0;
81469
+ if (zot(passthroughShiftY)) passthroughShiftY = DS.passthroughShiftY != null ? DS.passthroughShiftY : 0;
81470
+
81471
+ var size = Math.max(frame.width, frame.height);
80894
81472
 
80895
- if (zot(obj)) obj=DS.obj!=null?DS.obj:new zim.Tile(new zim.Rectangle(50, 50, [purple,pink,white]), 5, 5, 10, 10);
80896
- if (zot(points)) points=DS.points!=null?DS.points:null;
80897
- if (zot(interactive)) interactive=DS.interactive!=null?DS.interactive:true;
80898
- if (zot(showControls)) showControls=DS.showControls!=null?DS.showControls:true;
80899
- if (zot(allowToggle)) allowToggle=DS.allowToggle!=null?DS.allowToggle:true;
80900
- if (zot(move)) move=DS.move!=null?DS.move:true;
80901
- if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:red;
80902
- if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:2;
80903
- if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
80904
- else if (borderColor!=null && borderWidth==null) borderWidth = 2;
80905
- if (zot(dashed)) dashed=DS.dashed!=null?DS.dashed:false;
80906
- if (zot(plane)) plane=DS.plane!=null?DS.plane:false;
80907
- if (zot(fade)) fade=DS.fade!=null?DS.fade:true;
80908
- if (zot(dynamic)) dynamic=DS.dynamic!=null?DS.dynamic:true;
80909
- if (zot(frame)) frame=DS.frame!=null?DS.frame:zdf;
80910
-
80911
- // PICK
80912
- var oa = remember(obj, borderColor, borderWidth, dashed);
80913
- this.veeObj = {obj:oa[0], borderColor:oa[1], borderWidth:oa[2], dashed:oa[3]};
80914
- function remember() {return arguments;} // for cloning PICK
80915
- obj = zim.Pick.choose(obj);
80916
- borderColor = zim.Pick.choose(borderColor);
80917
- borderWidth = zim.Pick.choose(borderWidth);
80918
- dashed = zim.Pick.choose(dashed);
80919
-
80920
- var size = frame.width;
80921
- var mobile = zim.mobile();
80922
-
80923
- // 2D Homography, Matthew Arcus, mla, 2022 - reduced by Dr Abstract 2026
80924
- // https://www.shadertoy.com/view/7dXfDH
80925
- var frag = "uniform vec2 a;uniform vec2 b;uniform vec2 c;uniform vec2 d;uniform bool plane;uniform bool fade;\n";
80926
- frag += "#define map(screenpos) ((2.0*(screenpos)-iResolution.xy)/iResolution.y)\n";
80927
- frag += "mat3 rproject(vec3 p0, vec3 p1, vec3 p2, vec3 p3) {mat3 m = inverse(mat3(p0,p1,p2));vec3 t = 1.0/(m*p3);return mat3(t[0],0,0, 0,t[1],0, 0,0,t[2])*m;}mat3 rproject(vec2 p0, vec2 p1, vec2 p2, vec2 p3) {return rproject(vec3(p0,1),vec3(p1,1),vec3(p2,1),vec3(p3,1));}\n";
80928
- frag += "void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n";
80929
- frag += "vec2 p = map(fragCoord.xy);float px = fwidth(p.x);vec2 p0 = d;vec2 p1 = a;vec2 p2 = b;vec2 p3 = c;mat3 m = rproject(p0,p1,p2,p3);mat3 n = rproject(vec2(0,0),vec2(0,1),vec2(1,1),vec2(1,0));mat3 t = inverse(n)*m;vec3 uv = t*vec3(p,1);float z = uv.z;uv /= z;mat3x2 tt = transpose(mat2x3(t));vec2 nx0 = tt*vec3(0,1,0);vec2 ny0 = tt*vec3(1,0,0);vec2 nx1 = tt*vec3(0,1,-1);vec2 ny1 = tt*vec3(1,0,-1);vec3 color = pow(texture(iChannel0,uv.xy).xyz,vec3(2.2));vec4 final;if (!(uv.x >= 0.0 && uv.x <= 1.0 && uv.y >= 0.0 && uv.y <= 1.0) && !plane) {final = vec4(0.0,0.0,0.0,0.0);} else {color = pow(color, vec3(0.4545)); if (fade && plane) {color *= min(2.5*z*z,1.0);} if (plane) final = vec4(color,min(2.5*z*z,texture(iChannel0,uv.xy).a)); else final = vec4(color,texture(iChannel0,uv.xy).a);} fragColor = final;}";
81473
+ // PICK
81474
+ var oa = remember(obj, borderColor, borderWidth, dashed);
81475
+ this.veeObj = {obj: oa[0], borderColor: oa[1], borderWidth: oa[2], dashed: oa[3]};
81476
+ function remember() {return arguments;}
81477
+ obj = zim.Pick.choose(obj);
81478
+ borderColor = zim.Pick.choose(borderColor);
81479
+ borderWidth = zim.Pick.choose(borderWidth);
81480
+ dashed = zim.Pick.choose(dashed);
81481
+
81482
+ var mobile = zim.mobile();
80930
81483
 
80931
- this.zimContainer_constructor(size, size, null, null, false);
80932
- this.type = "Perspective";
80933
-
80934
- // MONITOR
80935
- var mID = this.mID = "z~"+(DS.monitor===false?"-":this.type);
81484
+ var frag = "uniform vec2 a; uniform vec2 b; uniform vec2 c; uniform vec2 d;\n";
81485
+ frag += "uniform float plane;\nuniform float fade;\n";
81486
+ frag += "uniform float shape;\nuniform float feather;\nuniform float aspect;\nuniform float useMaskTex;\n";
81487
+ frag += "uniform float passthrough;\nuniform float passthroughScale;\nuniform vec2 passthroughCenter;\nuniform vec2 passthroughShift;\nuniform vec2 assetNormSize;\n";
81488
+ frag += "#define map(screenpos) ((2.0*(screenpos)-iResolution.xy)/iResolution.y)\n";
81489
+ frag += "mat3 rproject(vec3 p0, vec3 p1, vec3 p2, vec3 p3) {\n";
81490
+ frag += " mat3 m = inverse(mat3(p0,p1,p2));\n";
81491
+ frag += " vec3 t = vec3(1.0)/(m*p3);\n";
81492
+ frag += " return mat3(t.x,0.0,0.0, 0.0,t.y,0.0, 0.0,0.0,t.z)*m;\n";
81493
+ frag += "}\n";
81494
+ frag += "mat3 rproject(vec2 p0, vec2 p1, vec2 p2, vec2 p3) {\n";
81495
+ frag += " return rproject(vec3(p0,1.0), vec3(p1,1.0), vec3(p2,1.0), vec3(p3,1.0));\n";
81496
+ frag += "}\n";
81497
+ frag += "void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n";
81498
+ frag += " vec2 p = map(fragCoord.xy);\n";
81499
+ frag += " mat3 m = rproject(d, a, b, c);\n";
81500
+ frag += " mat3 n = rproject(vec2(0.0,0.0), vec2(0.0,1.0), vec2(1.0,1.0), vec2(1.0,0.0));\n";
81501
+ frag += " mat3 t = inverse(n)*m;\n";
81502
+ frag += " vec3 uv = t*vec3(p, 1.0);\n";
81503
+ frag += " float z = uv.z;\n";
81504
+ frag += " // 1. Horizon & In-Bounds Checks\n";
81505
+ frag += " if (plane > 0.5) {\n";
81506
+ frag += " if (z <= 0.0) { fragColor = vec4(0.0); return; }\n";
81507
+ frag += " }\n";
81508
+ frag += " uv /= z;\n";
81509
+ frag += " bool inBounds = (uv.x >= 0.0 && uv.x <= 1.0 && uv.y >= 0.0 && uv.y <= 1.0);\n";
81510
+ frag += " if (!inBounds && plane < 0.5) {\n";
81511
+ frag += " fragColor = vec4(0.0);\n";
81512
+ frag += " return;\n";
81513
+ frag += " }\n";
81514
+ frag += " // 2. Tile UV (Repeats across plane with fract)\n";
81515
+ frag += " vec2 tileUV = (plane > 0.5) ? fract(uv.xy) : uv.xy;\n";
81516
+ frag += " vec2 texUV;\n";
81517
+ frag += " if (passthrough > 0.5) {\n";
81518
+ frag += " vec2 pScale = max(vec2(0.0001), assetNormSize * passthroughScale);\n";
81519
+ frag += " texUV = (p - passthroughCenter - passthroughShift) / pScale + vec2(0.5);\n";
81520
+ frag += " if (texUV.x < 0.0 || texUV.x > 1.0 || texUV.y < 0.0 || texUV.y > 1.0) {\n";
81521
+ frag += " fragColor = vec4(0.0);\n";
81522
+ frag += " return;\n";
81523
+ frag += " }\n";
81524
+ frag += " } else {\n";
81525
+ frag += " texUV = tileUV;\n";
81526
+ frag += " }\n";
81527
+ frag += " vec4 texColor = texture(iChannel0, texUV);\n";
81528
+ frag += " vec3 color = pow(texColor.rgb, vec3(2.2));\n";
81529
+ frag += " color = pow(color, vec3(0.4545));\n";
81530
+ frag += " float alpha = texColor.a;\n";
81531
+ frag += " // 3. Circle / Ellipse Feather (applied to tileUV)\n";
81532
+ frag += " if (shape > 0.5) {\n";
81533
+ frag += " vec2 centerCoord = (tileUV - vec2(0.5)) * 2.0;\n";
81534
+ frag += " if (shape < 1.5) {\n";
81535
+ frag += " if (aspect >= 1.0) centerCoord.x *= aspect;\n";
81536
+ frag += " else centerCoord.y /= aspect;\n";
81537
+ frag += " }\n";
81538
+ frag += " float dist = length(centerCoord);\n";
81539
+ frag += " float f = max(feather, 0.001);\n";
81540
+ frag += " float circleAlpha = 1.0 - smoothstep(1.0 - f, 1.0, dist);\n";
81541
+ frag += " color *= circleAlpha;\n";
81542
+ frag += " alpha *= circleAlpha;\n";
81543
+ frag += " if (alpha <= 0.0) { fragColor = vec4(0.0); return; }\n";
81544
+ frag += " }\n";
81545
+ frag += " // 4. Texture Mask (Blob) Feather (applied to tileUV)\n";
81546
+ frag += " if (useMaskTex > 0.5) {\n";
81547
+ frag += " float maskAlpha = texture(iChannel1, tileUV).a;\n";
81548
+ frag += " if (feather > 0.001) {\n";
81549
+ frag += " float spread = feather * 0.03;\n";
81550
+ frag += " float total = maskAlpha * 2.0;\n";
81551
+ frag += " total += texture(iChannel1, tileUV + vec2(spread, 0.0)).a;\n";
81552
+ frag += " total += texture(iChannel1, tileUV - vec2(spread, 0.0)).a;\n";
81553
+ frag += " total += texture(iChannel1, tileUV + vec2(0.0, spread)).a;\n";
81554
+ frag += " total += texture(iChannel1, tileUV - vec2(0.0, spread)).a;\n";
81555
+ frag += " total += texture(iChannel1, tileUV + vec2(spread, spread) * 0.707).a;\n";
81556
+ frag += " total += texture(iChannel1, tileUV - vec2(spread, spread) * 0.707).a;\n";
81557
+ frag += " total += texture(iChannel1, tileUV + vec2(-spread, spread) * 0.707).a;\n";
81558
+ frag += " total += texture(iChannel1, tileUV + vec2(spread, -spread) * 0.707).a;\n";
81559
+ frag += " maskAlpha = total / 10.0;\n";
81560
+ frag += " }\n";
81561
+ frag += " color *= maskAlpha;\n";
81562
+ frag += " alpha *= maskAlpha;\n";
81563
+ frag += " if (alpha <= 0.0) { fragColor = vec4(0.0); return; }\n";
81564
+ frag += " }\n";
81565
+ frag += " // 5. Standard Quad Edge Feather (applied to tileUV)\n";
81566
+ frag += " if (feather > 0.001 && shape < 0.5 && useMaskTex < 0.5) {\n";
81567
+ frag += " float f = max(feather, 0.001);\n";
81568
+ frag += " float edgeX = smoothstep(0.0, f, tileUV.x) * (1.0 - smoothstep(1.0 - f, 1.0, tileUV.x));\n";
81569
+ frag += " float edgeY = smoothstep(0.0, f, tileUV.y) * (1.0 - smoothstep(1.0 - f, 1.0, tileUV.y));\n";
81570
+ frag += " float edgeAlpha = edgeX * edgeY;\n";
81571
+ frag += " color *= edgeAlpha;\n";
81572
+ frag += " alpha *= edgeAlpha;\n";
81573
+ frag += " if (alpha <= 0.0) { fragColor = vec4(0.0); return; }\n";
81574
+ frag += " }\n";
81575
+ frag += " // 6. Horizon Distance Fade\n";
81576
+ frag += " if (fade > 0.5 && plane > 0.5) {\n";
81577
+ frag += " float distFade = min(2.5 * z * z, 1.0);\n";
81578
+ frag += " color *= distFade;\n";
81579
+ frag += " alpha *= distFade;\n";
81580
+ frag += " }\n";
81581
+ frag += " fragColor = vec4(color, alpha);\n";
81582
+ frag += "}\n";
81583
+
81584
+ this.zimContainer_constructor(size, size, null, null, false);
81585
+ this.type = "Perspective";
81586
+
81587
+ var mID = this.mID = "z~" + (DS.monitor === false ? "-" : this.type);
81588
+ var that = this;
81589
+ var pps = [];
81590
+ var sides = [];
81591
+ var _onTop = onTop;
81592
+ var _overlay = overlay;
81593
+ var _clipping = clipping;
81594
+ var _maskShape = maskShape;
81595
+ var _passthrough = Boolean(passthrough);
81596
+ var _passthroughScale = Number(passthroughScale) || 1;
81597
+ var _passthroughShiftX = Number(passthroughShiftX) || 0;
81598
+ var _passthroughShiftY = Number(passthroughShiftY) || 0;
81599
+ var _passthroughCenter = null;
81600
+
81601
+ var controls = that.sides = new zim.Container(size, size).center(that).mov(size/2, -size/2);
81602
+ obj.center(this);
81603
+
81604
+ var p;
81605
+ if (!points) {
81606
+ var b = obj.getBounds();
81607
+ var tl = obj.localToLocal(b.x, b.y, this);
81608
+ var tr = obj.localToLocal(b.x + b.width, b.y, this);
81609
+ var br = obj.localToLocal(b.x + b.width, b.y + b.height, this);
81610
+ var bl = obj.localToLocal(b.x, b.y + b.height, this);
81611
+ p = [tl, tr, br, bl];
81612
+ } else {
81613
+ p = points;
81614
+ zim.loop(points, function(pp, i) {
81615
+ p[i] = {x: pp.x + size/2, y: pp.y + size/2};
81616
+ });
81617
+ }
80936
81618
 
80937
- var that = this;
81619
+ var blob = that.blob = new zim.Blob({
81620
+ points: [
81621
+ [p[0].x, p[0].y, 0, 0, 0, 0, 0, 0, "none"],
81622
+ [p[1].x, p[1].y, 0, 0, 0, 0, 0, 0, "none"],
81623
+ [p[2].x, p[2].y, 0, 0, 0, 0, 0, 0, "none"],
81624
+ [p[3].x, p[3].y, 0, 0, 0, 0, 0, 0, "none"]
81625
+ ],
81626
+ color: !interactive && !move ? clear : faint,
81627
+ borderColor: interactive ? borderColor : clear,
81628
+ borderWidth: borderWidth,
81629
+ showControls: !interactive ? false : showControls,
81630
+ allowToggle: !interactive ? false : allowToggle,
81631
+ dashed: dashed,
81632
+ move: false,
81633
+ lockControlType: true,
81634
+ editPoints: false
81635
+ }).addTo(this);
81636
+
81637
+ blob.on("controlsshow", function() {
81638
+ blob.borderColor = borderColor;
81639
+ controls.vis(true);
81640
+ zim.loop(sides, function(side) {
81641
+ side.inside.vis(true);
81642
+ });
81643
+ blob.selectionManager.enabled = true;
81644
+ }, null, null, null, null, mID);
81645
+ blob.on("controlshide", function() {
81646
+ blob.borderColor = clear;
81647
+ controls.vis(false);
81648
+ zim.loop(sides, function(side) {
81649
+ side.inside.vis(false);
81650
+ });
81651
+ }, null, null, null, null, mID);
81652
+ if (move) blob.shape.cur();
80938
81653
 
80939
- // seems to maximize on each side if we move half the size and half the -size
80940
- var controls = that.sides = new zim.Container(size, size).center(that).mov(size/2,-size/2);
80941
- obj.center(this);
81654
+ function syncOverlayZ() {
81655
+ if (that.shader && that.shader.tag) {
81656
+ var idx = that.parent ? that.parent.getChildIndex(that) : 0;
81657
+ that.shader.tag.style.zIndex = -100 + idx;
81658
+ if (that.shader.tag.parentNode) {
81659
+ that.shader.tag.parentNode.appendChild(that.shader.tag);
81660
+ }
81661
+ }
81662
+ }
80942
81663
 
80943
- // make it so we can pass in points too as alternative
80944
- // to start with a perspective
80945
- // also have a recordPoints
81664
+ function bringToFront() {
81665
+ if (_onTop) {
81666
+ that.top();
81667
+ syncOverlayZ();
81668
+ }
81669
+ }
80946
81670
 
80947
- var p;
80948
- if (!points) {
80949
- var b = obj.getBounds();
80950
- var tl = obj.localToLocal(b.x, b.y, this);
80951
- var tr = obj.localToLocal(b.x + b.width, b.y, this);
80952
- var br = obj.localToLocal(b.x + b.width, b.y + b.height, this);
80953
- var bl = obj.localToLocal(b.x, b.y + b.height, this);
80954
- p = [tl, tr, br, bl];
81671
+ blob.shape.on("mousedown", function() {
81672
+ activate();
81673
+ bringToFront();
81674
+ zim.loop(sides, function(side) {
81675
+ side.color = black;
81676
+ });
81677
+ blob.selectionManager.enabled = true;
81678
+ if (!move) return;
81679
+ that.diffX = that.x - frame.mouseX;
81680
+ that.diffY = that.y - frame.mouseY;
81681
+ }, null, null, null, null, mID);
81682
+
81683
+ blob.shape.on("pressmove", function() {
81684
+ if (!move) return;
81685
+ that.x = frame.mouseX + that.diffX;
81686
+ that.y = frame.mouseY + that.diffY;
81687
+ }, null, null, null, null, mID);
81688
+
81689
+ that.selectCorner = function(index, state) {
81690
+ if (zot(index)) index = 0;
81691
+ if (index > 3) index = 3;
81692
+ var corner = that.blob.pointControls[index];
81693
+ if (zot(state)) state = true;
81694
+ if (state) {
81695
+ that.blob.selectPoint(index, true, true);
80955
81696
  } else {
80956
- p = points;
80957
- zim.loop(points, function(pp, i) {
80958
- p[i] = {x:pp.x+size/2, y:pp.y+size/2};
80959
- })
81697
+ that.blob.selectPoint(index, false, true);
80960
81698
  }
81699
+ return corner;
81700
+ };
80961
81701
 
80962
- var blob = that.blob = new zim.Blob({
80963
- points: [
80964
- [p[0].x, p[0].y, 0, 0, 0, 0, 0, 0, "none"],
80965
- [p[1].x, p[1].y, 0, 0, 0, 0, 0, 0, "none"],
80966
- [p[2].x, p[2].y, 0, 0, 0, 0, 0, 0, "none"],
80967
- [p[3].x, p[3].y, 0, 0, 0, 0, 0, 0, "none"]],
80968
- color: !interactive&&!move?clear:faint,
80969
- borderColor: interactive?borderColor:clear,
80970
- borderWidth: borderWidth,
80971
- showControls:!interactive?false:showControls,
80972
- allowToggle:!interactive?false:allowToggle,
80973
- dashed:dashed,
80974
- move: false,
80975
- // interactive:interactive, // can;t manipulate points if interactive is false
80976
- lockControlType: true,
80977
- editPoints: false
80978
- }).addTo(this); //.vis(false);
80979
-
80980
- blob.on("controlsshow", function() {
80981
- blob.borderColor = borderColor;
80982
- controls.vis(true);
80983
- zim.loop(sides, function(side) {
80984
- side.inside.vis(true);
80985
- });
80986
- blob.selectionManager.enabled = true;
80987
- }, null, null, null, null, mID);
80988
- blob.on("controlshide", function() {
80989
- blob.borderColor = clear;
80990
- controls.vis(false);
80991
- zim.loop(sides, function(side) {
80992
- side.inside.vis(false);
80993
- });
80994
- }, null, null, null, null, mID);
80995
- if (move) blob.shape.cur()
80996
-
81702
+ that.updateCorner = function(corner, refresh) {
81703
+ if (zot(refresh)) refresh = true;
81704
+ updatePoint(corner);
81705
+ if (refresh) {
81706
+ blob.update();
81707
+ update();
81708
+ }
81709
+ return corner;
81710
+ };
80997
81711
 
80998
- // dragging - fix for within containers
80999
- blob.shape.on("mousedown", function() {
81000
- zim.loop(sides, function(side) {
81001
- side.color = black;
81002
- });
81003
- blob.selectionManager.enabled = true;
81004
- if (!move) return;
81005
- that.diffX = that.x - frame.mouseX;
81006
- that.diffY = that.y - frame.mouseY;
81007
- }, null, null, null, null, mID);
81008
- blob.shape.on("pressmove", function() {
81009
- if (!move) return;
81010
- that.x = frame.mouseX + that.diffX;
81011
- that.y = frame.mouseY + that.diffY;
81012
- }, null, null, null, null, mID);
81712
+ that.deselectPoints = function() {
81713
+ zim.loop(4, function(i) {
81714
+ that.selectCorner(i, false);
81715
+ that.selectSide(i, false);
81716
+ });
81717
+ return that;
81718
+ };
81719
+ that.deselect = that.deselectPoints;
81013
81720
 
81014
- that.selectCorner = function(index, state) {
81015
- if (zot(index)) index = 0;
81016
- if (index > 3) index = 3;
81017
- var corner = that.blob.pointControls[index];
81018
- if (zot(state)) state = true
81019
- if (state) {
81020
- that.blob.selectPoint(index, true, true);
81721
+ that.toggled = showControls && interactive;
81722
+ that.toggle = function(state) {
81723
+ if (!interactive) return that;
81724
+ if (zot(state)) that.toggled = !that.toggled;
81725
+ else that.toggled = state;
81726
+ if (that.toggled) activate();
81727
+ blob.toggle(that.toggled);
81728
+ controls.vis(that.toggled);
81729
+ zim.loop(sides, function(side) {
81730
+ if (side.inside) side.inside.vis(that.toggled);
81731
+ });
81732
+ if (that.toggled) blob.borderColor = borderColor;
81733
+ else blob.borderColor = clear;
81734
+ return that;
81735
+ };
81736
+
81737
+ var sp = [];
81738
+ sp[0] = this.localToLocal(p[0].x, p[0].y, controls);
81739
+ sp[1] = this.localToLocal(p[1].x, p[1].y, controls);
81740
+ sp[2] = this.localToLocal(p[2].x, p[2].y, controls);
81741
+ sp[3] = this.localToLocal(p[3].x, p[3].y, controls);
81742
+
81743
+ var objW = obj.width || (obj.getBounds ? (obj.getBounds() ? obj.getBounds().width : size) : size);
81744
+ var objH = obj.height || (obj.getBounds ? (obj.getBounds() ? obj.getBounds().height : size) : size);
81745
+ var aspect = objW / objH;
81746
+
81747
+ var shapeVal = 0;
81748
+ var useMaskTexVal = 0;
81749
+ if (typeof _maskShape === "string") {
81750
+ if (_maskShape === "circle") shapeVal = 1;
81751
+ else if (_maskShape === "ellipse") shapeVal = 2;
81752
+ } else if (_maskShape) {
81753
+ useMaskTexVal = 1;
81754
+ }
81755
+
81756
+ var initCx = (sp[0].x + sp[1].x + sp[2].x + sp[3].x) / (4 * size);
81757
+ var initCy = 1 - (sp[0].y + sp[1].y + sp[2].y + sp[3].y) / (4 * size);
81758
+
81759
+ var uniforms = that.uniforms = new zim.Uniforms({
81760
+ a: [sp[0].x / size, 1 - sp[0].y / size],
81761
+ b: [sp[1].x / size, 1 - sp[1].y / size],
81762
+ c: [sp[2].x / size, 1 - sp[2].y / size],
81763
+ d: [sp[3].x / size, 1 - sp[3].y / size],
81764
+ plane: plane ? 1 : 0,
81765
+ fade: fade ? 1 : 0,
81766
+ shape: shapeVal,
81767
+ feather: Number(feather) || 0,
81768
+ aspect: aspect || 1.0,
81769
+ useMaskTex: useMaskTexVal,
81770
+ passthrough: _passthrough ? 1 : 0,
81771
+ passthroughScale: _passthroughScale,
81772
+ passthroughCenter: [initCx, initCy],
81773
+ passthroughShift: [_passthroughShiftX / size, -_passthroughShiftY / size],
81774
+ assetNormSize: [objW / size, objH / size]
81775
+ });
81776
+
81777
+ // Align Mask into an exact matching 1:1 buffer container
81778
+ var maskSource = null;
81779
+ var maskContainer = null;
81780
+ function setupMaskSource(mObj) {
81781
+ if (!mObj || typeof mObj === "string") {
81782
+ maskSource = null;
81783
+ return;
81784
+ }
81785
+ if (!maskContainer) {
81786
+ maskContainer = new zim.Container(objW, objH);
81787
+ } else {
81788
+ maskContainer.removeAllChildren();
81789
+ }
81790
+ mObj.loc(objW / 2, objH / 2, maskContainer);
81791
+ maskContainer.cache(0, 0, objW, objH);
81792
+ maskSource = maskContainer;
81793
+
81794
+ if (mObj.on) {
81795
+ var updateMaskTex = function() {
81796
+ if (maskContainer.cacheCanvas) maskContainer.updateCache();
81797
+ if (that.shader) that.shader.replaceChannel(maskContainer, 1, false);
81798
+ };
81799
+ mObj.on("update", updateMaskTex, null, null, null, null, mID);
81800
+ mObj.on("pressmove", updateMaskTex, null, null, null, null, mID);
81801
+ mObj.on("change", updateMaskTex, null, null, null, null, mID);
81802
+ }
81803
+ }
81804
+ if (_maskShape && typeof _maskShape !== "string") setupMaskSource(_maskShape);
81805
+
81806
+ var pc = blob.pointCircles;
81807
+ var pct = blob.pointControls;
81808
+
81809
+ function calculatePassthroughCenter() {
81810
+ pps[0] = pc[0].localToLocal(0, 0, controls);
81811
+ pps[1] = pc[1].localToLocal(0, 0, controls);
81812
+ pps[2] = pc[2].localToLocal(0, 0, controls);
81813
+ pps[3] = pc[3].localToLocal(0, 0, controls);
81814
+ var cx = (pps[0].x + pps[1].x + pps[2].x + pps[3].x) / (4 * size);
81815
+ var cy = 1 - (pps[0].y + pps[1].y + pps[2].y + pps[3].y) / (4 * size);
81816
+ _passthroughCenter = [cx, cy];
81817
+ uniforms.passthroughCenter_A = cx;
81818
+ uniforms.passthroughCenter_B = cy;
81819
+ }
81820
+
81821
+ function buildShader(isOverlay) {
81822
+ if (that.shader) {
81823
+ that.shader.removeFrom();
81824
+ that.shader.dispose();
81825
+ that.shader = null;
81826
+ }
81827
+
81828
+ if (isOverlay) {
81829
+ var p0 = pc[0].localToGlobal(0, 0);
81830
+ var p1 = pc[1].localToGlobal(0, 0);
81831
+ var p2 = pc[2].localToGlobal(0, 0);
81832
+ var p3 = pc[3].localToGlobal(0, 0);
81833
+
81834
+ var minX = Math.min(p0.x, p1.x, p2.x, p3.x);
81835
+ var minY = Math.min(p0.y, p1.y, p2.y, p3.y);
81836
+ var maxX = Math.max(p0.x, p1.x, p2.x, p3.x);
81837
+ var maxY = Math.max(p0.y, p1.y, p2.y, p3.y);
81838
+
81839
+ var stageW = frame.width;
81840
+ var stageH = frame.height;
81841
+ var cMinX, cMinY, cMaxX, cMaxY;
81842
+
81843
+ if (_clipping) {
81844
+ cMinX = Math.max(0, Math.floor(minX));
81845
+ cMinY = Math.max(0, Math.floor(minY));
81846
+ cMaxX = Math.min(stageW, Math.ceil(maxX));
81847
+ cMaxY = Math.min(stageH, Math.ceil(maxY));
81021
81848
  } else {
81022
- that.blob.selectPoint(index, false, true);
81023
- }
81024
- return corner;
81849
+ cMinX = Math.floor(minX);
81850
+ cMinY = Math.floor(minY);
81851
+ cMaxX = Math.ceil(maxX);
81852
+ cMaxY = Math.ceil(maxY);
81853
+ }
81854
+
81855
+ var cW = Math.max(2, cMaxX - cMinX);
81856
+ var cH = Math.max(2, cMaxY - cMinY);
81857
+
81858
+ function toP(pt) {
81859
+ var lx = pt.x - cMinX;
81860
+ var ly = pt.y - cMinY;
81861
+ var gx = (2.0 * lx - cW) / cH;
81862
+ var gy = (2.0 * (cH - ly) - cH) / cH;
81863
+ return [gx, gy];
81864
+ }
81865
+
81866
+ var g0 = toP(p0);
81867
+ var g1 = toP(p1);
81868
+ var g2 = toP(p2);
81869
+ var g3 = toP(p3);
81870
+
81871
+ uniforms.a_A = g0[0]; uniforms.a_B = g0[1];
81872
+ uniforms.b_A = g1[0]; uniforms.b_B = g1[1];
81873
+ uniforms.c_A = g2[0]; uniforms.c_B = g2[1];
81874
+ uniforms.d_A = g3[0]; uniforms.d_B = g3[1];
81875
+
81876
+ var shW = Math.round(cW * resolution);
81877
+ var shH = Math.round(cH * resolution);
81878
+
81879
+ var locInParent = that.globalToLocal(cMinX, cMinY);
81880
+
81881
+ that.shader = new zim.ShaderOverlay({
81882
+ width: shW,
81883
+ height: shH,
81884
+ fragment: frag,
81885
+ uniforms: uniforms,
81886
+ channel0: obj,
81887
+ channel1: maskSource,
81888
+ dynamic: dynamic,
81889
+ dynamic1: false
81890
+ })
81891
+ .sca(1 / resolution)
81892
+ .addTo(that, 0)
81893
+ .loc(locInParent.x, locInParent.y);
81894
+
81895
+ syncOverlayZ();
81896
+ } else {
81897
+ var shaderW = Math.round(2 * size * resolution);
81898
+ var shaderH = Math.round(2 * size * resolution);
81899
+
81900
+ that.shader = new zim.Shader({
81901
+ width: shaderW,
81902
+ height: shaderH,
81903
+ fragment: frag,
81904
+ uniforms: uniforms,
81905
+ channel0: obj,
81906
+ channel1: maskSource,
81907
+ dynamic: dynamic,
81908
+ dynamic1: false
81909
+ })
81910
+ .sca(1 / resolution)
81911
+ .addTo(that, 0)
81912
+ .mov(-size)
81913
+ .mov(size/2, -size/2);
81914
+
81915
+ if (sides && sides.length > 0) update();
81025
81916
  }
81917
+ }
81026
81918
 
81027
- that.updateCorner = function(corner, refresh) {
81028
- if (zot(refresh)) refresh = true;
81029
- updatePoint(corner);
81030
- if (refresh) {
81031
- blob.update();
81032
- update();
81033
- }
81034
- return corner;
81035
- }
81919
+ buildShader(_overlay);
81036
81920
 
81037
- that.deselectPoints = function() {
81038
- zim.loop(4, function(i) {
81039
- that.selectCorner(i, false);
81040
- that.selectSide(i, false);
81041
- });
81042
- return that;
81921
+ obj.removeFrom();
81922
+
81923
+ Object.defineProperty(this, "maskShape", {
81924
+ get: function() {
81925
+ return _maskShape;
81926
+ },
81927
+ set: function(value) {
81928
+ _maskShape = value;
81929
+ if (typeof value === "string") {
81930
+ if (value === "circle") uniforms.shape = 1;
81931
+ else if (value === "ellipse") uniforms.shape = 2;
81932
+ else uniforms.shape = 0;
81933
+ uniforms.useMaskTex = 0;
81934
+ } else if (value) {
81935
+ uniforms.shape = 0;
81936
+ uniforms.useMaskTex = 1;
81937
+ setupMaskSource(value);
81938
+ if (that.shader) that.shader.replaceChannel(maskContainer, 1, false);
81939
+ }
81043
81940
  }
81941
+ });
81044
81942
 
81045
- that.toggled = showControls && interactive;
81046
- that.toggle = function(state) {
81047
- if (!interactive) return that;
81048
- if (zot(state)) that.toggled = !that.toggled;
81049
- else that.toggled = state;
81050
- blob.toggle(that.toggled);
81051
- controls.vis(that.toggled);
81052
- if (that.toggled) blob.borderColor = borderColor;
81053
- else blob.borderColor = clear;
81054
- return that;
81943
+ Object.defineProperty(this, "feather", {
81944
+ get: function() {
81945
+ return uniforms.feather;
81946
+ },
81947
+ set: function(value) {
81948
+ uniforms.feather = Number(value) || 0;
81055
81949
  }
81950
+ });
81056
81951
 
81952
+ Object.defineProperty(this, "passthrough", {
81953
+ get: function() {
81954
+ return _passthrough;
81955
+ },
81956
+ set: function(value) {
81957
+ _passthrough = Boolean(value);
81958
+ uniforms.passthrough = _passthrough ? 1 : 0;
81959
+ if (_passthrough) calculatePassthroughCenter();
81960
+ }
81961
+ });
81057
81962
 
81058
- var sp = [];
81059
- sp[0] = this.localToLocal(p[0].x, p[0].y, controls);
81060
- sp[1] = this.localToLocal(p[1].x, p[1].y, controls);
81061
- sp[2] = this.localToLocal(p[2].x, p[2].y, controls);
81062
- sp[3] = this.localToLocal(p[3].x, p[3].y, controls);
81063
- var uniforms = that.uniforms = new zim.Uniforms({
81064
- a: [sp[0].x / size, 1-sp[0].y / size], // top left
81065
- b: [sp[1].x / size, 1-sp[1].y / size], // top right
81066
- c: [sp[2].x / size, 1-sp[2].y / size], // bottom right
81067
- d: [sp[3].x / size, 1-sp[3].y / size], // bottom left
81068
- plane: plane,
81069
- fade: fade
81070
- });
81071
- that.shader = new zim.Shader({
81072
- width: 2*size,
81073
- height:2*size,
81074
- fragment: frag,
81075
- uniforms: uniforms,
81076
- channel0: obj,
81077
- dynamic: dynamic
81078
- })
81079
- .addTo(this, 0)
81080
- .mov(-size)
81081
- // seems to maximize on each side if we move half the size and half the -size
81082
- .mov(size/2,-size/2);
81963
+ Object.defineProperty(this, "passthroughScale", {
81964
+ get: function() {
81965
+ return _passthroughScale;
81966
+ },
81967
+ set: function(value) {
81968
+ _passthroughScale = Number(value) || 1;
81969
+ uniforms.passthroughScale = _passthroughScale;
81970
+ }
81971
+ });
81083
81972
 
81084
- obj.removeFrom();
81085
- var pc = blob.pointCircles;
81086
- var pct = blob.pointControls;
81087
-
81088
- that.update = function() {
81089
- blob.update();
81090
- update();
81973
+ Object.defineProperty(this, "passthroughShiftX", {
81974
+ get: function() {
81975
+ return _passthroughShiftX;
81976
+ },
81977
+ set: function(value) {
81978
+ _passthroughShiftX = Number(value) || 0;
81979
+ uniforms.passthroughShift_A = _passthroughShiftX / size;
81091
81980
  }
81981
+ });
81092
81982
 
81093
- // ~~~~~~~~~~~~~~~~~~~~~~
81094
- // MAKE SIDES
81983
+ Object.defineProperty(this, "passthroughShiftY", {
81984
+ get: function() {
81985
+ return _passthroughShiftY;
81986
+ },
81987
+ set: function(value) {
81988
+ _passthroughShiftY = Number(value) || 0;
81989
+ uniforms.passthroughShift_B = -_passthroughShiftY / size;
81990
+ }
81991
+ });
81095
81992
 
81096
- that.selectSide = function(index, state) {
81097
- if (zot(index)) index = 0;
81098
- if (index > 3) index = 3;
81099
- var side = sides[index];
81100
- if (zot(state)) state = true
81101
- if (state) {
81102
- blob.selectionManager.enabled = false;
81103
- side.color = white;
81104
- side.aX = side.inside.x-side.pctA.x;
81105
- side.aY = side.inside.y-side.pctA.y;
81106
- side.bX = side.inside.x-side.pctB.x;
81107
- side.bY = side.inside.y-side.pctB.y;
81993
+ Object.defineProperty(this, "overlay", {
81994
+ get: function() {
81995
+ return _overlay;
81996
+ },
81997
+ set: function(value) {
81998
+ value = Boolean(value);
81999
+ if (value === _overlay && that.shader) return;
82000
+ _overlay = value;
82001
+ if (_overlay) {
82002
+ blob.vis(false);
82003
+ controls.vis(false);
82004
+ buildShader(true);
81108
82005
  } else {
81109
- side.color = black;
81110
- var notSelected = zim.loop(sides, function(s) {
81111
- if (s.color == white) return false;
81112
- });
81113
- if (notSelected) blob.selectionManager.enabled = true;
82006
+ buildShader(false);
82007
+ if (interactive && that.toggled) {
82008
+ blob.vis(true);
82009
+ controls.vis(true);
82010
+ blob.borderColor = borderColor;
82011
+ }
81114
82012
  }
81115
- return side;
81116
82013
  }
81117
-
81118
- that.updateSide = function(side, refresh) {
81119
- if (zot(side.aX)) return;
81120
- if (zot(refresh)) refresh = true;
81121
- side.inside.loc(side,null,blob);
81122
- side.pctA.x = side.inside.x - side.aX;
81123
- side.pctA.y = side.inside.y - side.aY;
81124
- side.pctB.x = side.inside.x - side.bX;
81125
- side.pctB.y = side.inside.y - side.bY;
81126
- if (refresh) {
81127
- blob.update();
81128
- update();
81129
- }
81130
- return side;
81131
- }
82014
+ });
81132
82015
 
81133
- var sidePoints = [
81134
- [pct[0], pct[1], pc[0], pc[1]],
81135
- [pct[1], pct[2], pc[1], pc[2]],
81136
- [pct[2], pct[3], pc[2], pc[3]],
81137
- [pct[3], pct[0], pc[3], pc[0]]
81138
- ];
81139
-
81140
- var sides = [];
81141
- zim.loop(4, function(i) {
81142
- var side = new zim.Circle(7*(mobile?1.5:1),black,red,2).addTo(controls).drag();
81143
- side.update = true;
81144
- // pc - pointCircles (second and third index)
81145
- side.pcA = sidePoints[i][2];
81146
- side.pcB = sidePoints[i][3];
81147
- // pct - pointControls (the rest in this function)
81148
- var pctA = side.pctA = sidePoints[i][0];
81149
- var pctB = side.pctB = sidePoints[i][1];
81150
- pctA.sideA = side;
81151
- pctB.sideB = side;
81152
-
81153
- side.inside = new zim.Circle(8*(mobile?1.5:1),black);
81154
- sides.push(side);
82016
+ Object.defineProperty(this, "clipping", {
82017
+ get: function() {
82018
+ return _clipping;
82019
+ },
82020
+ set: function(value) {
82021
+ _clipping = Boolean(value);
82022
+ if (_overlay) buildShader(true);
82023
+ }
82024
+ });
81155
82025
 
81156
- setTimeout(function() {
81157
- side.aX = side.inside.x-side.pctA.x;
81158
- side.aY = side.inside.y-side.pctA.y;
81159
- side.bX = side.inside.x-side.pctB.x;
81160
- side.bY = side.inside.y-side.pctB.y;
81161
- },60);
81162
-
81163
- // MID MOVES
81164
- side.on("mousedown", function() {
81165
- that.selectSide(i);
81166
- }, null, null, null, null, mID);
81167
- side.on("pressmove", function() {
81168
- that.updateSide(side);
81169
- }, null, null, null, null, mID);
81170
- if (!interactive){
81171
- side.vis(false);
81172
- side.inside.vis(false);
81173
- }
81174
- });
82026
+ Object.defineProperty(this, "onTop", {
82027
+ get: function() {
82028
+ return _onTop;
82029
+ },
82030
+ set: function(value) {
82031
+ _onTop = Boolean(value);
82032
+ }
82033
+ });
81175
82034
 
81176
- if (!showControls) {
81177
- blob.borderColor = clear;
81178
- controls.vis(false);
81179
- zim.loop(sides, function(side) {
81180
- side.inside.vis(false);
82035
+ if (_overlay) {
82036
+ blob.vis(false);
82037
+ controls.vis(false);
82038
+ }
82039
+
82040
+ that.update = function() {
82041
+ blob.update();
82042
+ update();
82043
+ };
82044
+
82045
+ that.selectSide = function(index, state) {
82046
+ if (zot(index)) index = 0;
82047
+ if (index > 3) index = 3;
82048
+ var side = sides[index];
82049
+ if (zot(state)) state = true;
82050
+ if (state) {
82051
+ blob.selectionManager.enabled = false;
82052
+ side.color = white;
82053
+ side.aX = side.inside.x - side.pctA.x;
82054
+ side.aY = side.inside.y - side.pctA.y;
82055
+ side.bX = side.inside.x - side.pctB.x;
82056
+ side.bY = side.inside.y - side.pctB.y;
82057
+ } else {
82058
+ side.color = black;
82059
+ var notSelected = zim.loop(sides, function(s) {
82060
+ if (s.color == white) return false;
81181
82061
  });
82062
+ if (notSelected) blob.selectionManager.enabled = true;
81182
82063
  }
81183
-
81184
-
81185
- blob.selectionManager.multipleKey = null;
81186
- blob.on("update", function() {
81187
- // HANDLE KEY ARROWS
81188
- if (blob.selectionManager.currentSet && blob.selectionManager.currentSet.selections) {
81189
- var s = blob.selectionManager.currentSet.selections;
81190
- if (s.length > 0) {
81191
- zim.loop(s, function(index) {
81192
- updatePoint(pct[index]);
81193
- });
81194
- blob.update();
81195
- }
81196
- }
81197
- }, null, null, null, null, mID);
82064
+ return side;
82065
+ };
82066
+
82067
+ that.updateSide = function(side, refresh) {
82068
+ if (zot(side.aX)) return;
82069
+ if (zot(refresh)) refresh = true;
82070
+ side.inside.loc(side, null, blob);
82071
+ side.pctA.x = side.inside.x - side.aX;
82072
+ side.pctA.y = side.inside.y - side.aY;
82073
+ side.pctB.x = side.inside.x - side.bX;
82074
+ side.pctB.y = side.inside.y - side.bY;
82075
+ if (refresh) {
82076
+ blob.update();
82077
+ update();
82078
+ }
82079
+ return side;
82080
+ };
81198
82081
 
81199
- that.keyDE = frame.on("keydown", function(e) {
81200
- if (e.keyCode >= 37 && e.keyCode <= 40) {
81201
- var x = 0;
81202
- var y = 0;
81203
- if (e.keyCode == 37) x -= blob.selectionManager.shiftKey?10:1;
81204
- else if (e.keyCode == 39) x += blob.selectionManager.shiftKey?10:1;
81205
- else if (e.keyCode == 38) y -= blob.selectionManager.shiftKey?10:1;
81206
- else if (e.keyCode == 40) y += blob.selectionManager.shiftKey?10:1;
81207
- var changed = false; // batch updates if multiple sides
81208
-
81209
- zim.loop(sides, function(side) {
81210
- if (side.color==white) {
81211
- side.update = false;
81212
- changed = true;
81213
- side.x += x;
81214
- side.y += y;
81215
- that.updateSide(side, false);
81216
- }
81217
- })
81218
- if (changed) {
81219
- blob.selectionManager.enabled = false;
81220
- blob.update();
81221
- update();
81222
- }
81223
- }
81224
- }, null, null, null, null, mID);
82082
+ var sidePoints = [
82083
+ [pct[0], pct[1], pc[0], pc[1]],
82084
+ [pct[1], pct[2], pc[1], pc[2]],
82085
+ [pct[2], pct[3], pc[2], pc[3]],
82086
+ [pct[3], pct[0], pc[3], pc[0]]
82087
+ ];
82088
+
82089
+ zim.loop(4, function(i) {
82090
+ var side = new zim.Circle(7 * (mobile ? 1.5 : 1), black, red, 2).addTo(controls).drag();
82091
+ side.update = true;
82092
+ side.pcA = sidePoints[i][2];
82093
+ side.pcB = sidePoints[i][3];
82094
+ var pctA = side.pctA = sidePoints[i][0];
82095
+ var pctB = side.pctB = sidePoints[i][1];
82096
+ pctA.sideA = side;
82097
+ pctB.sideB = side;
82098
+
82099
+ side.inside = new zim.Circle(8 * (mobile ? 1.5 : 1), black);
82100
+ sides.push(side);
81225
82101
 
81226
- that.keyUE = frame.on("keyup", function(e) {
81227
- if (e.keyCode >= 37 && e.keyCode <= 40) {
81228
- zim.loop(sides, function(side) {
81229
- side.update = true;
81230
- })
81231
- }
82102
+ setTimeout(function() {
82103
+ side.aX = side.inside.x - side.pctA.x;
82104
+ side.aY = side.inside.y - side.pctA.y;
82105
+ side.bX = side.inside.x - side.pctB.x;
82106
+ side.bY = side.inside.y - side.pctB.y;
82107
+ }, 60);
82108
+
82109
+ side.on("mousedown", function() {
82110
+ activate();
82111
+ bringToFront();
82112
+ that.selectSide(i);
81232
82113
  }, null, null, null, null, mID);
82114
+ side.on("pressmove", function() {
82115
+ that.updateSide(side);
82116
+ }, null, null, null, null, mID);
82117
+ if (!interactive || _overlay) {
82118
+ side.vis(false);
82119
+ side.inside.vis(false);
82120
+ }
82121
+ });
81233
82122
 
81234
- zim.loop(pct, function(point, i) {
81235
- point.on("mousedown", function() {
81236
- if (point.sideA.color==white) point.sideA.update = false;
81237
- if (point.sideB.color==white) point.sideB.update = false;
81238
- }, null, null, null, null, mID)
81239
- point.on("pressmove", function() {
81240
- updatePoint(point);
81241
- }, null, null, null, null, mID);
81242
-
81243
- point.on("pressup", function() {
81244
- zim.loop(sides, function(side, i) {
81245
- if (side.color == white) {
81246
- zim.timeout(.1, function() {
81247
- side.aX = side.inside.x-side.pctA.x;
81248
- side.aY = side.inside.y-side.pctA.y;
81249
- side.bX = side.inside.x-side.pctB.x;
81250
- side.bY = side.inside.y-side.pctB.y;
81251
- });
81252
- }
81253
- });
81254
- point.sideA.update = true;
81255
- point.sideB.update = true;
81256
- }, null, null, null, null, mID);
82123
+ if (!showControls && !_overlay) {
82124
+ blob.borderColor = clear;
82125
+ controls.vis(false);
82126
+ zim.loop(sides, function(side) {
82127
+ side.inside.vis(false);
81257
82128
  });
82129
+ }
81258
82130
 
81259
- function updatePoint(point) {
81260
- var sideA = point.sideA;
81261
- var sideB = point.sideB;
81262
- if (sideA.color==white || sideB.color==white) {
81263
- // MIRRORS
81264
- var p;
81265
- if (sideA.color==white) {
81266
- p = sideA.pcA.localToLocal(0,0,controls); // note pointCircle (pcA) not pointControl (pctA)
81267
- sideA.pctB.x = sideA.inside.x - (p.x-sideA.x); // note pointControl (pctB) not pointCircle (pcB)
81268
- sideA.pctB.y = sideA.inside.y - (p.y-sideA.y);
81269
- }
81270
- if (sideB.color==white) {
81271
- p = sideB.pcB.localToLocal(0,0,controls);
81272
- sideB.pctA.x = sideB.inside.x - (p.x-sideB.x); // change the opposite point to the dragged point
81273
- sideB.pctA.y = sideB.inside.y - (p.y-sideB.y);
81274
- }
82131
+ blob.selectionManager.multipleKey = null;
82132
+ blob.on("update", function() {
82133
+ if (blob.selectionManager.currentSet && blob.selectionManager.currentSet.selections) {
82134
+ var s = blob.selectionManager.currentSet.selections;
82135
+ if (s.length > 0) {
82136
+ zim.loop(s, function(index) {
82137
+ updatePoint(pct[index]);
82138
+ });
82139
+ blob.update();
81275
82140
  }
81276
82141
  }
82142
+ }, null, null, null, null, mID);
81277
82143
 
81278
-
81279
- var pps = [];
81280
- function update() {
81281
- pps[0] = pc[0].localToLocal(0, 0, controls);
81282
- pps[1] = pc[1].localToLocal(0, 0, controls);
81283
- pps[2] = pc[2].localToLocal(0, 0, controls);
81284
- pps[3] = pc[3].localToLocal(0, 0, controls);
81285
- uniforms.a_A = pps[0].x / size;
81286
- uniforms.a_B = 1-pps[0].y / size;
81287
- uniforms.b_A = pps[1].x / size;
81288
- uniforms.b_B = 1-pps[1].y / size;
81289
- uniforms.c_A = pps[2].x / size;
81290
- uniforms.c_B = 1-pps[2].y / size;
81291
- uniforms.d_A = pps[3].x / size;
81292
- uniforms.d_B = 1-pps[3].y / size;
81293
-
81294
- var ps = [
81295
- [pps[0], pps[1]],
81296
- [pps[1], pps[2]],
81297
- [pps[2], pps[3]],
81298
- [pps[3], pps[0]]
81299
- ];
81300
- zim.loop(sides, function(side,i) {
81301
- // KEEP SIDES CENTERED
81302
- if (side.update) {
81303
- var pA = ps[i][0];
81304
- var pB = ps[i][1];
81305
- side.x = pB.x+(pA.x-pB.x)/2;
81306
- side.y = pB.y+(pA.y-pB.y)/2;
81307
- side.inside.loc(side,null,blob);
82144
+ that.keyDE = frame.on("keydown", function(e) {
82145
+ if (_overlay) return;
82146
+ if (e.keyCode >= 37 && e.keyCode <= 40) {
82147
+ var x = 0;
82148
+ var y = 0;
82149
+ if (e.keyCode == 37) x -= blob.selectionManager.shiftKey ? 10 : 1;
82150
+ else if (e.keyCode == 39) x += blob.selectionManager.shiftKey ? 10 : 1;
82151
+ else if (e.keyCode == 38) y -= blob.selectionManager.shiftKey ? 10 : 1;
82152
+ else if (e.keyCode == 40) y += blob.selectionManager.shiftKey ? 10 : 1;
82153
+ var changed = false;
82154
+
82155
+ zim.loop(sides, function(side) {
82156
+ if (side.color == white) {
82157
+ side.update = false;
82158
+ changed = true;
82159
+ side.x += x;
82160
+ side.y += y;
82161
+ that.updateSide(side, false);
81308
82162
  }
81309
- });
81310
-
82163
+ });
82164
+ if (changed) {
82165
+ blob.selectionManager.enabled = false;
82166
+ blob.update();
82167
+ update();
82168
+ }
81311
82169
  }
81312
- update();
81313
- controls.top();
82170
+ }, null, null, null, null, mID);
81314
82171
 
81315
- if (interactive) {
81316
- blob.on("update", update, null, null, null, null, mID);
81317
- blob.on("pressmove", update, null, null, null, null, mID);
82172
+ that.keyUE = frame.on("keyup", function(e) {
82173
+ if (_overlay) return;
82174
+ if (e.keyCode >= 37 && e.keyCode <= 40) {
82175
+ zim.loop(sides, function(side) {
82176
+ side.update = true;
82177
+ });
81318
82178
  }
82179
+ }, null, null, null, null, mID);
81319
82180
 
81320
- Object.defineProperty(this, "obj", {
81321
- get : function() {
81322
- return obj;
81323
- },
81324
- set : function(value) {
81325
- obj = value;
81326
- that.shader.replaceChannel(value, 0);
82181
+ zim.loop(pct, function(point, i) {
82182
+ point.on("mousedown", function() {
82183
+ activate();
82184
+ bringToFront();
82185
+ if (point.sideA.color == white) point.sideA.update = false;
82186
+ if (point.sideB.color == white) point.sideB.update = false;
82187
+ }, null, null, null, null, mID);
82188
+ point.on("pressmove", function() {
82189
+ updatePoint(point);
82190
+ }, null, null, null, null, mID);
82191
+
82192
+ point.on("pressup", function() {
82193
+ zim.loop(sides, function(side, i) {
82194
+ if (side.color == white) {
82195
+ zim.timeout(.1, function() {
82196
+ side.aX = side.inside.x - side.pctA.x;
82197
+ side.aY = side.inside.y - side.pctA.y;
82198
+ side.bX = side.inside.x - side.pctB.x;
82199
+ side.bY = side.inside.y - side.pctB.y;
82200
+ });
82201
+ }
82202
+ });
82203
+ point.sideA.update = true;
82204
+ point.sideB.update = true;
82205
+ }, null, null, null, null, mID);
82206
+ });
82207
+
82208
+ function updatePoint(point) {
82209
+ var sideA = point.sideA;
82210
+ var sideB = point.sideB;
82211
+ if (sideA.color == white || sideB.color == white) {
82212
+ var p;
82213
+ if (sideA.color == white) {
82214
+ p = sideA.pcA.localToLocal(0, 0, controls);
82215
+ sideA.pctB.x = sideA.inside.x - (p.x - sideA.x);
82216
+ sideA.pctB.y = sideA.inside.y - (p.y - sideA.y);
82217
+ }
82218
+ if (sideB.color == white) {
82219
+ p = sideB.pcB.localToLocal(0, 0, controls);
82220
+ sideB.pctA.x = sideB.inside.x - (p.x - sideB.x);
82221
+ sideB.pctA.y = sideB.inside.y - (p.y - sideB.y);
82222
+ }
82223
+ }
82224
+ }
82225
+
82226
+ function update() {
82227
+ if (_overlay) return;
82228
+ pps[0] = pc[0].localToLocal(0, 0, controls);
82229
+ pps[1] = pc[1].localToLocal(0, 0, controls);
82230
+ pps[2] = pc[2].localToLocal(0, 0, controls);
82231
+ pps[3] = pc[3].localToLocal(0, 0, controls);
82232
+ uniforms.a_A = pps[0].x / size;
82233
+ uniforms.a_B = 1 - pps[0].y / size;
82234
+ uniforms.b_A = pps[1].x / size;
82235
+ uniforms.b_B = 1 - pps[1].y / size;
82236
+ uniforms.c_A = pps[2].x / size;
82237
+ uniforms.c_B = 1 - pps[2].y / size;
82238
+ uniforms.d_A = pps[3].x / size;
82239
+ uniforms.d_B = 1 - pps[3].y / size;
82240
+
82241
+ if (!_passthroughCenter) {
82242
+ calculatePassthroughCenter();
82243
+ }
82244
+
82245
+ var ps = [
82246
+ [pps[0], pps[1]],
82247
+ [pps[1], pps[2]],
82248
+ [pps[2], pps[3]],
82249
+ [pps[3], pps[0]]
82250
+ ];
82251
+ zim.loop(sides, function(side, i) {
82252
+ if (side.update) {
82253
+ var pA = ps[i][0];
82254
+ var pB = ps[i][1];
82255
+ side.x = pB.x + (pA.x - pB.x) / 2;
82256
+ side.y = pB.y + (pA.y - pB.y) / 2;
82257
+ side.inside.loc(side, null, blob);
81327
82258
  }
81328
82259
  });
81329
-
81330
- this.dispose = function(a,b,disposing) {
81331
- frame.off("keydown", that.keyDE, null, mID);
81332
- frame.off("keyup", that.keyUE, null, mID);
81333
- if (!disposing) {this.zimContainer_dispose();}
81334
- return true;
81335
- };
81336
-
81337
- if (style!==false) zim.styleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
81338
-
81339
- this.clone = function(exact) {
81340
- return that.cloneProps(new zim.Perspective((exact||!zim.isPick(oa[0]))?obj:oa[0], points, interactive, showControls, allowToggle, move, (exact||!zim.isPick(oa[1]))?amount:oa[1], (exact||!zim.isPick(oa[2]))?amountY:oa[2], (exact||!zim.isPick(oa[3]))?blur:oa[3], plane, fade, dynamic, frame, style, this.group, inherit));
81341
- };
82260
+ }
82261
+ update();
82262
+ controls.top();
81342
82263
 
82264
+ if (interactive) {
82265
+ blob.on("update", update, null, null, null, null, mID);
82266
+ blob.on("pressmove", update, null, null, null, null, mID);
82267
+ }
82268
+
82269
+ Object.defineProperty(this, "obj", {
82270
+ get: function() {
82271
+ return obj;
82272
+ },
82273
+ set: function(value) {
82274
+ obj = value;
82275
+ that.shader.replaceChannel(value, 0);
82276
+ }
82277
+ });
82278
+
82279
+ function activate() {
82280
+ if (zim.Perspective.active && zim.Perspective.active !== that) {
82281
+ zim.Perspective.active.deselectPoints();
82282
+ zim.Perspective.active.toggle(false);
82283
+ }
82284
+ zim.Perspective.active = that;
82285
+ }
82286
+
82287
+ this.dispose = function(a, b, disposing) {
82288
+ frame.off("keydown", that.keyDE, null, mID);
82289
+ frame.off("keyup", that.keyUE, null, mID);
82290
+ if (maskContainer && maskContainer.dispose) maskContainer.dispose();
82291
+ if (that.shader && that.shader.dispose) that.shader.dispose();
82292
+ if (!disposing) {this.zimContainer_dispose();}
82293
+ return true;
81343
82294
  };
81344
- zim.extend(zim.Perspective, zim.Container, ["clone", "dispose"], "zimContainer", false);
82295
+
82296
+ if (style !== false) zim.styleTransforms(this, DS);
82297
+
82298
+ this.clone = function(exact) {
82299
+ return that.cloneProps(new zim.Perspective((exact || !zim.isPick(oa[0])) ? obj : oa[0], points, interactive, showControls, allowToggle, move, (exact || !zim.isPick(oa[1])) ? borderColor : oa[1], (exact || !zim.isPick(oa[2])) ? borderWidth : oa[2], (exact || !zim.isPick(oa[3])) ? dashed : oa[3], plane, fade, dynamic, frame, resolution, _maskShape, feather, _onTop, _overlay, _clipping, _passthrough, _passthroughScale, _passthroughShiftX, _passthroughShiftY, style, this.group, inherit));
82300
+ };
82301
+ };
82302
+ zim.extend(zim.Perspective, zim.Container, ["clone", "dispose"], "zimContainer", false);
82303
+ zim.Perspective.active = null;
81345
82304
  //-69.9748
81346
82305
 
81347
82306
 
@@ -85513,8 +86472,8 @@ zim.Emitter = function(obj, width, height, interval, num, life, fade, shrink, wa
85513
86472
  cache = zim.mobile();
85514
86473
  }
85515
86474
  }
85516
- if (cache) stage.snapToPixelEnabled = true;
85517
86475
  if (stage) {
86476
+ if (cache) stage.snapToPixelEnabled = true;
85518
86477
  var myIndex = that.parent.getChildIndex(that);
85519
86478
  that.parent.addChildAt(particles, myIndex); // add particles beneath emitter in emitter's container
85520
86479
  // particles.x = that.x;
@@ -85928,7 +86887,7 @@ zim.Emitter = function(obj, width, height, interval, num, life, fade, shrink, wa
85928
86887
  if (p.trace?p.getChildAt(0).endSpurt:p.endSpurt) {
85929
86888
  sendEvent("spurtfizzed", p);
85930
86889
  that.spurting = false;
85931
- if (cache) stage.snapToPixelEnabled = false;
86890
+ if (cache && stage) stage.snapToPixelEnabled = false;
85932
86891
  }
85933
86892
  if (that.pool) {
85934
86893
  if (p.pooled == "end") {
@@ -85990,14 +86949,14 @@ zim.Emitter = function(obj, width, height, interval, num, life, fade, shrink, wa
85990
86949
  // that.removeFrom();
85991
86950
  if (that.parent) that.parent.removeChild(that);
85992
86951
  that.particles.removeFrom();
85993
- if (cache) stage.snapToPixelEnabled = false;
86952
+ if (cache && stage) stage.snapToPixelEnabled = false;
85994
86953
  };
85995
86954
 
85996
86955
  this.spurting = false;
85997
86956
  this.spurt = function(num, time, restart) {
85998
86957
  var sig = "num, time, restart";
85999
86958
  var duo; if (duo = zob(that.spurt, arguments, sig)) return duo;
86000
- if (cache) stage.snapToPixelEnabled = true;
86959
+ if (cache && stage) stage.snapToPixelEnabled = true;
86001
86960
  if (!zot(time)) {
86002
86961
  zim.timeout(zim.Pick.choose(time), function() {
86003
86962
  lastSpurt(that.currentParticle);
@@ -86046,7 +87005,7 @@ zim.Emitter = function(obj, width, height, interval, num, life, fade, shrink, wa
86046
87005
  }
86047
87006
  that.zimInterval.pause();
86048
87007
  that.emitterPaused = true;
86049
- if (cache) stage.snapToPixelEnabled = false;
87008
+ if (cache && stage) stage.snapToPixelEnabled = false;
86050
87009
  } else { // unpausing
86051
87010
  if (!that.emitterPaused) return that;
86052
87011
  if (restart) {
@@ -86067,7 +87026,7 @@ zim.Emitter = function(obj, width, height, interval, num, life, fade, shrink, wa
86067
87026
  }
86068
87027
  if (that.zimInterval) that.zimInterval.pause(false, immediate);
86069
87028
  that.emitterPaused = false;
86070
- if (cache) stage.snapToPixelEnabled = true;
87029
+ if (cache && stage) stage.snapToPixelEnabled = true;
86071
87030
  }
86072
87031
 
86073
87032
  if (that.zimInterval) that.zimInterval.pauseOnBlurPaused = state; // ZIM 019 Patch - in case being paused when tab not active
@@ -86099,7 +87058,7 @@ zim.Emitter = function(obj, width, height, interval, num, life, fade, shrink, wa
86099
87058
 
86100
87059
 
86101
87060
  this.dispose = function() {
86102
- if (cache) stage.snapToPixelEnabled = true;
87061
+ if (cache && stage) stage.snapToPixelEnabled = true;
86103
87062
  if (that.zimInterval) that.zimInterval.clear();
86104
87063
  if (emitterTicker) zim.Ticker.remove(emitterTicker, mID, that);
86105
87064
  zim.loop(poolList, function(particle) {
@@ -91241,7 +92200,7 @@ assets - (default null) - 1. a string asset or 2. an array of assets, 3. ZIM ass
91241
92200
  2. ["logo.png", "bounce.mp3", "Reuben.otf"]
91242
92201
  3. {id:"string", src:"logo.png", path:"assets/", loadTimeout:2, noCORSonImage:true}
91243
92202
  4. [{assets:["one.png", "two.png"], path:"images/"}, {assets:["big.mp3", "oof.mp3"], path:"sounds/"}]
91244
- ** see the loadAssets() method for details - including more file types, etc.
92203
+ ** see the loadAssets() method for details - including more file types, Google fonts, Noto Emojis, etc.
91245
92204
  NOTE: "complete", "progress" and "fileLoaded" events are not dispatched
91246
92205
  use loadAssets() for these if desired
91247
92206
  the "ready" event will be dispatched when the canvas is ready and initial assets are loaded
@@ -91344,8 +92303,15 @@ loadAssets(assets, path, progress, xhr, time, loadTimeout, outputAudioSprite, cr
91344
92303
  assets - a file (url String, asset object or multi-asset object) or files in an Array
91345
92304
  each asset String is how you then access the asset with the asset() method of Frame
91346
92305
  asset types (from CreateJS PreloadJS): Image, Font, JSON, Sound, SVG, Text, XML
91347
- NOTE: as of ZIM ZIM 02, fonts can be loaded with just the font file name (including Google Fonts) rather than a ZIM font object - see FONTS in the Docs.
92306
+ NOTE: as of ZIM ZIM 02, fonts can be loaded with just the font file name (including Google Fonts)
92307
+ rather than a ZIM font object - see FONTS in the Docs.
92308
+ so for google fonts, use "gf_Font+Family" and then when assigning the font to the Label, use "Font Family" without the gf (+ is optional)
91348
92309
  NOTE: as of ZIM Cat 04, SVG will be automatically converted to a Bitmap with and svg property of the original SVG.
92310
+ NOTE: as of ZIM 020, Noto Color Emojis can be loaded with "noto_emoji"
92311
+ These look consistent across platforms (Windows, Linux, Android, iOS)
92312
+ Paste any emoji character or code after noto_ to preload the SVG for the emoji
92313
+ If color or borderColor is specified in the Emoji (or SVG) then individual parts
92314
+ can be colored, dragged, wiggled, or animated (see Emoji and SVG)
91349
92315
  asset can also be a ZIM asset object:
91350
92316
  {id:"string", src:"filename", path:"dir/", loadTimeout:1, maxNum:num, noCORSonImage:true}
91351
92317
  then can use the id to access the asset in the asset() method of Frame
@@ -91378,7 +92344,8 @@ loadAssets(assets, path, progress, xhr, time, loadTimeout, outputAudioSprite, cr
91378
92344
  ]
91379
92345
  ** then asset("one.png") will be the asset in the images folder
91380
92346
  ** and asset("portraits/one.png") will be the asset in the portraits folder
91381
- asset can also be a font object - but as of ZIM ZIM 02, fonts can be loaded with just the file name, including Google Fonts
92347
+ asset can also be a font object (DEPRECATED)
92348
+ As of ZIM ZIM 02, fonts can be loaded with just the file name, including Google Fonts ("gf_fontfamily")
91382
92349
  DO NOT use uppercase letters on mobile apps
91383
92350
  {font:name, src:url, type:string, weight:string, style:string} // with last three properties being optional
91384
92351
  eg.
@@ -91386,6 +92353,7 @@ loadAssets(assets, path, progress, xhr, time, loadTimeout, outputAudioSprite, cr
91386
92353
  {font: "regu", src:"regul-bold.woff", weight:"bold"}
91387
92354
  {src:"https://fonts.googleapis.com/css?family=Roboto"}
91388
92355
  For google fonts https://fonts.google.com/ you add extra information to the url so the font (family), type, weight and style are ignored
92356
+ It is easier to just load google fonts as "gf_fontfamily" as an asset
91389
92357
  If absolute src is used, path parameter is ignored - otherwise path is added to start of src
91390
92358
  After loading, can just use:
91391
92359
  var label = new Label("hello", 30, "wildwood") // or whatever the font property is
@@ -92432,6 +93400,56 @@ zim.Frame = function(scaling, width, height, color, outerColor, ready, assets, p
92432
93400
  that.dispatchEvent("update");
92433
93401
  };
92434
93402
 
93403
+ // Made by AI - Gemini - used to load Noto Emojis from GitHub
93404
+ function getNotoFilename(inputStr) {
93405
+ // Clean up whitespace
93406
+ var input = inputStr.trim();
93407
+ if (!input) return 'emoji_u.svg';
93408
+
93409
+ // Regex check: If it contains letters/numbers and starts with U+, contains hex prefixes,
93410
+ // or is separated by underscores/hyphens/spaces, treat it as a code string.
93411
+ var isCodeRegex = /^[0-9a-fA-F_\-\sU\+]+$/;
93412
+ var points = [];
93413
+
93414
+ if (isCodeRegex.test(input) && input.replace(/[_\-\sU\+]/g, '').length > 0) {
93415
+ // --- PROCESS AS ALPHANUMERIC CODE ---
93416
+ // Split by common delimiters: spaces, underscores, hyphens, or "U+"
93417
+ var rawSegments = input.split(/[_\-\s]+/);
93418
+
93419
+ for (var s = 0; s < rawSegments.length; s++) {
93420
+ var segment = rawSegments[s].replace(/^U\+/i, '').toLowerCase();
93421
+ if (segment && segment !== 'fe0f') {
93422
+ points.push(segment);
93423
+ }
93424
+ }
93425
+ } else {
93426
+ // --- PROCESS AS RAW EMOJI PICTURE (Legacy ES5 Surrogate Math) ---
93427
+ var i = 0;
93428
+ while (i < input.length) {
93429
+ var code = input.charCodeAt(i);
93430
+
93431
+ // Handle High/Low Surrogate pairs for 32-bit emojis
93432
+ if (code >= 0xD800 && code <= 0xDBFF && i + 1 < input.length) {
93433
+ var nextCode = input.charCodeAt(i + 1);
93434
+ if (nextCode >= 0xDC00 && nextCode <= 0xDFFF) {
93435
+ code = ((code - 0xD800) * 0x400) + (nextCode - 0xDC00) + 0x10000;
93436
+ i++;
93437
+ }
93438
+ }
93439
+
93440
+ var hex = code.toString(16).toLowerCase();
93441
+ if (hex !== 'fe0f') {
93442
+ points.push(hex);
93443
+ }
93444
+ i++;
93445
+ }
93446
+ }
93447
+
93448
+ // Join all collected hex values with underscores per Google's standard layout
93449
+ return 'emoji_u' + points.join('_') + '.svg';
93450
+ }
93451
+ this.getNotoFilename = getNotoFilename;
93452
+
92435
93453
  function setVisible() {
92436
93454
  if (scaling == "fill") {
92437
93455
  var beside = (zum(that.canvas.style.width) - zim.windowWidth()) / 2;
@@ -92551,6 +93569,14 @@ zim.Frame = function(scaling, width, height, color, outerColor, ready, assets, p
92551
93569
  // // continue;
92552
93570
  // // }
92553
93571
  // }
93572
+
93573
+
93574
+
93575
+ var match;
93576
+ if (a.match) match = a.match(/^noto_(.*)/);
93577
+ if (match) {
93578
+ a = {id:a, src:"https://raw.githubusercontent.com/googlefonts/noto-emoji/main/svg/" + getNotoFilename(match[1])}
93579
+ }
92554
93580
  if (a.replace) a = a.replace(/gf_/i, "https://fonts.googleapis.com/css?family=");
92555
93581
  // split multi into individual ZIM asset objects and make the first of these
92556
93582
  if (a.assets) {
@@ -92559,6 +93585,11 @@ zim.Frame = function(scaling, width, height, color, outerColor, ready, assets, p
92559
93585
  if (!Array.isArray(a.assets)) a.assets = [a.assets];
92560
93586
  for (j=0; j<a.assets.length; j++) {
92561
93587
  var aj = a.assets[j];
93588
+ match = null;
93589
+ if (aj.match) match = aj.match(/^noto_(.*)/);
93590
+ if (match) {
93591
+ aj = {id:aj, src:"https://raw.githubusercontent.com/googlefonts/noto-emoji/main/svg/" + getNotoFilename(match[1])}
93592
+ }
92562
93593
  if (aj.split) {
92563
93594
  var temp = aj.split("?");
92564
93595
  ext = temp[0].match(re);
@@ -92978,7 +94009,7 @@ zim.Frame = function(scaling, width, height, color, outerColor, ready, assets, p
92978
94009
  };
92979
94010
 
92980
94011
  // called by asset if auto loading (ac is Asset Container)
92981
- this.ac = function(method, args, obj) {
94012
+ this.ac = function(method, args, obj) {
92982
94013
  if (obj) {
92983
94014
  if (!obj.commands) obj.commands = [];
92984
94015
  obj.commands.push([method,args,obj]);
@@ -95196,7 +96227,7 @@ zim.Dat = function(file) {
95196
96227
  zim.extend(zim.Dat, createjs.EventDispatcher, null, "cjsEventDispatcher", false);//-83.08
95197
96228
 
95198
96229
  /*--
95199
- SVG = function(svg, width, height, bitmap, splitTypes, geometric, showControls, interactive, style, group, inherit)
96230
+ SVG = function(svg, width, height, bitmap, splitTypes, geometric, showControls, interactive, color, borderColor, order, style, group, inherit)
95200
96231
 
95201
96232
  SVG
95202
96233
  zim class - extends a zim.Container which extends a createjs.Container
@@ -95314,10 +96345,16 @@ PARAMETERS
95314
96345
  Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
95315
96346
  ** supports OCT - parameter defaults can be set with STYLE control (like CSS)
95316
96347
  svg - |ZIM VEE| the String file name of the SVG including file extension for instance, "pic.svg"
95317
- or an SVG tag either directly as a string or as a reference to an HTML tag - ie. zid("svgID")
95318
- There is a global PATH constant that can be set to add a path to the start of the file name
95319
- for instance setting PATH = "assets/" would then look for "assets/pic.svg".
95320
- If a path is provided to Frame() parameter or the loadAssets() then these will automatically set the global PATH constant.
96348
+ or an SVG tag either directly as a string or as a reference to an HTML tag - ie. zid("svgID")
96349
+ There is a global PATH constant that can be set to add a path to the start of the file name
96350
+ for instance setting PATH = "assets/" would then look for "assets/pic.svg".
96351
+ If a path is provided to Frame() parameter or the loadAssets() then these will automatically set the global PATH constant.
96352
+ NOTE: as of ZIM 020, Noto Color Emojis can be loaded with "noto_emoji"
96353
+ These look consistent across platforms (Windows, Linux, Android, iOS)
96354
+ Paste any emoji character or code after noto_
96355
+ Can also preload the SVG using the noto_ if SVG is to be used in Tile() for instance
96356
+ If color or borderColor is specified then an SVG Container will be nade with individual parts
96357
+ that can be colored, dragged, wiggled, or animated
95321
96358
  width - (default null) optionally predict the width of the SVG
95322
96359
  The width will be ignored and the actual width will be used if the SVG is preloaded
95323
96360
  and if lazy-loaded, the width will be replaced with the actual width after the SVG is loaded.
@@ -95333,7 +96370,12 @@ bitmap - (default true) this will show the SVG as a Bitmap (still nicely scalabl
95333
96370
  splitTypes - (default false) - set to true to split different types of paths into separate objects
95334
96371
  geometric - (default true) - set to false to load Rectangle and Circle objects as Blob objects
95335
96372
  showControls - (default true) set to false to start with controls not showing
95336
- interactive - (default true) set to false to turn off controls, move, toggle, select, edit - leaving just the shapes
96373
+ interactive - (default true) for bitmap:false, set to false to turn off controls, move, toggle, select, edit - leaving just the shapes
96374
+ color - |ZIM VEE| (default null) for bitmap:false, set to a color or an array of colors to apply to fill of children - in order of the children
96375
+ usually a series() would be used here for colors in order, or an array for random colors
96376
+ borderColor - |ZIM VEE| (default null) set to a color or an array of colors to apply to border of children - in order of the children
96377
+ order - and array showing a new order of the old index numbers
96378
+ eg [3,1,2,0] means the old index 3 is now at level 0, old index 1 stays the same, old index 2 is now third, and old index 0 is at the top
95337
96379
  style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
95338
96380
  group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
95339
96381
  inherit - (default null) used internally but can receive an {} of styles directly
@@ -95381,8 +96423,8 @@ dispatches a "complete" and a "ready" event (use either one) when the SVG is loa
95381
96423
  See the CreateJS Easel Docs for Container events such as:
95382
96424
  added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
95383
96425
  --*///+83.09
95384
- zim.SVG = function(svg, width, height, bitmap, splitTypes, geometric, showControls, interactive, style, group, inherit) {
95385
- var sig = "svg, width, height, bitmap, splitTypes, geometric, showControls, interactive, style, group, inherit";
96426
+ zim.SVG = function(svg, width, height, bitmap, splitTypes, geometric, showControls, interactive, color, borderColor, order, style, group, inherit) {
96427
+ var sig = "svg, width, height, bitmap, splitTypes, geometric, showControls, interactive, color, borderColor, order, style, group, inherit";
95386
96428
  var duo; if (duo = zob(zim.SVG, arguments, sig, this)) return duo;
95387
96429
  z_d("83.09");
95388
96430
 
@@ -95396,6 +96438,12 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
95396
96438
  if (zot(geometric)) geometric = DS.geometric!=null?DS.geometric:true;
95397
96439
  if (zot(showControls)) showControls = DS.showControls!=null?DS.showControls:null;
95398
96440
  if (zot(interactive)) interactive = DS.interactive!=null?DS.interactive:true;
96441
+ if (zot(color)) color = DS.color!=null?DS.color:null;
96442
+ if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
96443
+ if (zot(order)) order = DS.order!=null?DS.order:null;
96444
+
96445
+ var setColors = [];
96446
+ var setBorderColors = [];
95399
96447
 
95400
96448
  this.zimContainer_constructor(width, height);
95401
96449
  var that = this;
@@ -95474,6 +96522,8 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
95474
96522
  if (that.stage) that.stage.update();
95475
96523
  }
95476
96524
  setTimeout(function () {
96525
+ doOrder();
96526
+ doColors();
95477
96527
  that.dispatchEvent("ready");
95478
96528
  that.dispatchEvent("complete");
95479
96529
  },20);
@@ -95482,6 +96532,8 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
95482
96532
  that.bitmap = bitmap;
95483
96533
  that.bitmap.addTo(that);
95484
96534
  applyCommands();
96535
+ doOrder();
96536
+ doColors();
95485
96537
  that.dispatchEvent("ready");
95486
96538
  that.dispatchEvent("complete");
95487
96539
  if (that.stage) that.stage.update();
@@ -95494,11 +96546,13 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
95494
96546
  svgContainer.loop(function (obj) {
95495
96547
  if (obj) obj.addTo(that);
95496
96548
  }, true);
96549
+ doOrder();
96550
+ doColors();
95497
96551
  if (second) {
95498
96552
  applyCommands();
95499
96553
  if (that.stage) that.stage.update();
95500
96554
  }
95501
- setTimeout(function () {
96555
+ setTimeout(function () {
95502
96556
  that.dispatchEvent("ready");
95503
96557
  that.dispatchEvent("complete");
95504
96558
  },20);
@@ -95510,6 +96564,8 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
95510
96564
  if (obj) obj.addTo(that);
95511
96565
  }, true);
95512
96566
  applyCommands();
96567
+ doOrder();
96568
+ doColors();
95513
96569
  that.dispatchEvent("ready");
95514
96570
  that.dispatchEvent("complete");
95515
96571
  if (that.stage) that.stage.update();
@@ -95517,17 +96573,42 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
95517
96573
  }
95518
96574
  }
95519
96575
  }
96576
+
96577
+ function doColors() {
96578
+ if (color) {
96579
+ if (color.index) color.index = 0; // not sure where it was setting to 1 when being cloned?
96580
+ that.loop(function(obj) {
96581
+ var c = zik(color);
96582
+ if (c!=null && c!="") obj.color = c;
96583
+ setColors.push(c);
96584
+ });
96585
+ }
96586
+ if (borderColor) {
96587
+ if (borderColor.index) borderColor.index = 0;
96588
+ that.loop(function(obj) {
96589
+ var c = zik(borderColor);
96590
+ if (c!=null) obj.borderColor = c;
96591
+ setBorderColors.push(c);
96592
+ });
96593
+ }
96594
+ }
96595
+
96596
+ function doOrder() {
96597
+ if (order) zim.orderContainer(that, order);
96598
+ }
95520
96599
 
95521
96600
  function applyCommands() {
95522
96601
  if (zot(width) && zot(height)) that.setBounds(null); // resets size
95523
96602
  that.type = "SVG";
95524
- if (that.commands) {
95525
- for (var i=0; i<that.commands.length; i++) {
95526
- if (that.commands[i][2]) that[that.commands[i][0]].apply(that, that.commands[i][1]);
95527
- else zim[that.commands[i][0]].apply(that, that.commands[i][1]);
95528
- }
95529
- }
95530
- that.commands = null;
96603
+ var os = that; // adjusted 020 for Lazy Load Noto SVG Emoji
96604
+ if (that.parent && that.parent.type == "Emoji") os = that.parent;
96605
+ if (os.commands) {
96606
+ for (var i=0; i<os.commands.length; i++) {
96607
+ if (os.commands[i][2]) os[os.commands[i][0]].apply(os, os.commands[i][1]);
96608
+ else zim[os.commands[i][0]].apply(os, os.commands[i][1]);
96609
+ }
96610
+ }
96611
+ os.commands = null;
95531
96612
  }
95532
96613
 
95533
96614
  that.keyOut = function(color, tolerance, replacement) {
@@ -95538,8 +96619,8 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
95538
96619
  }
95539
96620
 
95540
96621
  if (style!==false) zim.styleTransforms(this, DS);
95541
- that.clone = function (exact) {
95542
- return this.cloneProps(new zim.SVG(exact?svgO:originalSVG, width, height, bitmap, splitTypes, geometric, showControls, interactive, style, this.group, inherit));
96622
+ that.clone = function (exact) {
96623
+ return this.cloneProps(new zim.SVG(exact?svgO:originalSVG, width, height, bitmap, splitTypes, geometric, showControls, interactive, exact&&setColors.length>0?zim.series(setColors):color, exact&&setBoarderColors.length>0?zim.series(setBorderColors):borderColor, style, this.group, inherit));
95543
96624
  }
95544
96625
  }
95545
96626
  zim.extend(zim.SVG, zim.Container, ["clone"], "zimContainer", false);//-83.09
@@ -95741,11 +96822,14 @@ Note: there are more features to the Web Speech API - see the HTML docs
95741
96822
  if (zot(rate)) rate = 1;
95742
96823
 
95743
96824
  utter.text = text;
95744
- utter.voice = M=="ios"?null:voice;
95745
- utter.lang = lang;
95746
- utter.volume = volume;
95747
- utter.rate = rate;
95748
- utter.pitch = pitch;
96825
+ // utter.voice = M=="ios"?null:voice;
96826
+ // if (voice instanceof SpeechSynthesisVoice && M != "ios") utter.voice = voice;
96827
+ if (voice instanceof SpeechSynthesisVoice) utter.voice = voice;
96828
+ if (lang != null) utter.lang = lang;
96829
+ if (volume != null) utter.volume = volume;
96830
+ if (rate != null) utter.rate = rate;
96831
+ if (pitch != null) utter.pitch = pitch;
96832
+
95749
96833
  speechSynthesis.speak(utter);
95750
96834
 
95751
96835
  return utter;
@@ -95783,7 +96867,283 @@ Note: there are more features to the Web Speech API - see the HTML docs
95783
96867
  }
95784
96868
 
95785
96869
  }
95786
- zim.extend(zim.Speech, createjs.EventDispatcher, null, "cjsEventDispatcher", false);//-83.095
96870
+ zim.extend(zim.Speech, createjs.EventDispatcher, null, "cjsEventDispatcher", false);
96871
+ //-83.095
96872
+
96873
+ /*--
96874
+ Hardware = function(callback, baudRate, delimiter)
96875
+
96876
+ Hardware
96877
+ zim class - extends a createjs.EventDispatcher
96878
+
96879
+ DESCRIPTION
96880
+ Reads from and writes to a device such as an Ardiuno
96881
+ Wraps the JS Web Serial API
96882
+ https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API
96883
+ Coded primarily by Gemini AI
96884
+
96885
+ See: https://zimjs.com/hardware/
96886
+
96887
+ NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
96888
+
96889
+ EXAMPLE
96890
+ // USING ZIM as INPUT to ARDUINO
96891
+
96892
+ // would need an arduino connected
96893
+ // with the following .ino file loaded onto it
96894
+
96895
+ // ------------------------
96896
+ // ---- Arduinin Code -----
96897
+
96898
+ const int LED_PIN = 13; // Built-in LED on your Uno R3 board
96899
+ void setup() {
96900
+ Serial.begin(9600); // Initialize background channel at matching speed
96901
+ pinMode(LED_PIN, OUTPUT); // Configure Pin 13 as an output light source
96902
+ }
96903
+ void loop() {
96904
+ // Check if ZIM has sent a data character over the USB cable
96905
+ if (Serial.available() > 0) {
96906
+ char incomingChar = Serial.read(); // Read the character data fragment
96907
+ if (incomingChar == '1') {
96908
+ digitalWrite(LED_PIN, HIGH); // Turn physical light ON
96909
+ }
96910
+ else if (incomingChar == '0') {
96911
+ digitalWrite(LED_PIN, LOW); // Turn physical light OFF
96912
+ }
96913
+ }
96914
+ }
96915
+
96916
+ // -------------------
96917
+ // ---- ZIM Code -----
96918
+
96919
+ const device = new Hardware();
96920
+
96921
+ const toggle = new Toggle({
96922
+ label: "LED POWER",
96923
+ toggleBackgroundColor: green,
96924
+ color: white
96925
+ })
96926
+ .center()
96927
+ .change(() => {
96928
+ if (toggle.toggled) {
96929
+ device.write("1"); // note a \n will be automatically added if missing
96930
+ } else {
96931
+ device.write("0");
96932
+ }
96933
+ });
96934
+
96935
+ // must interact to connect
96936
+ const pane = new Pane("CONNECT", yellow).show(() => {
96937
+ device.connect()
96938
+ });
96939
+
96940
+ device.on("disconnected", () => {
96941
+ pane.show(() => { // remember to add the callback again
96942
+ device.connect();
96943
+ });
96944
+ });
96945
+ END EXAMPLE
96946
+
96947
+ EXAMPLE
96948
+ // USING ZIM AS OUTPUT FROM ARDUINO
96949
+ See: https://zimjs.com/hardware/
96950
+
96951
+ // would need an arduino connected
96952
+ // with a potentiometer (pot) dial
96953
+ // (probably on a breadboard)
96954
+ // with outside pins goint to ground and 5V
96955
+ // and middle pin goint to analogue A0
96956
+ // with the following .ino file loaded onto it
96957
+
96958
+ // ------------------------
96959
+ // ---- Arduinin Code -----
96960
+
96961
+ const int potPin = A0;
96962
+ void setup() {
96963
+ Serial.begin(9600);
96964
+ }
96965
+ void loop() {
96966
+ int potValue = analogRead(potPin);
96967
+ Serial.println(potValue);
96968
+ delay(20);
96969
+ }
96970
+
96971
+ // -------------------
96972
+ // ---- ZIM Code -----
96973
+
96974
+ const device = new Hardware(data => {
96975
+ zog(data); // gives values from 0-1023
96976
+ });
96977
+
96978
+ // must interact to connect
96979
+ const pane = new Pane("CONNECT", yellow).show(()=>{
96980
+ device.connect();
96981
+ });
96982
+
96983
+ device.on("disconnected", () => {
96984
+ pane.show(()=>{ // remember to add the callback again
96985
+ device.connect();
96986
+ });
96987
+ });
96988
+ END EXAMPLE
96989
+
96990
+ PARAMETERS
96991
+ callback - the function to call when data is received and will receive the data in its single parameter
96992
+ baudRate - (default 9600) Port speed matching the microcontroller
96993
+ delimiter - (default \n) Character used to split data lines
96994
+
96995
+ METHODS
96996
+ connect() - must interact before connecting - will receive a connected event
96997
+ write(data) - write to the device - also see the data event for reading from the device
96998
+ disconnect() - disconnect from the device
96999
+
97000
+ PROPERTIES
97001
+ type - holds the class name as a String
97002
+ port - readonly the port the hardware is connected on
97003
+ reader - readonly the textDecoder.readable.getReader()
97004
+ writer - readonly the textEncoder.writable.getWriter()
97005
+ textDecoder - readonly the JavaScript TextEncoderStream()
97006
+ textEncoder - readonly the JavaScript TextEncoderStream()
97007
+ isListening - whether actively reading on port
97008
+ baudRate - readonly baud rate - see parameter
97009
+ delimiter - end character for outgoing data
97010
+
97011
+ EVENTS
97012
+ dispatches "connected" when connected
97013
+ dispatches "disconnected" when disconnected
97014
+ --*///+83.097
97015
+ zim.Hardware = function(callback, baudRate, delimiter) {
97016
+ z_d("83.097");
97017
+ this.cjsEventDispatcher_constructor();
97018
+ this.type = "Hardware";
97019
+ var that = this;
97020
+
97021
+ // MONITOR
97022
+ this.mID = "z~"+this.type;
97023
+
97024
+ // Core Properties
97025
+ that.baudRate = baudRate || 9600;
97026
+ that.delimiter = delimiter || "\n";
97027
+
97028
+ that.port = null
97029
+ that.reader = null
97030
+ that.writer = null
97031
+ that.textDecoder = null
97032
+ that.isListening = false
97033
+
97034
+ // GLOBAL HARDWARE DISCONNECT MONITOR
97035
+ if (navigator.serial) {
97036
+ navigator.serial.addEventListener("disconnect", function (event) {
97037
+ if (event.target === that.port) {
97038
+ zogy("ZIM Harware - hardware physically disconnected!")
97039
+ that.isListening = false;
97040
+
97041
+ // Clean break: release locks and clear active streams
97042
+ if (that.reader) {
97043
+ try { that.reader.releaseLock() } catch (e) { }
97044
+ that.reader = null
97045
+ }
97046
+ if (that.writer) {
97047
+ try { that.writer.releaseLock() } catch (e) { }
97048
+ that.writer = null
97049
+ }
97050
+ that.port = null;
97051
+ that.dispatchEvent("disconnected");
97052
+ }
97053
+ });
97054
+ }
97055
+
97056
+ // CONNECT METHOD
97057
+ that.connect = function () {
97058
+ if (!navigator.serial) {
97059
+ console.error("Web Serial API is not supported in this browser. Please use Chrome or Edge.")
97060
+ return;
97061
+ }
97062
+
97063
+ navigator.serial.requestPort()
97064
+ .then(function (selectedPort) {
97065
+ that.port = selectedPort;
97066
+ return that.port.open({ baudRate: that.baudRate });s
97067
+ })
97068
+ .then(function () {
97069
+ zogy("ZIM Hardware - connected successfully!")
97070
+ that.isListening = true
97071
+
97072
+ // Set up Output Stream (Browser to Microcontroller)
97073
+ var textEncoder = new TextEncoderStream()
97074
+ textEncoder.readable.pipeTo(that.port.writable)
97075
+ that.writer = textEncoder.writable.getWriter()
97076
+
97077
+ // Set up Input Stream (Microcontroller to Browser)
97078
+ that.textDecoder = new TextDecoderStream()
97079
+ that.port.readable.pipeTo(that.textDecoder.writable)
97080
+ that.reader = that.textDecoder.readable.getReader()
97081
+
97082
+ // Start recursive background reader
97083
+ that._readLoop("");
97084
+ that.dispatchEvent("connected");
97085
+ })
97086
+ .catch(function (error) {
97087
+ console.error("Hardware connection failed:", error)
97088
+ })
97089
+ }
97090
+
97091
+ that.write = function (data) {
97092
+ if (that.writer && that.isListening) {
97093
+ var message = String(data);
97094
+ if (message.charAt(str.length - 1) != that.delimeter) {
97095
+ message += that.delimiter;
97096
+ }
97097
+ that.writer.write(message)
97098
+ .catch(function (error) {
97099
+ console.error("Failed to transmit data to hardware:", error);
97100
+ })
97101
+ } else {
97102
+ console.warn("Cannot write data: Hardware is not connected.");
97103
+ }
97104
+ }
97105
+
97106
+ // DISCONNECT METHOD (Manual Shutdown)
97107
+ that.disconnect = function () {
97108
+ that.isListening = false
97109
+ if (that.reader && that.writer) {
97110
+ that.reader.cancel()
97111
+ .then(function () { return that.writer.close() })
97112
+ .then(function () { if (that.port) return that.port.close() })
97113
+ .then(function () { zogy("ZIM Hardware: cleanly disconnected.") })
97114
+ .catch(function (err) { console.error("Error during disconnect process:", err) })
97115
+ }
97116
+ }
97117
+
97118
+ // INTERNAL RECURSIVE LOOP METHOD
97119
+ that._readLoop = function (buffer) {
97120
+ if (!that.isListening) return;
97121
+
97122
+ that.reader.read()
97123
+ .then(function (result) {
97124
+ if (result.done) {
97125
+ that.isListening = false;
97126
+ return;
97127
+ }
97128
+ buffer += result.value;
97129
+ var delimiterPattern = that.delimiter === "\n" ? /\r?\n/ : new RegExp(that.delimiter)
97130
+ var lines = buffer.split(delimiterPattern)
97131
+ buffer = lines.pop()
97132
+ for (var i = 0; i < lines.length; i++) {
97133
+ var cleanLine = lines[i].trim()
97134
+ if (cleanLine.length > 0 && typeof callback === "function") (callback)(cleanLine);
97135
+ }
97136
+ that._readLoop(buffer);
97137
+ })
97138
+ .catch(function (error) {
97139
+ // If it crashes due to a sudden cable pull, let the event listener handle the cleanup
97140
+ that.isListening = false
97141
+ });
97142
+ }
97143
+ }
97144
+ zim.extend(zim.Hardware, createjs.EventDispatcher, null, "cjsEventDispatcher", false);
97145
+ //-83.097
97146
+
95787
97147
 
95788
97148
  /*--
95789
97149
  Fonts - loaded into Frame()
@@ -97758,7 +99118,7 @@ RETURNS - null
97758
99118
  --*///+83.27
97759
99119
  zim.svgToBitmap = function(svg, callback, width, height, params) {
97760
99120
  z_d("83.27");
97761
-
99121
+
97762
99122
  if (!zot(svg.draggable)) {
97763
99123
  // CreateJS seems to wrap up an SVG with loadAssets as an SVG object
97764
99124
  var parser = new DOMParser();
@@ -104192,41 +105552,42 @@ END EXAMPLE
104192
105552
  PARAMETERS
104193
105553
  ** supports DUO - parameters or single object with properties below
104194
105554
  ** supports OCT - parameter defaults can be set with STYLE control (like CSS)
104195
- width - (400) width in pixels
104196
- height - (width) height in pixels (defaults to width)
104197
- info - (null) ***** array of label objects with name and backgroundColor properties
104198
- data - (null) ***** array of numbers representing pie slice values
104199
- units - (null) ***** unit label appended to data values
104200
- title - (null) title label or text displayed at top
104201
- footer - (null) footer label or text displayed at bottom in italics
104202
- backgroundColor - (white) background color
104203
- color - (dark) text color
104204
- size - (14) title/footer label font size
104205
- dataSize - (size) font size for data labels
104206
- font - (null) font family name
104207
- spacing - (5) spacing between elements in pixels
104208
- iconOrient - (true) ***** whether icon graphics are oriented to angle
104209
- iconFlip - (true) ***** whether icons are flipped
104210
- iconWidth - (null) ***** width of icon graphics if used
104211
- iconScale - (null) ***** scale factor for icon graphics
104212
- dec - (0) decimal places for displayed data values
104213
- padding - (10) padding around chart edges
104214
- showData - (true) whether to display data values
104215
- showInfo - (true) whether to display info labels
104216
- exchange - (false) ***** whether to exchange display positions of data and info
104217
- shiftForWedge - (true) whether labels shift when wedge is raised
105555
+ width - (default 400) width in pixels
105556
+ height - (default width) height in pixels (defaults to width)
105557
+ info - (default null) array of label objects with name and backgroundColor properties
105558
+ data - (default null) array of numbers representing pie slice values
105559
+ units - (default null) unit label appended to data values
105560
+ title - (default null) title label or text displayed at top
105561
+ footer - (default null) footer label or text displayed at bottom in italics
105562
+ backgroundColor - (default white) background color
105563
+ color - (default dark) text color
105564
+ size - (default 14) title/footer label font size
105565
+ dataSize - (default size) font size for data labels
105566
+ font - (default null) font family name
105567
+ spacing - (default 5) spacing between elements in pixels
105568
+ iconOrient - (default true) whether icon graphics are oriented to angle
105569
+ iconFlip - (default true) whether icons are flipped
105570
+ iconWidth - (default null) width of icon graphics if used
105571
+ iconScale - (default null) scale factor for icon graphics
105572
+ dec - (default 0) decimal places for displayed data values
105573
+ padding - (default 10) padding around chart edges
105574
+ showData - (default true) whether to display data values
105575
+ showInfo - (default true) whether to display info labels
105576
+ exchange - (default false) whether to exchange display positions of data and info
105577
+ shiftForWedge - (default true) whether labels shift when wedge is raised
104218
105578
 
104219
105579
  METHODS
104220
105580
  clone() - returns a clone of the PieChart
104221
105581
  getIndex(x, y) - returns the pie wedge index at the given local coordinates
104222
105582
  raiseWedge(index, factor) - raises a wedge by the specified factor
104223
105583
  lowerWedge(index) - lowers the raised wedge(s) back to flat
104224
- setChart(obj) - ***** redraws chart with new data or configuration
105584
+ setChart(obj) - redraws chart with new data or configuration
104225
105585
 
104226
105586
  PROPERTIES
104227
105587
  index - the currently selected wedge index from mouse click
104228
105588
  rollIndex - the wedge index currently under the mouse
104229
105589
  angles - array of angle values for each wedge
105590
+ angleWedges - array of start and stop angles, the two labelOnArc objects, and the icon holder container
104230
105591
  info - info labels array
104231
105592
  data - data values array
104232
105593
  title - title label
@@ -104349,6 +105710,7 @@ zim class - extends zim.Graph which extends a zim.Container which extends a crea
104349
105710
 
104350
105711
  DESCRIPTION
104351
105712
  Creates a live/animated line graph that updates data over time using a WebWorker.
105713
+ Data is read in from a text file source specified in the src parameter.
104352
105714
  Displays multiple data series as lines with optional gradient fills and smooth curves.
104353
105715
  Automatically manages maxData limit, supports real-time data streaming and animation.
104354
105716
 
@@ -104378,6 +105740,7 @@ const graph = new LiveGraph({
104378
105740
  {item: "CPU", icon: null},
104379
105741
  {item: "Memory", icon: null},
104380
105742
  ],
105743
+ src: "url_to_live_data.txt", // with [12, 24] for instance changing over time
104381
105744
  timeStep: .5,
104382
105745
  smooth: true,
104383
105746
  thickness: 2,
@@ -104410,6 +105773,8 @@ title - (default null) title label or text displayed at top
104410
105773
  info - (default null) info object with labelH, labelV, dataH, dataV arrays
104411
105774
  data - (default null) array of data objects with dataH and dataV properties
104412
105775
  src - (default null) external data source URL for updates
105776
+ format [data] for one entry - this gets read over timeStep
105777
+ format [data, data, data] for three entries, etc. match number of items with data items
104413
105778
  timeStep - (default .5) time interval in seconds between data updates
104414
105779
  thickness - (default 2) line thickness in pixels
104415
105780
  smooth - (default true) whether to use smooth curves instead of straight lines
@@ -104887,7 +106252,7 @@ for (z_i = 0; z_i < globalFunctions.length; z_i++) {
104887
106252
  ["FILL", zim.FILL],
104888
106253
  ["FULL", zim.FULL],
104889
106254
  ["LEFT", zim.LEFT],
104890
- ["RIGHT", zim.RIGHT],
106255
+ ["RIGHT", zim.RIGHT],s
104891
106256
  ["CENTER", zim.CENTER],
104892
106257
  ["MIDDLE", zim.MIDDLE],
104893
106258
  ["JUSTIFY", zim.JUSTIFY],
@@ -104994,6 +106359,7 @@ export let extend = zim.extend;
104994
106359
  export let copy = zim.copy;
104995
106360
  export let merge = zim.merge;
104996
106361
  export let sortObject = zim.sortObject;
106362
+ export let orderContainer = zim.orderContainer;
104997
106363
  export let arraysEqual = zim.arraysEqual;
104998
106364
  export let arrayMinMax = zim.arrayMinMax;
104999
106365
  export let isEmpty = zim.isEmpty;
@@ -105255,6 +106621,7 @@ export let Vid = zim.Vid;
105255
106621
  export let Dat = zim.Dat;
105256
106622
  export let SVG = zim.SVG;
105257
106623
  export let Speech = zim.Speech;
106624
+ export let Hardware = zim.Hardware;
105258
106625
  export let PermissionAsk = zim.PermissionAsk;
105259
106626
  export let Monitor = zim.Monitor;
105260
106627
  export let distill = zim.distill;