targetj 1.0.260 → 1.1.1

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.
@@ -1,4 +1,14 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
3
+ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
4
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
5
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
6
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
7
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
8
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
9
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
10
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
11
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
2
12
  function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
3
13
  function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
4
14
  function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
@@ -8,6 +18,7 @@ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r),
8
18
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
9
19
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
10
20
  import { ColorUtil } from "./ColorUtil.js";
21
+ import { TUtil } from "./TUtil.js";
11
22
 
12
23
  /**
13
24
  * It renders GPU-backed children using WebGPU.
@@ -25,10 +36,24 @@ var ParticleRenderer = /*#__PURE__*/function () {
25
36
  this.particleBuffer = undefined;
26
37
  this.targetParticleBuffer = undefined;
27
38
  this.uniformBuffer = undefined;
39
+ this.explodeFragmentBuffer = undefined;
40
+ this.explodeTexture = undefined;
41
+ this.explodeSampler = undefined;
42
+ this.explodeSourceCanvas = undefined;
43
+ this.explodeTextureReady = false;
28
44
  this.transitionStep = 0;
29
45
  this.transitionActive = false;
30
46
  this.particleCount = 0;
31
47
  this.canvasLayer = undefined;
48
+
49
+ // Canvas origin and viewport are in the owning TModel's local content space.
50
+ this.canvasX = 0;
51
+ this.canvasY = 0;
52
+ this.canvasBounds = undefined;
53
+ this.canvasSize = undefined;
54
+ this.boundsDirty = true;
55
+ this.currentParticleData = undefined;
56
+ this.targetParticleData = undefined;
32
57
  this.initializationPromise = undefined;
33
58
  }
