@twick/live-player 0.15.20 → 0.15.21

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,6 +1,191 @@
1
+ "use strict";
1
2
  var __defProp = Object.defineProperty;
2
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ var dist = {};
6
+ var runtime = {};
7
+ Object.defineProperty(runtime, "__esModule", { value: true });
8
+ runtime.createEffectContext = createEffectContext;
9
+ runtime.applyEffects = applyEffects;
10
+ var BASIC_VERTEX_SHADER = "\n attribute vec2 a_position;\n attribute vec2 a_texCoord;\n\n varying vec2 v_texCoord;\n\n void main() {\n v_texCoord = a_texCoord;\n gl_Position = vec4(a_position, 0.0, 1.0);\n }\n";
11
+ function createShader(gl, type, source) {
12
+ var shader = gl.createShader(type);
13
+ if (!shader) {
14
+ throw new Error("Failed to create shader");
15
+ }
16
+ gl.shaderSource(shader, source);
17
+ gl.compileShader(shader);
18
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
19
+ var info = gl.getShaderInfoLog(shader) || "Unknown error";
20
+ gl.deleteShader(shader);
21
+ throw new Error("Failed to compile shader: ".concat(info));
22
+ }
23
+ return shader;
24
+ }
25
+ function createProgram(gl, vertexSrc, fragmentSrc) {
26
+ var vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSrc);
27
+ var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSrc);
28
+ var program = gl.createProgram();
29
+ if (!program) {
30
+ throw new Error("Failed to create program");
31
+ }
32
+ gl.attachShader(program, vertexShader);
33
+ gl.attachShader(program, fragmentShader);
34
+ gl.linkProgram(program);
35
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
36
+ var info = gl.getProgramInfoLog(program) || "Unknown error";
37
+ gl.deleteProgram(program);
38
+ gl.deleteShader(vertexShader);
39
+ gl.deleteShader(fragmentShader);
40
+ throw new Error("Failed to link program: ".concat(info));
41
+ }
42
+ gl.deleteShader(vertexShader);
43
+ gl.deleteShader(fragmentShader);
44
+ return program;
45
+ }
46
+ function createEffectContext(canvas) {
47
+ var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
48
+ if (!gl) {
49
+ throw new Error("WebGL not supported");
50
+ }
51
+ var quadBuffer = gl.createBuffer();
52
+ if (!quadBuffer) {
53
+ throw new Error("Failed to create quad buffer");
54
+ }
55
+ gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
56
+ var quadVertices = new Float32Array([
57
+ -1,
58
+ -1,
59
+ //
60
+ 1,
61
+ -1,
62
+ -1,
63
+ 1,
64
+ 1,
65
+ 1
66
+ ]);
67
+ gl.bufferData(gl.ARRAY_BUFFER, quadVertices, gl.STATIC_DRAW);
68
+ var texCoordBuffer = gl.createBuffer();
69
+ if (!texCoordBuffer) {
70
+ throw new Error("Failed to create texCoord buffer");
71
+ }
72
+ gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
73
+ var texCoords = new Float32Array([
74
+ 0,
75
+ 0,
76
+ //
77
+ 1,
78
+ 0,
79
+ 0,
80
+ 1,
81
+ 1,
82
+ 1
83
+ ]);
84
+ gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW);
85
+ var framebuffers = [];
86
+ var textures = [];
87
+ return {
88
+ gl,
89
+ programCache: /* @__PURE__ */ new Map(),
90
+ quadBuffer,
91
+ texCoordBuffer,
92
+ framebuffers,
93
+ textures
94
+ };
95
+ }
96
+ function ensureRenderTargets(ctx, width, height) {
97
+ var gl = ctx.gl, framebuffers = ctx.framebuffers, textures = ctx.textures;
98
+ while (framebuffers.length < 2) {
99
+ var fb = gl.createFramebuffer();
100
+ var tex = gl.createTexture();
101
+ if (!fb || !tex) {
102
+ throw new Error("Failed to create framebuffer or texture");
103
+ }
104
+ gl.bindTexture(gl.TEXTURE_2D, tex);
105
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
106
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
107
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
108
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
109
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
110
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
111
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
112
+ framebuffers.push(fb);
113
+ textures.push(tex);
114
+ }
115
+ for (var i = 0; i < textures.length; i++) {
116
+ gl.bindTexture(gl.TEXTURE_2D, textures[i]);
117
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
118
+ }
119
+ }
120
+ function applyEffects(opts) {
121
+ var ctx = opts.ctx, sourceTexture = opts.sourceTexture, width = opts.width, height = opts.height, effects = opts.effects;
122
+ var gl = ctx.gl, programCache = ctx.programCache, quadBuffer = ctx.quadBuffer, texCoordBuffer = ctx.texCoordBuffer, framebuffers = ctx.framebuffers, textures = ctx.textures;
123
+ if (!effects.length) {
124
+ return sourceTexture;
125
+ }
126
+ ensureRenderTargets(ctx, width, height);
127
+ var readTexture = sourceTexture;
128
+ var writeIndex = 0;
129
+ gl.viewport(0, 0, width, height);
130
+ effects.forEach(function(active) {
131
+ if (!active.fragment)
132
+ return;
133
+ var cacheKey = active.fragment;
134
+ var program = programCache.get(cacheKey);
135
+ if (!program) {
136
+ program = createProgram(gl, BASIC_VERTEX_SHADER, active.fragment);
137
+ programCache.set(cacheKey, program);
138
+ }
139
+ gl.useProgram(program);
140
+ var positionLocation = gl.getAttribLocation(program, "a_position");
141
+ var texCoordLocation = gl.getAttribLocation(program, "a_texCoord");
142
+ gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
143
+ gl.enableVertexAttribArray(positionLocation);
144
+ gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
145
+ gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
146
+ gl.enableVertexAttribArray(texCoordLocation);
147
+ gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
148
+ var fb = framebuffers[writeIndex];
149
+ var targetTex = textures[writeIndex];
150
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
151
+ gl.activeTexture(gl.TEXTURE0);
152
+ gl.bindTexture(gl.TEXTURE_2D, readTexture);
153
+ var textureLocation = gl.getUniformLocation(program, "uTexture");
154
+ if (textureLocation) {
155
+ gl.uniform1i(textureLocation, 0);
156
+ }
157
+ var resolutionLocation = gl.getUniformLocation(program, "uResolution");
158
+ if (resolutionLocation) {
159
+ gl.uniform2f(resolutionLocation, width, height);
160
+ }
161
+ var timeLocation = gl.getUniformLocation(program, "uTime");
162
+ if (timeLocation) {
163
+ gl.uniform1f(timeLocation, active.progress);
164
+ }
165
+ var intensityLocation = gl.getUniformLocation(program, "uIntensity");
166
+ if (intensityLocation) {
167
+ gl.uniform1f(intensityLocation, active.intensity);
168
+ }
169
+ gl.clearColor(0, 0, 0, 0);
170
+ gl.clear(gl.COLOR_BUFFER_BIT);
171
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
172
+ readTexture = targetTex;
173
+ writeIndex = (writeIndex + 1) % textures.length;
174
+ });
175
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
176
+ return readTexture;
177
+ }
178
+ (function(exports$1) {
179
+ Object.defineProperty(exports$1, "__esModule", { value: true });
180
+ exports$1.applyEffects = exports$1.createEffectContext = void 0;
181
+ var runtime_1 = runtime;
182
+ Object.defineProperty(exports$1, "createEffectContext", { enumerable: true, get: function() {
183
+ return runtime_1.createEffectContext;
184
+ } });
185
+ Object.defineProperty(exports$1, "applyEffects", { enumerable: true, get: function() {
186
+ return runtime_1.applyEffects;
187
+ } });
188
+ })(dist);
4
189
  const parseNumber = (color, len) => {
5
190
  if (typeof color !== "number") return;
6
191
  if (len === 3) {
@@ -6064,6 +6249,15 @@ var TwickPlayer = class extends HTMLElement {
6064
6249
  __publicField(this, "_looping", true);
6065
6250
  __publicField(this, "_volume", 1);
6066
6251
  __publicField(this, "volumeChangeRequested", true);
6252
+ /** WebGL canvas and context for applying effects to the live preview. */
6253
+ __publicField(this, "effectGlCanvas", null);
6254
+ __publicField(this, "effectContext", null);
6255
+ __publicField(this, "effectReadbackFbo", null);
6256
+ /**
6257
+ * Optional resolver for active effects at a given time. Set by the host (e.g. twick) so
6258
+ * effect logic lives outside twick-base. When set, used for live preview effects.
6259
+ */
6260
+ __publicField(this, "getActiveEffectsForTime");
6067
6261
  /**
6068
6262
  * Triggered by the timeline.
6069
6263
  */
@@ -6111,6 +6305,7 @@ var TwickPlayer = class extends HTMLElement {
6111
6305
  this.player.playback.currentScene,
6112
6306
  this.player.playback.previousScene
6113
6307
  );
6308
+ this.applyEffectsToFinalBuffer();
6114
6309
  this.dispatchEvent(new CustomEvent("timeupdate", { detail: this.time }));
6115
6310
  const durationInFrames = this.player.playback.duration;
6116
6311
  if (durationInFrames === this.duration) {
@@ -6308,6 +6503,85 @@ var TwickPlayer = class extends HTMLElement {
6308
6503
  this.addEventListener("seekto", this.handleSeekTo);
6309
6504
  this.addEventListener("volumechange", this.handleVolumeChange);
6310
6505
  }
6506
+ /**
6507
+ * Resolve active effects for the given time. Uses host-provided callback when set.
6508
+ */
6509
+ resolveActiveEffectsForTime(timeInSec) {
6510
+ var _a;
6511
+ if (this.getActiveEffectsForTime) {
6512
+ const fps = ((_a = this.player) == null ? void 0 : _a.playback.fps) ?? 30;
6513
+ return this.getActiveEffectsForTime(this.variables, timeInSec, fps);
6514
+ }
6515
+ return [];
6516
+ }
6517
+ /**
6518
+ * Apply GL effects to the current frame and draw the result back to the stage canvas.
6519
+ */
6520
+ applyEffectsToFinalBuffer() {
6521
+ const canvas = this.stage.finalBuffer;
6522
+ const w = canvas.width;
6523
+ const h = canvas.height;
6524
+ if (w <= 0 || h <= 0) return;
6525
+ const activeEffects = this.resolveActiveEffectsForTime(this.time);
6526
+ if (activeEffects.length === 0) return;
6527
+ if (!this.effectGlCanvas) {
6528
+ this.effectGlCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(w, h) : document.createElement("canvas");
6529
+ this.effectGlCanvas.width = w;
6530
+ this.effectGlCanvas.height = h;
6531
+ }
6532
+ const glCanvas = this.effectGlCanvas;
6533
+ if (glCanvas.width !== w || glCanvas.height !== h) {
6534
+ glCanvas.width = w;
6535
+ glCanvas.height = h;
6536
+ }
6537
+ if (!this.effectContext) {
6538
+ this.effectContext = dist.createEffectContext(glCanvas);
6539
+ }
6540
+ const gl = this.effectContext.gl;
6541
+ const sourceTexture = gl.createTexture();
6542
+ if (!sourceTexture) return;
6543
+ gl.bindTexture(gl.TEXTURE_2D, sourceTexture);
6544
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
6545
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
6546
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
6547
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
6548
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
6549
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
6550
+ const resultTexture = dist.applyEffects({
6551
+ ctx: this.effectContext,
6552
+ sourceTexture,
6553
+ width: w,
6554
+ height: h,
6555
+ effects: activeEffects
6556
+ });
6557
+ gl.deleteTexture(sourceTexture);
6558
+ if (!this.effectReadbackFbo) {
6559
+ this.effectReadbackFbo = gl.createFramebuffer();
6560
+ }
6561
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.effectReadbackFbo);
6562
+ gl.framebufferTexture2D(
6563
+ gl.FRAMEBUFFER,
6564
+ gl.COLOR_ATTACHMENT0,
6565
+ gl.TEXTURE_2D,
6566
+ resultTexture,
6567
+ 0
6568
+ );
6569
+ const pixels = new Uint8Array(w * h * 4);
6570
+ gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
6571
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
6572
+ const ctx2d = canvas.getContext("2d");
6573
+ if (ctx2d) {
6574
+ const imageData = ctx2d.createImageData(w, h);
6575
+ const rowBytes = w * 4;
6576
+ for (let y = 0; y < h; y++) {
6577
+ imageData.data.set(
6578
+ pixels.subarray((h - 1 - y) * rowBytes, (h - y) * rowBytes),
6579
+ y * rowBytes
6580
+ );
6581
+ }
6582
+ ctx2d.putImageData(imageData, 0, 0);
6583
+ }
6584
+ }
6311
6585
  updateSettings() {
6312
6586
  var _a;
6313
6587
  if (!this.defaultSettings) {
@@ -6327,4 +6601,4 @@ var TwickPlayer = class extends HTMLElement {
6327
6601
  if (!customElements.get(ID)) {
6328
6602
  customElements.define(ID, TwickPlayer);
6329
6603
  }
6330
- //# sourceMappingURL=internal-LKI2GAXH-C1j65akX.mjs.map
6604
+ //# sourceMappingURL=internal-B6KRB6EV-DXLdD4g5.js.map