34
59
  return _createClass(ParticleRenderer, [{
@@ -40,28 +65,29 @@ var ParticleRenderer = /*#__PURE__*/function () {
40
65
  while (1) switch (_context.prev = _context.next) {
41
66
  case 0:
42
67
  if (!this.device) {
43
- _context.next = 2;
68
+ _context.next = 3;
44
69
  break;
45
70
  }
71
+ this.mountCanvasLayer();
46
72
  return _context.abrupt("return", true);
47
- case 2:
73
+ case 3:
48
74
  if (this.tmodel.hasDom()) {
49
- _context.next = 4;
75
+ _context.next = 5;
50
76
  break;
51
77
  }
52
78
  return _context.abrupt("return", false);
53
- case 4:
79
+ case 5:
54
80
  if (!this.initializationPromise) {
55
81
  this.initializationPromise = this.initialize().catch(function (error) {
56
82
  _this.initializationPromise = undefined;
57
83
  throw error;
58
84
  });
59
85
  }
60
- _context.next = 7;
86
+ _context.next = 8;
61
87
  return this.initializationPromise;
62
- case 7:
63
- return _context.abrupt("return", !!this.device);
64
88
  case 8:
89
+ return _context.abrupt("return", !!this.device);
90
+ case 9:
65
91
  case "end":
66
92
  return _context.stop();
67
93
  }
@@ -119,11 +145,13 @@ var ParticleRenderer = /*#__PURE__*/function () {
119
145
  this.context.configure({
120
146
  device: this.device,
121
147
  format: this.format,
122
- alphaMode: "premultiplied"
148
+ alphaMode: "premultiplied",
149
+ usage: globalThis.GPUTextureUsage.RENDER_ATTACHMENT | globalThis.GPUTextureUsage.COPY_SRC
123
150
  });
124
151
  this.createUniformBuffer();
152
+ this.createExplodeResources();
125
153
  this.createPipeline();
126
- case 21:
154
+ case 22:
127
155
  case "end":
128
156
  return _context2.stop();
129
157
  }
@@ -137,18 +165,11 @@ var ParticleRenderer = /*#__PURE__*/function () {
137
165
  }, {
138
166
  key: "createCanvas",
139
167
  value: function createCanvas() {
140
- var _this$tmodel$$dom;
168
+ var _this2 = this;
141
169
  if (this.canvas) {
170
+ this.mountCanvasLayer();
142
171
  return;
143
172
  }
144
- var parent = (_this$tmodel$$dom = this.tmodel.$dom) === null || _this$tmodel$$dom === void 0 ? void 0 : _this$tmodel$$dom.element;
145
- if (!parent) {
146
- throw new Error("Unable to create a GPU child layer without a parent DOM element.");
147
- }
148
- var oldLayer = parent.querySelector('[data-targetjs-gpu-layer="true"]');
149
- if (oldLayer) {
150
- oldLayer.remove();
151
- }
152
173
  this.canvasLayer = document.createElement("div");
153
174
  this.canvasLayer.setAttribute("data-targetjs-gpu-layer", "true");
154
175
  Object.assign(this.canvasLayer.style, {
@@ -162,8 +183,11 @@ var ParticleRenderer = /*#__PURE__*/function () {
162
183
  });
163
184
  this.canvas = document.createElement("canvas");
164
185
  this.canvas.setAttribute("data-targetjs-gpu-children", "true");
186
+ this.canvas.captureBitmap = function () {
187
+ return _this2.captureBitmap();
188
+ };
165
189
  Object.assign(this.canvas.style, {
166
- position: "sticky",
190
+ position: "absolute",
167
191
  left: "0px",
168
192
  top: "0px",
169
193
  width: "1px",
@@ -172,7 +196,13 @@ var ParticleRenderer = /*#__PURE__*/function () {
172
196
  pointerEvents: "none"
173
197
  });
174
198
  this.canvasLayer.appendChild(this.canvas);
175
- parent.prepend(this.canvasLayer);
199
+ if (!this.mountCanvasLayer()) {
200
+ throw new Error("Unable to mount GPU child layer.");
201
+ }
202
+ this.onScroll = function () {
203
+ return _this2.tmodel.requestParticleRender();
204
+ };
205
+ this.updateScrollElements();
176
206
  }
177
207
  }, {
178
208
  key: "createUniformBuffer",
@@ -182,11 +212,38 @@ var ParticleRenderer = /*#__PURE__*/function () {
182
212
  usage: globalThis.GPUBufferUsage.UNIFORM | globalThis.GPUBufferUsage.COPY_DST
183
213
  });
184
214
  }
215
+ }, {
216
+ key: "createExplodeResources",
217
+ value: function createExplodeResources() {
218
+ this.explodeSampler = this.device.createSampler({
219
+ addressModeU: "clamp-to-edge",
220
+ addressModeV: "clamp-to-edge",
221
+ magFilter: "linear",
222
+ minFilter: "linear"
223
+ });
224
+ this.explodeTexture = this.device.createTexture({
225
+ size: {
226
+ width: 1,
227
+ height: 1
228
+ },
229
+ format: "rgba8unorm",
230
+ usage: globalThis.GPUTextureUsage.TEXTURE_BINDING | globalThis.GPUTextureUsage.COPY_DST
231
+ });
232
+ this.device.queue.writeTexture({
233
+ texture: this.explodeTexture
234
+ }, new Uint8Array([0, 0, 0, 0]), {
235
+ bytesPerRow: 4
236
+ }, {
237
+ width: 1,
238
+ height: 1
239
+ });
240
+ this.explodeTextureReady = false;
241
+ }
185
242
  }, {
186
243
  key: "createPipeline",
187
244
  value: function createPipeline() {
188
245
  var shaderModule = this.device.createShaderModule({
189
- code: "\n struct Uniforms {\n viewport: vec2f,\n contentOffset: vec2f,\n step: f32,\n transitionActive: f32,\n padding: vec2f,\n }\n\n @group(0) @binding(0)\n var<uniform> uniforms: Uniforms;\n\n struct VertexOutput {\n @builtin(position) position: vec4f,\n @location(0) localPosition: vec2f,\n @location(1) backgroundColor: vec4f,\n @location(2) size: vec2f,\n @location(3) borderRadius: f32,\n }\n\n fn getProgress(step: f32, steps: f32) -> f32 {\n if (uniforms.transitionActive < 0.5) {\n return 0.0;\n }\n\n if (steps < 0.0) {\n return 0.0;\n }\n\n if (steps == 0.0) {\n return 1.0;\n }\n\n return clamp(step / steps, 0.0, 1.0);\n }\n\n @vertex\n fn vertexMain(\n @location(0) childPosition: vec2f,\n @location(1) childSize: vec2f,\n @location(2) childBackgroundColor: vec4f,\n @location(3) childGeometry: vec2f,\n @location(4) targetPosition: vec2f,\n @location(5) targetSize: vec2f,\n @location(6) targetBackgroundColor: vec4f,\n @location(7) targetGeometry: vec2f,\n @location(8) targetPositionSteps: vec2f,\n @location(9) targetSizeSteps: vec2f,\n @location(10) targetBackgroundColorSteps: f32,\n @location(11) targetGeometrySteps: vec2f,\n @builtin(vertex_index) vertexIndex: u32\n ) -> VertexOutput {\n let corners = array<vec2f, 6>(\n vec2f(-1.0, -1.0),\n vec2f( 1.0, -1.0),\n vec2f(-1.0, 1.0),\n vec2f(-1.0, 1.0),\n vec2f( 1.0, -1.0),\n vec2f( 1.0, 1.0)\n );\n\n let xProgress = getProgress(uniforms.step, targetPositionSteps.x);\n let yProgress = getProgress(uniforms.step, targetPositionSteps.y);\n let widthProgress = getProgress(uniforms.step, targetSizeSteps.x);\n let heightProgress = getProgress(uniforms.step, targetSizeSteps.y);\n let backgroundColorProgress = getProgress(uniforms.step, targetBackgroundColorSteps);\n let borderRadiusProgress = getProgress(uniforms.step, targetGeometrySteps.x);\n let rotateProgress = getProgress(uniforms.step, targetGeometrySteps.y);\n\n let position = vec2f(\n mix(childPosition.x, targetPosition.x, xProgress),\n mix(childPosition.y, targetPosition.y, yProgress)\n );\n\n let size = vec2f(\n mix(childSize.x, targetSize.x, widthProgress),\n mix(childSize.y, targetSize.y, heightProgress)\n );\n\n let backgroundColor = mix(childBackgroundColor, targetBackgroundColor, backgroundColorProgress);\n let borderRadius = mix(childGeometry.x, targetGeometry.x, borderRadiusProgress);\n let rotate = mix(childGeometry.y, targetGeometry.y, rotateProgress);\n let localPosition = corners[vertexIndex];\n let localPixelPosition = localPosition * size * 0.5;\n let angle = rotate * 3.141592653589793 / 180.0;\n let cosine = cos(angle);\n let sine = sin(angle);\n\n let rotatedPosition = vec2f(\n localPixelPosition.x * cosine - localPixelPosition.y * sine,\n localPixelPosition.x * sine + localPixelPosition.y * cosine\n );\n\n let elementCenter = position - uniforms.contentOffset + size * 0.5;\n let pixelPosition = elementCenter + rotatedPosition;\n\n let clipPosition = vec2f(\n pixelPosition.x / uniforms.viewport.x * 2.0 - 1.0,\n 1.0 - pixelPosition.y / uniforms.viewport.y * 2.0\n );\n\n var output: VertexOutput;\n\n output.position = vec4f(clipPosition, 0.0, 1.0);\n output.localPosition = localPosition;\n output.backgroundColor = backgroundColor;\n output.size = size;\n output.borderRadius = borderRadius;\n\n return output;\n }\n\n @fragment\n fn fragmentMain(input: VertexOutput) -> @location(0) vec4f {\n let halfSize = max(input.size * 0.5, vec2f(0.0001));\n let radius = clamp(input.borderRadius, 0.0, min(halfSize.x, halfSize.y));\n\n if (radius > 0.0) {\n let pixelPosition = input.localPosition * halfSize;\n let q = abs(pixelPosition) - (halfSize - vec2f(radius));\n let distance = length(max(q, vec2f(0.0))) + min(max(q.x, q.y), 0.0) - radius;\n\n if (distance > 0.0) {\n discard;\n }\n }\n\n return input.backgroundColor;\n }\n "
246
+ code: "\n struct Uniforms {\n viewport: vec2f,\n contentOffset: vec2f,\n step: f32,\n transitionActive: f32,\n padding: vec2f,\n }\n\n @group(0) @binding(0)\n var<uniform> uniforms: Uniforms;\n \n @group(0) @binding(1)\n var explodeSampler: sampler;\n\n @group(0) @binding(2)\n var explodeTexture: texture_2d<f32>;\n\n struct VertexOutput {\n @builtin(position) position: vec4f,\n @location(0) localPosition: vec2f,\n @location(1) backgroundColor: vec4f,\n @location(2) size: vec2f,\n @location(3) borderRadius: f32,\n @location(4) sourceUv: vec2f,\n @location(5) useImage: f32,\n @location(6) opacity: f32,\n }\n \n fn getProgress(step: f32, steps: f32) -> f32 {\n if (uniforms.transitionActive < 0.5) {\n return 0.0;\n }\n\n if (steps < 0.0) {\n return 0.0;\n }\n\n if (steps == 0.0) {\n return 1.0;\n }\n\n return clamp(step / steps, 0.0, 1.0);\n }\n\n @vertex\n fn vertexMain(\n @location(0) childPosition: vec2f,\n @location(1) childSize: vec2f,\n @location(2) childBackgroundColor: vec4f,\n @location(3) childGeometry: vec2f,\n @location(4) targetPosition: vec2f,\n @location(5) targetSize: vec2f,\n @location(6) targetBackgroundColor: vec4f,\n @location(7) targetGeometry: vec2f,\n @location(8) targetPositionSteps: vec2f,\n @location(9) targetSizeSteps: vec2f,\n @location(10) targetColorOpacitySteps: vec2f,\n @location(11) targetGeometrySteps: vec2f,\n @location(12) childScaleOpacity: vec2f,\n @location(13) targetScaleOpacity: vec2f,\n @location(14) targetScaleSteps: f32,\n @location(15) explodeData: vec4f,\n @builtin(vertex_index) vertexIndex: u32\n ) -> VertexOutput {\n let corners = array<vec2f, 6>(\n vec2f(-1.0, -1.0),\n vec2f( 1.0, -1.0),\n vec2f(-1.0, 1.0),\n vec2f(-1.0, 1.0),\n vec2f( 1.0, -1.0),\n vec2f( 1.0, 1.0)\n );\n\n let xProgress = getProgress(uniforms.step, targetPositionSteps.x);\n let yProgress = getProgress(uniforms.step, targetPositionSteps.y);\n let widthProgress = getProgress(uniforms.step, targetSizeSteps.x);\n let heightProgress = getProgress(uniforms.step, targetSizeSteps.y);\n let backgroundColorProgress = getProgress(uniforms.step, targetColorOpacitySteps.x);\n let opacityProgress = getProgress(uniforms.step, targetColorOpacitySteps.y);\n let borderRadiusProgress = getProgress(uniforms.step, targetGeometrySteps.x);\n let rotateProgress = getProgress(uniforms.step, targetGeometrySteps.y);\n let scaleProgress = getProgress(uniforms.step, targetScaleSteps);\n \n let position = vec2f(\n mix(childPosition.x, targetPosition.x, xProgress),\n mix(childPosition.y, targetPosition.y, yProgress)\n );\n\n let size = vec2f(\n mix(childSize.x, targetSize.x, widthProgress),\n mix(childSize.y, targetSize.y, heightProgress)\n );\n\n let backgroundColor = mix(childBackgroundColor, targetBackgroundColor, backgroundColorProgress);\n let borderRadius = mix(childGeometry.x, targetGeometry.x, borderRadiusProgress);\n let rotate = mix(childGeometry.y, targetGeometry.y, rotateProgress);\n let scale = mix(childScaleOpacity.x, targetScaleOpacity.x, scaleProgress);\n let opacity = mix(childScaleOpacity.y, targetScaleOpacity.y, opacityProgress);\n\n let localPosition = corners[vertexIndex];\n \n let useImage = explodeData.w >= 0.0;\n let sourceV1 = select(-explodeData.w - 1.0, explodeData.w, useImage);\n let localUv = localPosition * 0.5 + vec2f(0.5);\n let sourceUv = mix(explodeData.xy, vec2f(explodeData.z, sourceV1), localUv);\n \n let localPixelPosition = localPosition * size * 0.5 * scale;\n\n let angle = rotate * 3.141592653589793 / 180.0;\n let cosine = cos(angle);\n let sine = sin(angle);\n\n let rotatedPosition = vec2f(\n localPixelPosition.x * cosine - localPixelPosition.y * sine,\n localPixelPosition.x * sine + localPixelPosition.y * cosine\n );\n\n let elementCenter = position - uniforms.contentOffset + size * 0.5;\n let pixelPosition = elementCenter + rotatedPosition;\n\n let clipPosition = vec2f(\n pixelPosition.x / uniforms.viewport.x * 2.0 - 1.0,\n 1.0 - pixelPosition.y / uniforms.viewport.y * 2.0\n );\n\n var output: VertexOutput;\n\n output.position = vec4f(clipPosition, 0.0, 1.0);\n output.localPosition = localPosition;\n output.backgroundColor = backgroundColor;\n output.size = size;\n output.borderRadius = borderRadius;\n output.opacity = opacity;\n \n output.sourceUv = sourceUv;\n output.useImage = select(0.0, 1.0, useImage);\n\n return output;\n }\n\n @fragment\n fn fragmentMain(input: VertexOutput) -> @location(0) vec4f {\n var color = input.backgroundColor;\n\n if (input.useImage > 0.5) {\n color = textureSampleLevel(explodeTexture, explodeSampler, input.sourceUv, 0.0);\n }\n\n let halfSize = max(input.size * 0.5, vec2f(0.0001));\n let radius = clamp(input.borderRadius, 0.0, min(halfSize.x, halfSize.y));\n let pixelPosition = input.localPosition * halfSize;\n let q = abs(pixelPosition) - (halfSize - vec2f(radius));\n let distance = length(max(q, vec2f(0.0))) + min(max(q.x, q.y), 0.0) - radius;\n let aa = max(fwidth(distance), 0.0001);\n let roundedCoverage = 1.0 - smoothstep(-aa, aa, distance);\n let coverage = select(1.0, roundedCoverage, radius > 0.0);\n\n if (coverage <= 0.0) {\n discard;\n }\n\n let alpha = color.a * input.opacity * coverage;\n\n return vec4f(color.rgb * alpha, alpha);\n }\n "
190
247
  });
191
248
  this.pipeline = this.device.createRenderPipeline({
192
249
  layout: "auto",
@@ -194,7 +251,7 @@ var ParticleRenderer = /*#__PURE__*/function () {
194
251
  module: shaderModule,
195
252
  entryPoint: "vertexMain",
196
253
  buffers: [{
197
- arrayStride: 80,
254
+ arrayStride: 84,
198
255
  stepMode: "instance",
199
256
  attributes: [{
200
257
  shaderLocation: 0,
@@ -212,9 +269,13 @@ var ParticleRenderer = /*#__PURE__*/function () {
212
269
  shaderLocation: 3,
213
270
  offset: 32,
214
271
  format: "float32x2"
272
+ }, {
273
+ shaderLocation: 12,
274
+ offset: 72,
275
+ format: "float32x2"
215
276
  }]
216
277
  }, {
217
- arrayStride: 80,
278
+ arrayStride: 84,
218
279
  stepMode: "instance",
219
280
  attributes: [{
220
281
  shaderLocation: 4,
@@ -243,11 +304,27 @@ var ParticleRenderer = /*#__PURE__*/function () {
243
304
  }, {
244
305
  shaderLocation: 10,
245
306
  offset: 56,
246
- format: "float32"
307
+ format: "float32x2"
247
308
  }, {
248
309
  shaderLocation: 11,
249
- offset: 60,
310
+ offset: 64,
311
+ format: "float32x2"
312
+ }, {
313
+ shaderLocation: 13,
314
+ offset: 72,
250
315
  format: "float32x2"
316
+ }, {
317
+ shaderLocation: 14,
318
+ offset: 80,
319
+ format: "float32"
320
+ }]
321
+ }, {
322
+ arrayStride: 16,
323
+ stepMode: "instance",
324
+ attributes: [{
325
+ shaderLocation: 15,
326
+ offset: 0,
327
+ format: "float32x4"
251
328
  }]
252
329
  }]
253
330
  },
@@ -255,13 +332,30 @@ var ParticleRenderer = /*#__PURE__*/function () {
255
332
  module: shaderModule,
256
333
  entryPoint: "fragmentMain",
257
334
  targets: [{
258
- format: this.format
335
+ format: this.format,
336
+ blend: {
337
+ color: {
338
+ srcFactor: "one",
339
+ dstFactor: "one-minus-src-alpha",
340
+ operation: "add"
341
+ },
342
+ alpha: {
343
+ srcFactor: "one",
344
+ dstFactor: "one-minus-src-alpha",
345
+ operation: "add"
346
+ }
347
+ }
259
348
  }]
260
349
  },
261
350
  primitive: {
262
351
  topology: "triangle-list"
263
352
  }
264
353
  });
354
+ this.createBindGroup();
355
+ }
356
+ }, {
357
+ key: "createBindGroup",
358
+ value: function createBindGroup() {
265
359
  this.bindGroup = this.device.createBindGroup({
266
360
  layout: this.pipeline.getBindGroupLayout(0),
267
361
  entries: [{
@@ -269,9 +363,151 @@ var ParticleRenderer = /*#__PURE__*/function () {
269
363
  resource: {
270
364
  buffer: this.uniformBuffer
271
365
  }
366
+ }, {
367
+ binding: 1,
368
+ resource: this.explodeSampler
369
+ }, {
370
+ binding: 2,
371
+ resource: this.explodeTexture.createView()
272
372
  }]
273
373
  });
274
374
  }
375
+ }, {
376
+ key: "createExplodeSourceCanvas",
377
+ value: function createExplodeSourceCanvas(source) {
378
+ var width = source === null || source === void 0 ? void 0 : source.width;
379
+ var height = source === null || source === void 0 ? void 0 : source.height;
380
+ if (!width || !height) {
381
+ return;
382
+ }
383
+ var canvas = document.createElement("canvas");
384
+ canvas.width = width;
385
+ canvas.height = height;
386
+ var context = canvas.getContext("2d");
387
+ if (!context) {
388
+ throw new Error("Could not create a 2D context for the explode source copy.");
389
+ }
390
+ context.drawImage(source, 0, 0, width, height);
391
+ return canvas;
392
+ }
393
+ }, {
394
+ key: "setExplodeSource",
395
+ value: function () {
396
+ var _setExplodeSource = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(capture) {
397
+ var _capture$bitmap, _capture$canvas, _this$explodeTexture;
398
+ var source, sourceCanvas, initialized, width, height, texture;
399
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
400
+ while (1) switch (_context3.prev = _context3.next) {
401
+ case 0:
402
+ source = (_capture$bitmap = capture === null || capture === void 0 ? void 0 : capture.bitmap) !== null && _capture$bitmap !== void 0 ? _capture$bitmap : capture === null || capture === void 0 ? void 0 : capture.canvas;
403
+ if (source) {
404
+ _context3.next = 3;
405
+ break;
406
+ }
407
+ return _context3.abrupt("return", false);
408
+ case 3:
409
+ sourceCanvas = (_capture$canvas = capture === null || capture === void 0 ? void 0 : capture.canvas) !== null && _capture$canvas !== void 0 ? _capture$canvas : this.createExplodeSourceCanvas(source);
410
+ if (sourceCanvas) {
411
+ _context3.next = 6;
412
+ break;
413
+ }
414
+ return _context3.abrupt("return", false);
415
+ case 6:
416
+ _context3.next = 8;
417
+ return this.init();
418
+ case 8:
419
+ initialized = _context3.sent;
420
+ if (initialized) {
421
+ _context3.next = 11;
422
+ break;
423
+ }
424
+ return _context3.abrupt("return", false);
425
+ case 11:
426
+ width = sourceCanvas.width;
427
+ height = sourceCanvas.height;
428
+ texture = this.device.createTexture({
429
+ size: {
430
+ width: width,
431
+ height: height
432
+ },
433
+ format: "rgba8unorm",
434
+ usage: globalThis.GPUTextureUsage.TEXTURE_BINDING | globalThis.GPUTextureUsage.COPY_DST | globalThis.GPUTextureUsage.RENDER_ATTACHMENT
435
+ });
436
+ this.device.queue.copyExternalImageToTexture({
437
+ source: sourceCanvas
438
+ }, {
439
+ texture: texture
440
+ }, {
441
+ width: width,
442
+ height: height
443
+ });
444
+ (_this$explodeTexture = this.explodeTexture) === null || _this$explodeTexture === void 0 || _this$explodeTexture.destroy();
445
+ this.explodeSourceCanvas = sourceCanvas;
446
+ this.explodeTexture = texture;
447
+ this.explodeTextureReady = true;
448
+ this.updateExplodeFragmentBuffer(this.tmodel.childHandles);
449
+ this.createBindGroup();
450
+ this.render();
451
+ return _context3.abrupt("return", true);
452
+ case 23:
453
+ case "end":
454
+ return _context3.stop();
455
+ }
456
+ }, _callee3, this);
457
+ }));
458
+ function setExplodeSource(_x) {
459
+ return _setExplodeSource.apply(this, arguments);
460
+ }
461
+ return setExplodeSource;
462
+ }()
463
+ }, {
464
+ key: "captureExplodeSourceBitmap",
465
+ value: function captureExplodeSourceBitmap() {
466
+ if (!this.explodeSourceCanvas) {
467
+ return;
468
+ }
469
+ return createImageBitmap(this.explodeSourceCanvas);
470
+ }
471
+ }, {
472
+ key: "createExplodeFragmentData",
473
+ value: function createExplodeFragmentData(children) {
474
+ var data = new Float32Array(children.length * 4);
475
+ var state = this.tmodel.explodeChildrenState;
476
+ var sourceWidth = (state === null || state === void 0 ? void 0 : state.width) || 1;
477
+ var sourceHeight = (state === null || state === void 0 ? void 0 : state.height) || 1;
478
+ for (var index = 0; index < children.length; index++) {
479
+ var child = children[index];
480
+ var childIndex = Number.isInteger(child === null || child === void 0 ? void 0 : child.index) ? child.index : index;
481
+ var fragment = this.tmodel.getExplodeFragment(childIndex);
482
+ var offset = index * 4;
483
+ if (!fragment) {
484
+ data[offset] = 0;
485
+ data[offset + 1] = 0;
486
+ data[offset + 2] = 0;
487
+ data[offset + 3] = -1;
488
+ continue;
489
+ }
490
+ var u0 = fragment.x / sourceWidth;
491
+ var v0 = fragment.y / sourceHeight;
492
+ var u1 = (fragment.x + fragment.width) / sourceWidth;
493
+ var v1 = (fragment.y + fragment.height) / sourceHeight;
494
+ var hasBackground = TUtil.isDefined(child.actualValues.backgroundColor);
495
+ var useImage = this.explodeTextureReady && !hasBackground;
496
+ data[offset] = u0;
497
+ data[offset + 1] = v0;
498
+ data[offset + 2] = u1;
499
+
500
+ // A negative fourth value means image:false.
501
+ data[offset + 3] = useImage ? v1 : -(v1 + 1);
502
+ }
503
+ return data;
504
+ }
505
+ }, {
506
+ key: "updateExplodeFragmentBuffer",
507
+ value: function updateExplodeFragmentBuffer(children) {
508
+ var data = this.createExplodeFragmentData(children);
509
+ this.explodeFragmentBuffer = this.uploadParticleBuffer(this.explodeFragmentBuffer, data);
510
+ }
275
511
  }, {
276
512
  key: "toNumber",
277
513
  value: function toNumber(value) {
@@ -282,18 +518,21 @@ var ParticleRenderer = /*#__PURE__*/function () {
282
518
  }, {
283
519
  key: "getBackgroundColor",
284
520
  value: function getBackgroundColor(value) {
521
+ if (!TUtil.isDefined(value)) {
522
+ return [0, 0, 0, 0];
523
+ }
285
524
  if (Array.isArray(value)) {
286
- return [this.toNumber(value[0], 1), this.toNumber(value[1], 1), this.toNumber(value[2], 1), this.toNumber(value[3], 1)];
525
+ return [this.toNumber(value[0], 0), this.toNumber(value[1], 0), this.toNumber(value[2], 0), this.toNumber(value[3], 0)];
287
526
  }
288
- var color = ColorUtil.color2Integers(value !== null && value !== void 0 ? value : "#fff");
527
+ var color = ColorUtil.color2Integers(value);
289
528
  if (!color) {
290
- return [1, 1, 1, 1];
529
+ return [0, 0, 0, 0];
291
530
  }
292
531
  var alpha = this.toNumber(color[3], 1);
293
532
  if (alpha > 1) {
294
533
  alpha /= 255;
295
534
  }
296
- return [this.toNumber(color[0], 255) / 255, this.toNumber(color[1], 255) / 255, this.toNumber(color[2], 255) / 255, alpha];
535
+ return [this.toNumber(color[0], 0) / 255, this.toNumber(color[1], 0) / 255, this.toNumber(color[2], 0) / 255, alpha];
297
536
  }
298
537
  }, {
299
538
  key: "getTargetStep",
@@ -303,32 +542,61 @@ var ParticleRenderer = /*#__PURE__*/function () {
303
542
  }
304
543
  return Math.max(0, this.toNumber(steps[key], 0));
305
544
  }
545
+ }, {
546
+ key: "writeParticleData",
547
+ value: function writeParticleData(particleData, offset, values, steps) {
548
+ var _values, _values2;
549
+ var x = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : (_values = values) === null || _values === void 0 ? void 0 : _values.x;
550
+ var y = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : (_values2 = values) === null || _values2 === void 0 ? void 0 : _values2.y;
551
+ values || (values = {});
552
+ var backgroundColor = this.getBackgroundColor(values.backgroundColor);
553
+ var opacity = Math.max(0, Math.min(1, this.toNumber(values.opacity, 1)));
554
+ particleData[offset] = this.toNumber(x, 0);
555
+ particleData[offset + 1] = this.toNumber(y, 0);
556
+ particleData[offset + 2] = this.toNumber(values.width, 0);
557
+ particleData[offset + 3] = this.toNumber(values.height, 0);
558
+ particleData[offset + 4] = backgroundColor[0];
559
+ particleData[offset + 5] = backgroundColor[1];
560
+ particleData[offset + 6] = backgroundColor[2];
561
+ particleData[offset + 7] = backgroundColor[3];
562
+ particleData[offset + 8] = Math.max(0, this.toNumber(values.borderRadius, 0));
563
+ particleData[offset + 9] = this.toNumber(values.rotate, 0);
564
+ particleData[offset + 10] = this.getTargetStep(steps, "x");
565
+ particleData[offset + 11] = this.getTargetStep(steps, "y");
566
+ particleData[offset + 12] = this.getTargetStep(steps, "width");
567
+ particleData[offset + 13] = this.getTargetStep(steps, "height");
568
+ particleData[offset + 14] = this.getTargetStep(steps, "backgroundColor");
569
+ particleData[offset + 15] = this.getTargetStep(steps, "opacity");
570
+ particleData[offset + 16] = this.getTargetStep(steps, "borderRadius");
571
+ particleData[offset + 17] = this.getTargetStep(steps, "rotate");
572
+ particleData[offset + 18] = this.toNumber(values.scale, 1);
573
+ particleData[offset + 19] = opacity;
574
+ particleData[offset + 20] = this.getTargetStep(steps, "scale");
575
+ }
576
+ }, {
577
+ key: "createChildData",
578
+ value: function createChildData(children) {
579
+ var particleData = new Float32Array(children.length * 21);
580
+ for (var i = 0; i < children.length; i++) {
581
+ var child = children[i];
582
+ var values = child.actualValues;
583
+ var _this$getParticlePosi = this.getParticlePosition(child, values),
584
+ x = _this$getParticlePosi.x,
585
+ y = _this$getParticlePosi.y;
586
+ this.writeParticleData(particleData, i * 21, values, undefined, x, y);
587
+ }
588
+ return particleData;
589
+ }
306
590
  }, {
307
591
  key: "createParticleData",
308
592
  value: function createParticleData(values, targetSteps) {
309
- var particleData = new Float32Array(values.length * 20);
593
+ var particleData = new Float32Array(values.length * 21);
310
594
  for (var i = 0; i < values.length; i++) {
311
- var child = values[i] || {};
312
- var steps = targetSteps === null || targetSteps === void 0 ? void 0 : targetSteps[i];
313
- var backgroundColor = this.getBackgroundColor(child.backgroundColor);
314
- var offset = i * 20;
315
- particleData[offset] = this.toNumber(child.x, 0);
316
- particleData[offset + 1] = this.toNumber(child.y, 0);
317
- particleData[offset + 2] = this.toNumber(child.width, 0);
318
- particleData[offset + 3] = this.toNumber(child.height, 0);
319
- particleData[offset + 4] = backgroundColor[0];
320
- particleData[offset + 5] = backgroundColor[1];
321
- particleData[offset + 6] = backgroundColor[2];
322
- particleData[offset + 7] = backgroundColor[3];
323
- particleData[offset + 8] = Math.max(0, this.toNumber(child.borderRadius, 0));
324
- particleData[offset + 9] = this.toNumber(child.rotate, 0);
325
- particleData[offset + 10] = this.getTargetStep(steps, "x");
326
- particleData[offset + 11] = this.getTargetStep(steps, "y");
327
- particleData[offset + 12] = this.getTargetStep(steps, "width");
328
- particleData[offset + 13] = this.getTargetStep(steps, "height");
329
- particleData[offset + 14] = this.getTargetStep(steps, "backgroundColor");
330
- particleData[offset + 15] = this.getTargetStep(steps, "borderRadius");
331
- particleData[offset + 16] = this.getTargetStep(steps, "rotate");
595
+ var child = this.tmodel.childHandles[i];
596
+ var _this$getParticlePosi2 = this.getParticlePosition(child, values[i]),
597
+ x = _this$getParticlePosi2.x,
598
+ y = _this$getParticlePosi2.y;
599
+ this.writeParticleData(particleData, i * 21, values[i], targetSteps === null || targetSteps === void 0 ? void 0 : targetSteps[i], x, y);
332
600
  }
333
601
  return particleData;
334
602
  }
@@ -354,36 +622,41 @@ var ParticleRenderer = /*#__PURE__*/function () {
354
622
  }, {
355
623
  key: "setParticles",
356
624
  value: function () {
357
- var _setParticles = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(values) {
625
+ var _setParticles = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(children) {
358
626
  var initialized, particleData;
359
- return _regeneratorRuntime().wrap(function _callee3$(_context3) {
360
- while (1) switch (_context3.prev = _context3.next) {
627
+ return _regeneratorRuntime().wrap(function _callee4$(_context4) {
628
+ while (1) switch (_context4.prev = _context4.next) {
361
629
  case 0:
362
- values = Array.isArray(values) ? values : [values];
363
- _context3.next = 3;
630
+ children = Array.isArray(children) ? children : [children];
631
+ _context4.next = 3;
364
632
  return this.init();
365
633
  case 3:
366
- initialized = _context3.sent;
634
+ initialized = _context4.sent;
367
635
  if (initialized) {
368
- _context3.next = 6;
636
+ _context4.next = 6;
369
637
  break;
370
638
  }
371
- return _context3.abrupt("return");
639
+ return _context4.abrupt("return", false);
372
640
  case 6:
373
- particleData = this.createParticleData(values);
374
- this.particleCount = values.length;
641
+ particleData = this.createChildData(children);
642
+ this.updateExplodeFragmentBuffer(children);
643
+ this.particleCount = children.length;
644
+ this.currentParticleData = particleData;
645
+ this.targetParticleData = particleData;
375
646
  this.particleBuffer = this.uploadParticleBuffer(this.particleBuffer, particleData);
376
647
  this.targetParticleBuffer = this.uploadParticleBuffer(this.targetParticleBuffer, particleData);
377
648
  this.transitionStep = 0;
378
649
  this.transitionActive = false;
650
+ this.boundsDirty = true;
379
651
  this.render();
380
- case 13:
652
+ return _context4.abrupt("return", true);
653
+ case 18:
381
654
  case "end":
382
- return _context3.stop();
655
+ return _context4.stop();
383
656
  }
384
- }, _callee3, this);
657
+ }, _callee4, this);
385
658
  }));
386
- function setParticles(_x) {
659
+ function setParticles(_x2) {
387
660
  return _setParticles.apply(this, arguments);
388
661
  }
389
662
  return setParticles;
@@ -391,36 +664,45 @@ var ParticleRenderer = /*#__PURE__*/function () {
391
664
  }, {
392
665
  key: "updateParticles",
393
666
  value: function () {
394
- var _updateParticles = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(values) {
667
+ var _updateParticles = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(children) {
395
668
  var initialized, particleData;
396
- return _regeneratorRuntime().wrap(function _callee4$(_context4) {
397
- while (1) switch (_context4.prev = _context4.next) {
669
+ return _regeneratorRuntime().wrap(function _callee5$(_context5) {
670
+ while (1) switch (_context5.prev = _context5.next) {
398
671
  case 0:
399
- values = Array.isArray(values) ? values : [values];
400
- _context4.next = 3;
672
+ children = Array.isArray(children) ? children : [children];
673
+ _context5.next = 3;
401
674
  return this.init();
402
675
  case 3:
403
- initialized = _context4.sent;
676
+ initialized = _context5.sent;
404
677
  if (initialized) {
405
- _context4.next = 6;
678
+ _context5.next = 6;
406
679
  break;
407
680
  }
408
- return _context4.abrupt("return");
681
+ return _context5.abrupt("return", false);
409
682
  case 6:
410
- particleData = this.createParticleData(values);
411
- this.particleCount = values.length;
683
+ particleData = this.createChildData(children);
684
+ this.updateExplodeFragmentBuffer(children);
685
+ this.particleCount = children.length;
686
+ this.currentParticleData = particleData;
412
687
  this.particleBuffer = this.uploadParticleBuffer(this.particleBuffer, particleData);
413
- if (!this.transitionActive) {
688
+ if (!children.length || !this.transitionActive) {
689
+ this.targetParticleData = particleData;
414
690
  this.targetParticleBuffer = this.uploadParticleBuffer(this.targetParticleBuffer, particleData);
415
691
  }
692
+ if (!children.length) {
693
+ this.transitionStep = 0;
694
+ this.transitionActive = false;
695
+ }
696
+ this.boundsDirty = true;
416
697
  this.render();
417
- case 11:
698
+ return _context5.abrupt("return", true);
699
+ case 16:
418
700
  case "end":
419
- return _context4.stop();
701
+ return _context5.stop();
420
702
  }
421
- }, _callee4, this);
703
+ }, _callee5, this);
422
704
  }));
423
- function updateParticles(_x2) {
705
+ function updateParticles(_x3) {
424
706
  return _updateParticles.apply(this, arguments);
425
707
  }
426
708
  return updateParticles;
@@ -428,40 +710,56 @@ var ParticleRenderer = /*#__PURE__*/function () {
428
710
  }, {
429
711
  key: "setTargetParticles",
430
712
  value: function () {
431
- var _setTargetParticles = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(values, steps) {
432
- var initialized, particleData;
433
- return _regeneratorRuntime().wrap(function _callee5$(_context5) {
434
- while (1) switch (_context5.prev = _context5.next) {
713
+ var _setTargetParticles = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(values, steps) {
714
+ var generation,
715
+ initialized,
716
+ currentChildren,
717
+ currentParticleData,
718
+ particleData,
719
+ _args6 = arguments;
720
+ return _regeneratorRuntime().wrap(function _callee6$(_context6) {
721
+ while (1) switch (_context6.prev = _context6.next) {
435
722
  case 0:
723
+ generation = _args6.length > 2 && _args6[2] !== undefined ? _args6[2] : this.tmodel.childGeneration;
436
724
  values = Array.isArray(values) ? values : [values];
437
- _context5.next = 3;
725
+ _context6.next = 4;
438
726
  return this.init();
439
- case 3:
440
- initialized = _context5.sent;
441
- if (initialized) {
442
- _context5.next = 6;
727
+ case 4:
728
+ initialized = _context6.sent;
729
+ if (!(!initialized || generation !== this.tmodel.childGeneration)) {
730
+ _context6.next = 7;
443
731
  break;
444
732
  }
445
- return _context5.abrupt("return");
446
- case 6:
447
- if (!(this.particleCount && values.length !== this.particleCount)) {
448
- _context5.next = 8;
733
+ return _context6.abrupt("return", false);
734
+ case 7:
735
+ currentChildren = this.tmodel.childHandles;
736
+ if (!(values.length !== currentChildren.length)) {
737
+ _context6.next = 10;
449
738
  break;
450
739
  }
451
- throw new Error("GPU child transition count ".concat(values.length, " does not match current child count ").concat(this.particleCount, "."));
452
- case 8:
740
+ return _context6.abrupt("return", false);
741
+ case 10:
742
+ if (this.particleCount !== currentChildren.length || !this.particleBuffer) {
743
+ currentParticleData = this.createChildData(currentChildren);
744
+ this.particleCount = currentChildren.length;
745
+ this.currentParticleData = currentParticleData;
746
+ this.particleBuffer = this.uploadParticleBuffer(this.particleBuffer, currentParticleData);
747
+ }
453
748
  particleData = this.createParticleData(values, steps);
749
+ this.targetParticleData = particleData;
454
750
  this.targetParticleBuffer = this.uploadParticleBuffer(this.targetParticleBuffer, particleData);
455
751
  this.transitionStep = 0;
456
752
  this.transitionActive = true;
753
+ this.boundsDirty = true;
457
754
  this.render();
458
- case 13:
755
+ return _context6.abrupt("return", true);
756
+ case 19:
459
757
  case "end":
460
- return _context5.stop();
758
+ return _context6.stop();
461
759
  }
462
- }, _callee5, this);
760
+ }, _callee6, this);
463
761
  }));
464
- function setTargetParticles(_x3, _x4) {
762
+ function setTargetParticles(_x4, _x5) {
465
763
  return _setTargetParticles.apply(this, arguments);
466
764
  }
467
765
  return setTargetParticles;
@@ -469,45 +767,132 @@ var ParticleRenderer = /*#__PURE__*/function () {
469
767
  }, {
470
768
  key: "setTransitionStep",
471
769
  value: function setTransitionStep(step) {
472
- this.transitionStep = Math.max(0, this.toNumber(step, 0));
770
+ step = Math.max(0, this.toNumber(step, 0));
771
+ if (step === this.transitionStep) {
772
+ return;
773
+ }
774
+ this.transitionStep = step;
473
775
  this.render();
474
776
  }
475
777
  }, {
476
778
  key: "getRenderWidth",
477
779
  value: function getRenderWidth() {
478
- var modelWidth = Number(this.tmodel.getWidth()) || 1;
479
- var parentWidth = Number(this.tmodel.getParent().getWidth()) || window.innerWidth || 1;
480
- return Math.max(1, Math.min(modelWidth, parentWidth));
780
+ return Math.max(1, Number(this.tmodel.getWidth()) || 1);
481
781
  }
482
782
  }, {
483
783
  key: "getRenderHeight",
484
784
  value: function getRenderHeight() {
485
- var _this$tmodel$getParen;
486
- var modelHeight = Number(this.tmodel.getHeight()) || 1;
487
- var parentHeight = Number((_this$tmodel$getParen = this.tmodel.getParent()) === null || _this$tmodel$getParen === void 0 ? void 0 : _this$tmodel$getParen.getHeight()) || window.innerHeight || 1;
488
- return Math.max(1, Math.min(modelHeight, parentHeight));
785
+ return Math.max(1, Number(this.tmodel.getHeight()) || 1);
786
+ }
787
+ }, {
788
+ key: "getParticleBounds",
789
+ value: function getParticleBounds() {
790
+ var modelWidth = this.getRenderWidth();
791
+ var modelHeight = this.getRenderHeight();
792
+ var viewport = this.tmodel.managesOwnScroll();
793
+ var bounds = this.canvasBounds;
794
+ if (!this.boundsDirty && (bounds === null || bounds === void 0 ? void 0 : bounds.modelWidth) === modelWidth && (bounds === null || bounds === void 0 ? void 0 : bounds.modelHeight) === modelHeight && (bounds === null || bounds === void 0 ? void 0 : bounds.viewport) === viewport) {
795
+ return bounds;
796
+ }
797
+ var calculated = viewport ? {
798
+ x: 0,
799
+ y: 0,
800
+ width: modelWidth,
801
+ height: modelHeight
802
+ } : this.calculateParticleBounds();
803
+ this.canvasBounds = _objectSpread(_objectSpread({}, calculated), {}, {
804
+ modelWidth: modelWidth,
805
+ modelHeight: modelHeight,
806
+ viewport: viewport
807
+ });
808
+ this.boundsDirty = false;
809
+ return this.canvasBounds;
810
+ }
811
+ }, {
812
+ key: "calculateParticleBounds",
813
+ value: function calculateParticleBounds() {
814
+ var _this$targetParticleD, _current$length;
815
+ var left = 0;
816
+ var top = 0;
817
+ var right = this.getRenderWidth();
818
+ var bottom = this.getRenderHeight();
819
+ var current = this.currentParticleData;
820
+ var target = (_this$targetParticleD = this.targetParticleData) !== null && _this$targetParticleD !== void 0 ? _this$targetParticleD : current;
821
+ var stride = 21;
822
+ var count = Math.min(this.particleCount, ((_current$length = current === null || current === void 0 ? void 0 : current.length) !== null && _current$length !== void 0 ? _current$length : 0) / stride);
823
+ var safety = 2;
824
+ for (var i = 0; i < count; i++) {
825
+ var j = i * stride;
826
+ var a = current;
827
+ var b = target && target.length >= j + stride ? target : current;
828
+ var minX = Math.min(a[j], b[j]);
829
+ var maxX = Math.max(a[j], b[j]);
830
+ var minY = Math.min(a[j + 1], b[j + 1]);
831
+ var maxY = Math.max(a[j + 1], b[j + 1]);
832
+ var minWidth = Math.min(a[j + 2], b[j + 2]);
833
+ var maxWidth = Math.max(a[j + 2], b[j + 2]);
834
+ var minHeight = Math.min(a[j + 3], b[j + 3]);
835
+ var maxHeight = Math.max(a[j + 3], b[j + 3]);
836
+ var maxScale = Math.max(Math.abs(a[j + 18]), Math.abs(b[j + 18]));
837
+ var radius = Math.hypot(Math.max(Math.abs(a[j + 2]), Math.abs(b[j + 2])), Math.max(Math.abs(a[j + 3]), Math.abs(b[j + 3]))) * maxScale * 0.5 + safety;
838
+ left = Math.min(left, minX + minWidth / 2 - radius);
839
+ right = Math.max(right, maxX + maxWidth / 2 + radius);
840
+ top = Math.min(top, minY + minHeight / 2 - radius);
841
+ bottom = Math.max(bottom, maxY + maxHeight / 2 + radius);
842
+ }
843
+ var x = Math.floor(left);
844
+ var y = Math.floor(top);
845
+ return {
846
+ x: x,
847
+ y: y,
848
+ width: Math.max(1, Math.ceil(right) - x),
849
+ height: Math.max(1, Math.ceil(bottom) - y)
850
+ };
851
+ }
852
+ }, {
853
+ key: "updateCanvasLayerWidthHeight",
854
+ value: function updateCanvasLayerWidthHeight() {
855
+ if (!this.canvasLayer) {
856
+ return;
857
+ }
858
+ var viewport = this.getParticleBounds().viewport;
859
+ var modelWidth = this.getRenderWidth();
860
+ var modelHeight = this.getRenderHeight();
861
+ var width = viewport ? Math.max(modelWidth, Number(this.tmodel.getContentWidth()) || 0) : modelWidth;
862
+ var height = viewport ? Math.max(modelHeight, Number(this.tmodel.getContentHeight()) || 0) : modelHeight;
863
+ if (this.canvasLayer.style.width !== "".concat(width, "px")) {
864
+ this.canvasLayer.style.width = "".concat(width, "px");
865
+ }
866
+ if (this.canvasLayer.style.height !== "".concat(height, "px")) {
867
+ this.canvasLayer.style.height = "".concat(height, "px");
868
+ }
489
869
  }
490
870
  }, {
491
871
  key: "resizeCanvas",
492
872
  value: function resizeCanvas() {
493
873
  var _this$device$limits;
494
874
  if (!this.canvas || !this.device) {
495
- return;
875
+ return false;
496
876
  }
497
- var width = this.getRenderWidth();
498
- var height = this.getRenderHeight();
499
- var requestedPixelRatio = window.devicePixelRatio || 1;
500
- var maxTextureDimension = ((_this$device$limits = this.device.limits) === null || _this$device$limits === void 0 ? void 0 : _this$device$limits.maxTextureDimension2D) || 8192;
501
- var pixelRatio = Math.min(requestedPixelRatio, maxTextureDimension / width, maxTextureDimension / height);
877
+ var bounds = this.getParticleBounds();
878
+ var width = bounds.width,
879
+ height = bounds.height,
880
+ modelWidth = bounds.modelWidth,
881
+ modelHeight = bounds.modelHeight;
882
+ var devicePixelRatio = window.devicePixelRatio || 1;
883
+ var maxDimension = ((_this$device$limits = this.device.limits) === null || _this$device$limits === void 0 ? void 0 : _this$device$limits.maxTextureDimension2D) || 8192;
884
+ var pixelRatio = Math.min(devicePixelRatio, maxDimension / width, maxDimension / height);
502
885
  var pixelWidth = Math.max(1, Math.round(width * pixelRatio));
503
886
  var pixelHeight = Math.max(1, Math.round(height * pixelRatio));
504
- var cssWidth = "".concat(width, "px");
505
- var cssHeight = "".concat(height, "px");
506
- if (this.canvas.style.width !== cssWidth) {
507
- this.canvas.style.width = cssWidth;
887
+ var previous = this.canvasSize;
888
+ if (previous && previous.width === width && previous.height === height && previous.pixelWidth === pixelWidth && previous.pixelHeight === pixelHeight && previous.modelWidth === modelWidth && previous.modelHeight === modelHeight) {
889
+ return false;
890
+ }
891
+ if (!previous || previous.width !== width) {
892
+ this.canvas.style.width = "".concat(width, "px");
508
893
  }
509
- if (this.canvas.style.height !== cssHeight) {
510
- this.canvas.style.height = cssHeight;
894
+ if (!previous || previous.height !== height) {
895
+ this.canvas.style.height = "".concat(height, "px");
511
896
  }
512
897
  if (this.canvas.width !== pixelWidth) {
513
898
  this.canvas.width = pixelWidth;
@@ -515,31 +900,92 @@ var ParticleRenderer = /*#__PURE__*/function () {
515
900
  if (this.canvas.height !== pixelHeight) {
516
901
  this.canvas.height = pixelHeight;
517
902
  }
903
+ if (!previous || previous.modelWidth !== modelWidth || previous.modelHeight !== modelHeight) {
904
+ this.updateCanvasLayerWidthHeight();
905
+ }
906
+ this.canvasSize = {
907
+ width: width,
908
+ height: height,
909
+ pixelWidth: pixelWidth,
910
+ pixelHeight: pixelHeight,
911
+ modelWidth: modelWidth,
912
+ modelHeight: modelHeight
913
+ };
914
+ return true;
915
+ }
916
+ }, {
917
+ key: "repositionCanvas",
918
+ value: function repositionCanvas() {
919
+ var _ref, _this$tmodel$$dom$get, _this$tmodel$$dom, _ref2, _this$tmodel$$dom$get2, _this$tmodel$$dom2;
920
+ if (!this.canvas || !this.canvasLayer || !this.tmodel.hasDom()) {
921
+ return false;
922
+ }
923
+ var bounds = this.getParticleBounds();
924
+ var scrollLeft = Number((_ref = (_this$tmodel$$dom$get = (_this$tmodel$$dom = this.tmodel.$dom) === null || _this$tmodel$$dom === void 0 ? void 0 : _this$tmodel$$dom.getScrollLeft()) !== null && _this$tmodel$$dom$get !== void 0 ? _this$tmodel$$dom$get : this.tmodel.getScrollLeft()) !== null && _ref !== void 0 ? _ref : 0) || 0;
925
+ var scrollTop = Number((_ref2 = (_this$tmodel$$dom$get2 = (_this$tmodel$$dom2 = this.tmodel.$dom) === null || _this$tmodel$$dom2 === void 0 ? void 0 : _this$tmodel$$dom2.getScrollTop()) !== null && _this$tmodel$$dom$get2 !== void 0 ? _this$tmodel$$dom$get2 : this.tmodel.getScrollTop()) !== null && _ref2 !== void 0 ? _ref2 : 0) || 0;
926
+
927
+ // Canvas origin in the scroller's content coordinates.
928
+ var contentX = bounds.x + (this.tmodel.managesOwnScroll() ? scrollLeft : 0);
929
+ var contentY = bounds.y + (this.tmodel.managesOwnScroll() ? scrollTop : 0);
930
+
931
+ // Internally mounted canvases scroll with their DOM parent.
932
+ // External canvases do not, so their CSS position remains fixed.
933
+ var x = this.tmodel.managesOwnScroll() && !this.externalCanvasHost ? contentX : bounds.x;
934
+ var y = this.tmodel.managesOwnScroll() && !this.externalCanvasHost ? contentY : bounds.y;
935
+ var nextX = this.tmodel.managesOwnScroll() ? contentX : bounds.x + (this.externalCanvasHost ? scrollLeft : 0);
936
+ var nextY = this.tmodel.managesOwnScroll() ? contentY : bounds.y + (this.externalCanvasHost ? scrollTop : 0);
937
+ var changed = nextX !== this.canvasX || nextY !== this.canvasY;
938
+ this.canvasX = nextX;
939
+ this.canvasY = nextY;
940
+ var left = "".concat(x, "px");
941
+ var top = "".concat(y, "px");
942
+ if (this.canvas.style.left !== left) {
943
+ this.canvas.style.left = left;
944
+ changed = true;
945
+ }
946
+ if (this.canvas.style.top !== top) {
947
+ this.canvas.style.top = top;
948
+ changed = true;
949
+ }
950
+ if (this.canvas.style.transform !== "none") {
951
+ this.canvas.style.transform = "none";
952
+ changed = true;
953
+ }
954
+ return changed;
955
+ }
956
+ }, {
957
+ key: "getParticlePosition",
958
+ value: function getParticlePosition(child) {
959
+ var values = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : child === null || child === void 0 ? void 0 : child.actualValues;
960
+ var layoutScrollLeft = Number(this.tmodel.getScrollLeft()) || 0;
961
+ var layoutScrollTop = Number(this.tmodel.getScrollTop()) || 0;
962
+ return {
963
+ x: child.allTargetMap.x ? values.x : child.x + layoutScrollLeft,
964
+ y: child.allTargetMap.y ? values.y : child.y + layoutScrollTop
965
+ };
518
966
  }
519
967
  }, {
520
968
  key: "updateUniforms",
521
969
  value: function updateUniforms() {
522
- var width = this.getRenderWidth();
523
- var height = this.getRenderHeight();
524
- var scrollLeft = this.tmodel.getRenderScrollLeft();
525
- var scrollTop = this.tmodel.getRenderScrollTop();
526
- this.device.queue.writeBuffer(this.uniformBuffer, 0, new Float32Array([width, height, scrollLeft, scrollTop, this.transitionStep, this.transitionActive ? 1 : 0, 0, 0]));
970
+ var _this$canvasBounds;
971
+ var bounds = (_this$canvasBounds = this.canvasBounds) !== null && _this$canvasBounds !== void 0 ? _this$canvasBounds : this.getParticleBounds();
972
+ this.device.queue.writeBuffer(this.uniformBuffer, 0, new Float32Array([bounds.width, bounds.height, this.canvasX, this.canvasY, this.transitionStep, this.transitionActive ? 1 : 0, 0, 0]));
527
973
  }
528
974
  }, {
529
975
  key: "waitForPresentedFrame",
530
976
  value: function () {
531
- var _waitForPresentedFrame = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6() {
532
- return _regeneratorRuntime().wrap(function _callee6$(_context6) {
533
- while (1) switch (_context6.prev = _context6.next) {
977
+ var _waitForPresentedFrame = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7() {
978
+ return _regeneratorRuntime().wrap(function _callee7$(_context7) {
979
+ while (1) switch (_context7.prev = _context7.next) {
534
980
  case 0:
535
981
  if (!this.device) {
536
- _context6.next = 3;
982
+ _context7.next = 3;
537
983
  break;
538
984
  }
539
- _context6.next = 3;
985
+ _context7.next = 3;
540
986
  return this.device.queue.onSubmittedWorkDone();
541
987
  case 3:
542
- _context6.next = 5;
988
+ _context7.next = 5;
543
989
  return new Promise(function (resolve) {
544
990
  requestAnimationFrame(function () {
545
991
  requestAnimationFrame(resolve);
@@ -547,9 +993,9 @@ var ParticleRenderer = /*#__PURE__*/function () {
547
993
  });
548
994
  case 5:
549
995
  case "end":
550
- return _context6.stop();
996
+ return _context7.stop();
551
997
  }
552
- }, _callee6, this);
998
+ }, _callee7, this);
553
999
  }));
554
1000
  function waitForPresentedFrame() {
555
1001
  return _waitForPresentedFrame.apply(this, arguments);
@@ -559,31 +1005,16 @@ var ParticleRenderer = /*#__PURE__*/function () {
559
1005
  }, {
560
1006
  key: "render",
561
1007
  value: function render() {
562
- if (!this.device || !this.context || !this.pipeline || !this.particleBuffer || !this.targetParticleBuffer || this.particleCount === 0) {
1008
+ if (!this.device || !this.context) {
1009
+ return;
1010
+ }
1011
+ if (!this.mountCanvasLayer()) {
563
1012
  return;
564
1013
  }
565
1014
  this.resizeCanvas();
566
- this.updateUniforms();
1015
+ this.repositionCanvas();
567
1016
  var commandEncoder = this.device.createCommandEncoder();
568
- var renderPass = commandEncoder.beginRenderPass({
569
- colorAttachments: [{
570
- view: this.context.getCurrentTexture().createView(),
571
- clearValue: {
572
- r: 0,
573
- g: 0,
574
- b: 0,
575
- a: 0
576
- },
577
- loadOp: "clear",
578
- storeOp: "store"
579
- }]
580
- });
581
- renderPass.setPipeline(this.pipeline);
582
- renderPass.setBindGroup(0, this.bindGroup);
583
- renderPass.setVertexBuffer(0, this.particleBuffer);
584
- renderPass.setVertexBuffer(1, this.targetParticleBuffer);
585
- renderPass.draw(6, this.particleCount);
586
- renderPass.end();
1017
+ this.encodeRenderPass(commandEncoder, this.context.getCurrentTexture().createView());
587
1018
  this.device.queue.submit([commandEncoder.finish()]);
588
1019
  }
589
1020
  }, {
@@ -595,28 +1026,251 @@ var ParticleRenderer = /*#__PURE__*/function () {
595
1026
  var previousBuffer = this.particleBuffer;
596
1027
  this.particleBuffer = this.targetParticleBuffer;
597
1028
  this.targetParticleBuffer = previousBuffer;
1029
+ this.currentParticleData = this.targetParticleData;
598
1030
  this.transitionStep = 0;
599
1031
  this.transitionActive = false;
1032
+ this.boundsDirty = true;
600
1033
  this.render();
601
1034
  }
602
1035
  }, {
603
1036
  key: "captureBitmap",
604
- value: function captureBitmap() {
605
- if (!this.canvas || !this.device) {
1037
+ value: function () {
1038
+ var _captureBitmap = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8() {
1039
+ var width, height, bytesPerRow, buffer, texture, commandEncoder, mapped, pixels, rowSize, y, i, red, _i, alpha, scale, canvas, context;
1040
+ return _regeneratorRuntime().wrap(function _callee8$(_context8) {
1041
+ while (1) switch (_context8.prev = _context8.next) {
1042
+ case 0:
1043
+ if (!(!this.canvas || !this.device || !this.context)) {
1044
+ _context8.next = 2;
1045
+ break;
1046
+ }
1047
+ return _context8.abrupt("return");
1048
+ case 2:
1049
+ this.resizeCanvas();
1050
+ this.repositionCanvas();
1051
+ width = this.canvas.width;
1052
+ height = this.canvas.height;
1053
+ bytesPerRow = Math.ceil(width * 4 / 256) * 256;
1054
+ buffer = this.device.createBuffer({
1055
+ size: bytesPerRow * height,
1056
+ usage: globalThis.GPUBufferUsage.COPY_DST | globalThis.GPUBufferUsage.MAP_READ
1057
+ });
1058
+ texture = this.context.getCurrentTexture();
1059
+ commandEncoder = this.device.createCommandEncoder();
1060
+ this.encodeRenderPass(commandEncoder, texture.createView());
1061
+ commandEncoder.copyTextureToBuffer({
1062
+ texture: texture
1063
+ }, {
1064
+ buffer: buffer,
1065
+ bytesPerRow: bytesPerRow
1066
+ }, {
1067
+ width: width,
1068
+ height: height
1069
+ });
1070
+ this.device.queue.submit([commandEncoder.finish()]);
1071
+ _context8.next = 15;
1072
+ return buffer.mapAsync(globalThis.GPUMapMode.READ);
1073
+ case 15:
1074
+ mapped = new Uint8Array(buffer.getMappedRange());
1075
+ pixels = new Uint8ClampedArray(width * height * 4);
1076
+ rowSize = width * 4;
1077
+ for (y = 0; y < height; y++) {
1078
+ pixels.set(mapped.subarray(y * bytesPerRow, y * bytesPerRow + rowSize), y * rowSize);
1079
+ }
1080
+ buffer.unmap();
1081
+ buffer.destroy();
1082
+ if (this.format.startsWith("bgra")) {
1083
+ for (i = 0; i < pixels.length; i += 4) {
1084
+ red = pixels[i];
1085
+ pixels[i] = pixels[i + 2];
1086
+ pixels[i + 2] = red;
1087
+ }
1088
+ }
1089
+ for (_i = 0; _i < pixels.length; _i += 4) {
1090
+ alpha = pixels[_i + 3];
1091
+ if (alpha > 0 && alpha < 255) {
1092
+ scale = 255 / alpha;
1093
+ pixels[_i] = Math.min(255, Math.round(pixels[_i] * scale));
1094
+ pixels[_i + 1] = Math.min(255, Math.round(pixels[_i + 1] * scale));
1095
+ pixels[_i + 2] = Math.min(255, Math.round(pixels[_i + 2] * scale));
1096
+ }
1097
+ }
1098
+ canvas = document.createElement("canvas");
1099
+ canvas.width = width;
1100
+ canvas.height = height;
1101
+ context = canvas.getContext("2d");
1102
+ context.putImageData(new ImageData(pixels, width, height), 0, 0);
1103
+ return _context8.abrupt("return", createImageBitmap(canvas));
1104
+ case 29:
1105
+ case "end":
1106
+ return _context8.stop();
1107
+ }
1108
+ }, _callee8, this);
1109
+ }));
1110
+ function captureBitmap() {
1111
+ return _captureBitmap.apply(this, arguments);
1112
+ }
1113
+ return captureBitmap;
1114
+ }()
1115
+ }, {
1116
+ key: "updateScrollElements",
1117
+ value: function updateScrollElements() {
1118
+ var _this$tmodel$$dom3, _this$tmodel$getParen, _this$scrollElements;
1119
+ var nextElements = _toConsumableArray(new Set([(_this$tmodel$$dom3 = this.tmodel.$dom) === null || _this$tmodel$$dom3 === void 0 ? void 0 : _this$tmodel$$dom3.element, (_this$tmodel$getParen = this.tmodel.getParent()) === null || _this$tmodel$getParen === void 0 || (_this$tmodel$getParen = _this$tmodel$getParen.$dom) === null || _this$tmodel$getParen === void 0 ? void 0 : _this$tmodel$getParen.element].filter(Boolean)));
1120
+ var _iterator = _createForOfIteratorHelper((_this$scrollElements = this.scrollElements) !== null && _this$scrollElements !== void 0 ? _this$scrollElements : []),
1121
+ _step;
1122
+ try {
1123
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
1124
+ var element = _step.value;
1125
+ if (!nextElements.includes(element)) {
1126
+ element.removeEventListener("scroll", this.onScroll);
1127
+ }
1128
+ }
1129
+ } catch (err) {
1130
+ _iterator.e(err);
1131
+ } finally {
1132
+ _iterator.f();
1133
+ }
1134
+ var _iterator2 = _createForOfIteratorHelper(nextElements),
1135
+ _step2;
1136
+ try {
1137
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
1138
+ var _this$scrollElements2;
1139
+ var _element = _step2.value;
1140
+ if (!((_this$scrollElements2 = this.scrollElements) !== null && _this$scrollElements2 !== void 0 ? _this$scrollElements2 : []).includes(_element)) {
1141
+ _element.addEventListener("scroll", this.onScroll, {
1142
+ passive: true
1143
+ });
1144
+ }
1145
+ }
1146
+ } catch (err) {
1147
+ _iterator2.e(err);
1148
+ } finally {
1149
+ _iterator2.f();
1150
+ }
1151
+ this.scrollElements = nextElements;
1152
+ }
1153
+ }, {
1154
+ key: "canHostCanvasLayer",
1155
+ value: function canHostCanvasLayer(element) {
1156
+ return !new Set(["IMG", "INPUT", "CANVAS", "VIDEO", "IFRAME", "OBJECT", "EMBED"]).has(element.tagName);
1157
+ }
1158
+ }, {
1159
+ key: "getCanvasMount",
1160
+ value: function getCanvasMount() {
1161
+ var _this$tmodel$$dom4;
1162
+ var source = (_this$tmodel$$dom4 = this.tmodel.$dom) === null || _this$tmodel$$dom4 === void 0 ? void 0 : _this$tmodel$$dom4.element;
1163
+ if (!source) {
606
1164
  return;
607
1165
  }
608
- this.render();
609
- return createImageBitmap(this.canvas);
1166
+ var external = !!this.tmodel.explodeChildrenState || !this.canHostCanvasLayer(source);
1167
+ return {
1168
+ source: source,
1169
+ host: external ? source.parentElement : source,
1170
+ external: external
1171
+ };
1172
+ }
1173
+ }, {
1174
+ key: "mountCanvasLayer",
1175
+ value: function mountCanvasLayer() {
1176
+ if (!this.canvasLayer) {
1177
+ return false;
1178
+ }
1179
+ var mount = this.getCanvasMount();
1180
+ if (!(mount !== null && mount !== void 0 && mount.host)) {
1181
+ return false;
1182
+ }
1183
+ var source = mount.source,
1184
+ host = mount.host,
1185
+ external = mount.external;
1186
+ if (this.canvasLayer.parentElement !== host) {
1187
+ if (external) {
1188
+ source.after(this.canvasLayer);
1189
+ } else {
1190
+ host.prepend(this.canvasLayer);
1191
+ }
1192
+ }
1193
+ this.canvasHost = host;
1194
+ this.externalCanvasHost = external;
1195
+ if (external) {
1196
+ this.canvasLayer.style.left = source.style.left || "0px";
1197
+ this.canvasLayer.style.top = source.style.top || "0px";
1198
+ this.canvasLayer.style.transform = source.style.transform || "none";
1199
+ this.canvasLayer.style.transformOrigin = source.style.transformOrigin || "50% 50%";
1200
+ this.canvasLayer.style.zIndex = this.tmodel.explodeChildrenState ? String((Number(source.style.zIndex) || 0) + 1) : source.style.zIndex || "0";
1201
+ } else {
1202
+ this.canvasLayer.style.left = "0px";
1203
+ this.canvasLayer.style.top = "0px";
1204
+ this.canvasLayer.style.transform = "none";
1205
+ this.canvasLayer.style.zIndex = "0";
1206
+ }
1207
+ this.updateScrollElements();
1208
+ return true;
1209
+ }
1210
+ }, {
1211
+ key: "encodeRenderPass",
1212
+ value: function encodeRenderPass(commandEncoder, view) {
1213
+ var canDraw = this.pipeline && this.bindGroup && this.particleBuffer && this.targetParticleBuffer && this.explodeFragmentBuffer && this.particleCount > 0;
1214
+ if (canDraw) {
1215
+ this.updateUniforms();
1216
+ }
1217
+ var renderPass = commandEncoder.beginRenderPass({
1218
+ colorAttachments: [{
1219
+ view: view,
1220
+ clearValue: {
1221
+ r: 0,
1222
+ g: 0,
1223
+ b: 0,
1224
+ a: 0
1225
+ },
1226
+ loadOp: "clear",
1227
+ storeOp: "store"
1228
+ }]
1229
+ });
1230
+ if (canDraw) {
1231
+ var _explodeState$firstEx;
1232
+ renderPass.setPipeline(this.pipeline);
1233
+ renderPass.setBindGroup(0, this.bindGroup);
1234
+ renderPass.setVertexBuffer(0, this.particleBuffer);
1235
+ renderPass.setVertexBuffer(1, this.targetParticleBuffer);
1236
+ renderPass.setVertexBuffer(2, this.explodeFragmentBuffer);
1237
+ var explodeState = this.tmodel.explodeChildrenState;
1238
+ var firstInstance = this.explodeTextureReady && explodeState ? (_explodeState$firstEx = explodeState.firstExplodeChild) !== null && _explodeState$firstEx !== void 0 ? _explodeState$firstEx : 0 : 0;
1239
+ var instanceCount = this.particleCount - firstInstance;
1240
+ if (instanceCount > 0) {
1241
+ renderPass.draw(6, instanceCount, 0, firstInstance);
1242
+ }
1243
+ }
1244
+ renderPass.end();
610
1245
  }
611
1246
  }, {
612
1247
  key: "destroy",
613
1248
  value: function destroy() {
614
- var _this$particleBuffer, _this$targetParticleB, _this$uniformBuffer, _this$context, _this$canvasLayer;
1249
+ var _this$particleBuffer, _this$targetParticleB, _this$uniformBuffer, _this$context, _this$canvasLayer, _this$explodeFragment, _this$explodeTexture2, _this$scrollElements3;
1250
+ var _iterator3 = _createForOfIteratorHelper((_this$scrollElements3 = this.scrollElements) !== null && _this$scrollElements3 !== void 0 ? _this$scrollElements3 : []),
1251
+ _step3;
1252
+ try {
1253
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
1254
+ var element = _step3.value;
1255
+ element.removeEventListener("scroll", this.onScroll);
1256
+ }
1257
+ } catch (err) {
1258
+ _iterator3.e(err);
1259
+ } finally {
1260
+ _iterator3.f();
1261
+ }
1262
+ this.canvasSize = undefined;
1263
+ this.canvasBounds = undefined;
1264
+ this.boundsDirty = true;
1265
+ this.scrollElements = undefined;
1266
+ this.onScroll = undefined;
615
1267
  (_this$particleBuffer = this.particleBuffer) === null || _this$particleBuffer === void 0 || _this$particleBuffer.destroy();
616
1268
  (_this$targetParticleB = this.targetParticleBuffer) === null || _this$targetParticleB === void 0 || _this$targetParticleB.destroy();
617
1269
  (_this$uniformBuffer = this.uniformBuffer) === null || _this$uniformBuffer === void 0 || _this$uniformBuffer.destroy();
618
1270
  (_this$context = this.context) === null || _this$context === void 0 || _this$context.unconfigure();
619
1271
  (_this$canvasLayer = this.canvasLayer) === null || _this$canvasLayer === void 0 || _this$canvasLayer.remove();
1272
+ (_this$explodeFragment = this.explodeFragmentBuffer) === null || _this$explodeFragment === void 0 || _this$explodeFragment.destroy();
1273
+ (_this$explodeTexture2 = this.explodeTexture) === null || _this$explodeTexture2 === void 0 || _this$explodeTexture2.destroy();
620
1274
  this.particleBuffer = undefined;
621
1275
  this.targetParticleBuffer = undefined;
622
1276
  this.uniformBuffer = undefined;
@@ -630,6 +1284,14 @@ var ParticleRenderer = /*#__PURE__*/function () {
630
1284
  this.transitionStep = 0;
631
1285
  this.transitionActive = false;
632
1286
  this.particleCount = 0;
1287
+ this.canvasBounds = undefined;
1288
+ this.currentParticleData = undefined;
1289
+ this.targetParticleData = undefined;
1290
+ this.explodeFragmentBuffer = undefined;
1291
+ this.explodeTexture = undefined;
1292
+ this.explodeSampler = undefined;
1293
+ this.explodeSourceCanvas = undefined;
1294
+ this.explodeTextureReady = false;
633
1295
  this.initializationPromise = undefined;
634
1296
  }
635
1297
  }]);