@pixerate/editor 0.231.0 → 0.232.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation-editor/index.cjs +25 -25
- package/dist/animation-editor/index.js +1 -1
- package/dist/canvas/index.cjs +7 -7
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-OPSK22DL.cjs → chunk-2K5TELHV.cjs} +19 -2
- package/dist/{chunk-CSM5T6SE.js → chunk-6QLTUGMO.js} +1 -1
- package/dist/{chunk-5T3H7CGG.cjs → chunk-A653N65Q.cjs} +7 -7
- package/dist/{chunk-SBPGIZQN.js → chunk-MUSZYMBX.js} +1 -1
- package/dist/{chunk-TCZ2J7PR.js → chunk-PQYDJ2AV.js} +18 -1
- package/dist/{chunk-C73U5UI3.cjs → chunk-RG4O6K2A.cjs} +14 -14
- package/dist/effects/conformance.d.cts +4 -1
- package/dist/effects/conformance.d.ts +4 -1
- package/dist/effects/errors.d.cts +6 -1
- package/dist/effects/errors.d.ts +6 -1
- package/dist/effects/fake-templates.d.cts +17 -0
- package/dist/effects/fake-templates.d.ts +17 -0
- package/dist/effects/fake.d.cts +6 -1
- package/dist/effects/fake.d.ts +6 -1
- package/dist/effects/index.cjs +537 -74
- package/dist/effects/index.d.cts +1 -0
- package/dist/effects/index.d.ts +1 -0
- package/dist/effects/index.js +466 -3
- package/dist/effects/templates.d.cts +56 -0
- package/dist/effects/templates.d.ts +56 -0
- package/dist/effects/types.d.cts +212 -0
- package/dist/effects/types.d.ts +212 -0
- package/dist/image-editor/controller.d.cts +12 -0
- package/dist/image-editor/controller.d.ts +12 -0
- package/dist/image-editor/index.cjs +189 -144
- package/dist/image-editor/index.js +48 -3
- package/dist/paint-editor/index.cjs +7 -7
- package/dist/paint-editor/index.js +2 -2
- package/dist/vector/index.cjs +6 -6
- package/dist/vector/index.js +1 -1
- package/dist/video-editor/index.cjs +329 -329
- package/dist/video-editor/index.js +3 -3
- package/package.json +1 -1
- package/skills/pixerate-animation-editor/SKILL.md +37 -0
package/dist/effects/index.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var _chunk4XSBOGMKcjs = require('../chunk-4XSBOGMK.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _chunkRG4O6K2Acjs = require('../chunk-RG4O6K2A.cjs');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
var _chunkPY4GWSE2cjs = require('../chunk-PY4GWSE2.cjs');
|
|
@@ -45,15 +45,249 @@ var _chunkPY4GWSE2cjs = require('../chunk-PY4GWSE2.cjs');
|
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
var _chunk2K5TELHVcjs = require('../chunk-2K5TELHV.cjs');
|
|
49
54
|
require('../chunk-WOFXZ3XU.cjs');
|
|
50
55
|
require('../chunk-FJ2MSI43.cjs');
|
|
51
56
|
|
|
52
57
|
|
|
53
58
|
var _chunkDWJJI6RTcjs = require('../chunk-DWJJI6RT.cjs');
|
|
54
59
|
|
|
60
|
+
// src/effects/templates.ts
|
|
61
|
+
var SLOT_NAME = /^[A-Za-z][\w-]*$/;
|
|
62
|
+
var COLOR = /^#[0-9a-fA-F]{6}$/;
|
|
63
|
+
var EFFECT_SEQUENCE_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
64
|
+
var isObject = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
65
|
+
var isSubjectTemplateSlot = (slot) => slot.type === "image" || slot.type === "video" || slot.type === "svg";
|
|
66
|
+
function effectSubjectKind(subject) {
|
|
67
|
+
if (!isObject(subject)) return void 0;
|
|
68
|
+
for (const k of ["slot", "image", "video", "svg", "text"]) if (typeof subject[k] === "string") return k;
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
71
|
+
var typeName = (value) => value === null ? "null" : Array.isArray(value) ? "a list" : typeof value === "object" ? "an object" : typeof value === "string" ? `the words ${JSON.stringify(value.length > 40 ? `${value.slice(0, 40)}\u2026` : value)}` : `${typeof value === "number" ? "the number" : "the value"} ${String(value)}`;
|
|
72
|
+
function range(slot) {
|
|
73
|
+
const whole = slot.integer ? "whole number" : "number";
|
|
74
|
+
if (slot.min !== void 0 && slot.max !== void 0) return `a ${whole} from ${slot.min} to ${slot.max}`;
|
|
75
|
+
if (slot.min !== void 0) return `a ${whole} of at least ${slot.min}`;
|
|
76
|
+
if (slot.max !== void 0) return `a ${whole} of at most ${slot.max}`;
|
|
77
|
+
return `a ${whole}`;
|
|
78
|
+
}
|
|
79
|
+
function templateSlotTakes(slot) {
|
|
80
|
+
switch (slot.type) {
|
|
81
|
+
case "text":
|
|
82
|
+
return `words${slot.maxLength !== void 0 ? ` (up to ${slot.maxLength} characters)` : ""}`;
|
|
83
|
+
case "color":
|
|
84
|
+
return `a colour written #RRGGBB, like "${slot.default}"`;
|
|
85
|
+
case "number":
|
|
86
|
+
return range(slot);
|
|
87
|
+
case "video":
|
|
88
|
+
return "a video URL";
|
|
89
|
+
case "svg":
|
|
90
|
+
return "SVG markup or an SVG URL";
|
|
91
|
+
default:
|
|
92
|
+
return "a picture: a URL, a data: URL or <svg> markup";
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function templateValueProblem(slot, value) {
|
|
96
|
+
const no = (extra = "") => `Slot "${slot.name}" takes ${templateSlotTakes(slot)}${extra}, not ${typeName(value)}.`;
|
|
97
|
+
switch (slot.type) {
|
|
98
|
+
case "text":
|
|
99
|
+
if (typeof value !== "string") return no();
|
|
100
|
+
if (slot.maxLength !== void 0 && value.length > slot.maxLength) return `Slot "${slot.name}" takes up to ${slot.maxLength} characters; the value has ${value.length}. Shorten it.`;
|
|
101
|
+
return void 0;
|
|
102
|
+
case "color":
|
|
103
|
+
return typeof value === "string" && COLOR.test(value) ? void 0 : no();
|
|
104
|
+
case "number":
|
|
105
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return no();
|
|
106
|
+
if (slot.integer && !Number.isInteger(value)) return `Slot "${slot.name}" takes ${range(slot)}; ${value} is not whole.`;
|
|
107
|
+
if (slot.min !== void 0 && value < slot.min || slot.max !== void 0 && value > slot.max) return `Slot "${slot.name}" takes ${range(slot)}; ${value} is out of range.`;
|
|
108
|
+
return void 0;
|
|
109
|
+
default: {
|
|
110
|
+
const host = ` (or { "slot": "${slot.name}" } to leave it for the host)`;
|
|
111
|
+
if (typeof value === "string") return value.trim() ? void 0 : no(host);
|
|
112
|
+
const kind = effectSubjectKind(value);
|
|
113
|
+
if (!kind) return no(host);
|
|
114
|
+
if (kind === "slot") return SLOT_NAME.test(value.slot) ? void 0 : `Slot "${slot.name}" left for the host is { "slot": name }, the name letters, digits, "-" and "_", starting with a letter.`;
|
|
115
|
+
const fits = kind === slot.type || slot.type === "image" && kind === "svg";
|
|
116
|
+
if (!fits) return `Slot "${slot.name}" takes { "${slot.type}": \u2026 }${slot.type === "image" ? ' or { "svg": \u2026 }' : ""}, not { "${kind}": \u2026 }.`;
|
|
117
|
+
return value[kind].trim() ? void 0 : `Slot "${slot.name}"'s "${kind}" is a non-empty string.`;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
var slotList = (slots) => slots.length ? `the slots are ${slots.map((s) => `${s.name} (${s.type})`).join(", ")}` : "the template has no slots";
|
|
122
|
+
function checkTemplateValues(slots, values) {
|
|
123
|
+
if (values === void 0) return [];
|
|
124
|
+
if (!isObject(values)) return [`Values are an object of slot names to values; ${slotList(slots)}.`];
|
|
125
|
+
const byName = new Map(slots.map((s) => [s.name, s]));
|
|
126
|
+
const errors = [];
|
|
127
|
+
for (const [name, value] of Object.entries(values)) {
|
|
128
|
+
const slot = byName.get(name);
|
|
129
|
+
if (!slot) errors.push(`There is no slot "${name}"; ${slotList(slots)}.`);
|
|
130
|
+
else if (value !== void 0) {
|
|
131
|
+
const problem = templateValueProblem(slot, value);
|
|
132
|
+
if (problem) errors.push(problem);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return errors;
|
|
136
|
+
}
|
|
137
|
+
function templateSlotSchema(slot) {
|
|
138
|
+
const about = `${slot.label}${slot.description ? `: ${slot.description}` : ""}.`;
|
|
139
|
+
switch (slot.type) {
|
|
140
|
+
case "text":
|
|
141
|
+
return { type: "string", ...slot.maxLength !== void 0 ? { maxLength: slot.maxLength } : {}, description: `${about} Words${slot.maxLength !== void 0 ? `, up to ${slot.maxLength} characters` : ""}. Default ${JSON.stringify(slot.default)}.` };
|
|
142
|
+
case "color":
|
|
143
|
+
return { type: "string", pattern: COLOR.source, description: `${about} A colour as #RRGGBB. Default ${slot.default}.` };
|
|
144
|
+
case "number":
|
|
145
|
+
return {
|
|
146
|
+
type: slot.integer ? "integer" : "number",
|
|
147
|
+
...slot.min !== void 0 ? { minimum: slot.min } : {},
|
|
148
|
+
...slot.max !== void 0 ? { maximum: slot.max } : {},
|
|
149
|
+
description: `${about} ${range(slot).replace(/^a /, "A ")}. Default ${slot.default}.`
|
|
150
|
+
};
|
|
151
|
+
default: {
|
|
152
|
+
const key = slot.type;
|
|
153
|
+
const object2 = (k, what) => ({ type: "object", properties: { [k]: { type: "string", description: what } }, required: [k], additionalProperties: false, description: `{ "${k}": \u2026 }` });
|
|
154
|
+
return {
|
|
155
|
+
anyOf: [
|
|
156
|
+
{ type: "string", minLength: 1, description: key === "video" ? "A video URL." : key === "svg" ? "SVG markup or an SVG URL." : "A picture URL, a data: URL or <svg> markup." },
|
|
157
|
+
object2(key, key === "video" ? "A video URL." : key === "svg" ? "SVG markup or an SVG URL." : "A picture URL or a data: URL."),
|
|
158
|
+
...key === "image" ? [object2("svg", "SVG markup.")] : [],
|
|
159
|
+
object2("slot", "A slot name, to leave the subject for the host to fill.")
|
|
160
|
+
],
|
|
161
|
+
description: `${about} ${templateSlotTakes(slot).replace(/^a /, "A ")}. ${slot.hasDefault ? "Default: a placeholder picture." : "No default: left out, the host fills it."}`
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function templateValuesSchema(slots) {
|
|
167
|
+
return {
|
|
168
|
+
type: "object",
|
|
169
|
+
properties: Object.fromEntries(slots.map((s) => [s.name, templateSlotSchema(s)])),
|
|
170
|
+
additionalProperties: false,
|
|
171
|
+
description: `Slot values by name; slots left out take their defaults. ${slots.length ? `Slots: ${slots.map((s) => s.name).join(", ")}.` : "This template has no slots."}`
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function templateDefaultValues(slots) {
|
|
175
|
+
const out = {};
|
|
176
|
+
for (const s of slots) if (!isSubjectTemplateSlot(s)) out[s.name] = s.default;
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
function templateSlotSummary(slot) {
|
|
180
|
+
const fallback = isSubjectTemplateSlot(slot) ? slot.hasDefault ? "a placeholder by default" : "the host fills it when none is given" : `default ${JSON.stringify(slot.default)}`;
|
|
181
|
+
return `${slot.name} (${slot.type}): ${slot.label}; takes ${templateSlotTakes(slot)}; ${fallback}.`;
|
|
182
|
+
}
|
|
183
|
+
function searchTemplateSummaries(catalog, options = {}) {
|
|
184
|
+
const words = (_nullishCoalesce(options.query, () => ( ""))).toLowerCase().split(/\s+/).filter(Boolean);
|
|
185
|
+
const scored = [];
|
|
186
|
+
for (const t of catalog) {
|
|
187
|
+
if (!_chunk2K5TELHVcjs.hasEffectTags.call(void 0, t, options.tags)) continue;
|
|
188
|
+
let score = 0;
|
|
189
|
+
const name = t.name.toLowerCase();
|
|
190
|
+
const rest = [t.id, ..._nullishCoalesce(t.tags, () => ( [])), t.description].join(" ").toLowerCase();
|
|
191
|
+
if (!words.every((w) => name.includes(w) || rest.includes(w))) continue;
|
|
192
|
+
for (const w of words) score += name.includes(w) ? 2 : 1;
|
|
193
|
+
scored.push({ t, score });
|
|
194
|
+
}
|
|
195
|
+
scored.sort((a, b) => b.score - a.score);
|
|
196
|
+
const out = scored.map((s) => s.t);
|
|
197
|
+
return options.limit !== void 0 ? out.slice(0, Math.max(0, options.limit)) : out;
|
|
198
|
+
}
|
|
199
|
+
var effectLayerRole = (layer) => _nullishCoalesce(layer.role, () => ( (layer.rect ? "subject" : "background")));
|
|
200
|
+
function effectLayerInput(description) {
|
|
201
|
+
const images = description.inputs.filter((i) => i.kind === "image");
|
|
202
|
+
return _optionalChain([(_nullishCoalesce(images.find((i) => i.name === "source"), () => ( images.find((i) => i.name !== "from" && i.name !== "to")))), 'optionalAccess', _ => _.name]);
|
|
203
|
+
}
|
|
204
|
+
var EFFECT_LAYER_USES = ["generator", "filter", "overlay", "title"];
|
|
205
|
+
var effectLayerOffered = (e) => (e.kind === "shader" || e.kind === "vector") && e.uses.some((u) => EFFECT_LAYER_USES.includes(u));
|
|
206
|
+
var isRect = (r) => isObject(r) && ["x", "y", "width", "height"].every((k) => Number.isFinite(r[k])) && r.width > 0 && r.height > 0;
|
|
207
|
+
var isLayerTime = (t) => typeof t === "number" && Number.isFinite(t) && t >= 0 || isObject(t) && Number.isInteger(t.shots) && t.shots >= 1;
|
|
208
|
+
function effectSubjectProblem(subject) {
|
|
209
|
+
const kind = effectSubjectKind(subject);
|
|
210
|
+
if (!kind) return `a subject is one of { image }, { video }, { svg }, { text } or { slot }, not ${typeName(subject)}`;
|
|
211
|
+
if (!subject[kind].trim()) return `a subject's "${kind}" is a non-empty string`;
|
|
212
|
+
return void 0;
|
|
213
|
+
}
|
|
214
|
+
function checkEffectSequence(sequence, catalog) {
|
|
215
|
+
const problems = [];
|
|
216
|
+
if (!isObject(sequence)) return ["A sequence is an object with name, stage and shots."];
|
|
217
|
+
if (typeof sequence.name !== "string" || !sequence.name) problems.push("The sequence needs a name.");
|
|
218
|
+
const stage = sequence.stage;
|
|
219
|
+
if (!isObject(stage) || !(Number(stage.width) > 0) || !(Number(stage.height) > 0)) problems.push("The sequence needs a stage { width, height } in pixels, both > 0.");
|
|
220
|
+
if (!Array.isArray(sequence.shots) || !sequence.shots.length) return [...problems, "The sequence needs at least one shot."];
|
|
221
|
+
const byId = catalog ? new Map(catalog.map((e) => [e.id, e])) : void 0;
|
|
222
|
+
const ids = /* @__PURE__ */ new Set();
|
|
223
|
+
sequence.shots.forEach((shot, i) => {
|
|
224
|
+
const at = `shot ${i + 1}`;
|
|
225
|
+
if (!isObject(shot)) return void problems.push(`${at} is not an object.`);
|
|
226
|
+
if (!(Number.isFinite(shot.hold) && shot.hold >= 0)) problems.push(`${at}: hold must be ms \u2265 0.`);
|
|
227
|
+
for (const k of ["title", "caption"]) if (shot[k] !== void 0 && typeof shot[k] !== "string") problems.push(`${at}: ${k} must be words.`);
|
|
228
|
+
if (shot.camera !== void 0) {
|
|
229
|
+
const camera = shot.camera;
|
|
230
|
+
if (!isObject(camera)) problems.push(`${at}: camera must be an object.`);
|
|
231
|
+
else if (camera.framing !== void 0 && !isRect(camera.framing)) problems.push(`${at}: camera.framing must be { x, y, width, height } with width and height > 0.`);
|
|
232
|
+
}
|
|
233
|
+
if (!Array.isArray(shot.layers)) problems.push(`${at}: layers must be a list (it may be empty).`);
|
|
234
|
+
else
|
|
235
|
+
shot.layers.forEach((layer, j) => {
|
|
236
|
+
const where = `${at}, layer ${j + 1}`;
|
|
237
|
+
if (!isObject(layer)) return void problems.push(`${where} is not an object.`);
|
|
238
|
+
if (layer.id !== void 0) {
|
|
239
|
+
if (typeof layer.id !== "string" || !layer.id) problems.push(`${where}: id must be a non-empty string.`);
|
|
240
|
+
else if (ids.has(layer.id)) problems.push(`${where}: id "${layer.id}" is used twice.`);
|
|
241
|
+
else ids.add(layer.id);
|
|
242
|
+
}
|
|
243
|
+
if (layer.effect === void 0 && layer.subject === void 0) problems.push(`${where} has neither an effect nor a subject.`);
|
|
244
|
+
if (layer.effect !== void 0 && (typeof layer.effect !== "string" || !layer.effect)) problems.push(`${where}: effect must be an effect id.`);
|
|
245
|
+
else if (typeof layer.effect === "string" && byId) {
|
|
246
|
+
const e = byId.get(layer.effect);
|
|
247
|
+
if (!e) problems.push(`${where}: the provider has no effect "${layer.effect}".`);
|
|
248
|
+
else if (!effectLayerOffered(e)) problems.push(`${where}: "${layer.effect}" (${e.kind}, ${e.uses.join("/")}) cannot be a layer; a layer's effect is a generator, filter, overlay or title.`);
|
|
249
|
+
}
|
|
250
|
+
if (layer.subject !== void 0) {
|
|
251
|
+
const p = effectSubjectProblem(layer.subject);
|
|
252
|
+
if (p) problems.push(`${where}: ${p}.`);
|
|
253
|
+
}
|
|
254
|
+
if (layer.role !== void 0 && !_chunk2K5TELHVcjs.EFFECT_LAYER_ROLES.includes(layer.role)) problems.push(`${where}: role is one of ${_chunk2K5TELHVcjs.EFFECT_LAYER_ROLES.join(", ")}.`);
|
|
255
|
+
if (layer.rect !== void 0 && !isRect(layer.rect)) problems.push(`${where}: rect must be { x, y, width, height } with width and height > 0.`);
|
|
256
|
+
for (const k of ["from", "until"]) if (layer[k] !== void 0 && !isLayerTime(layer[k])) problems.push(`${where}: ${k} is ms \u2265 0 or { shots: n } with n \u2265 1.`);
|
|
257
|
+
if (layer.opacity !== void 0 && !(typeof layer.opacity === "number" && layer.opacity >= 0 && layer.opacity <= 1)) problems.push(`${where}: opacity is 0\u20131.`);
|
|
258
|
+
if (layer.fade !== void 0 && !(typeof layer.fade === "number" && layer.fade >= 0)) problems.push(`${where}: fade is ms \u2265 0.`);
|
|
259
|
+
if (layer.values !== void 0 && !isObject(layer.values)) problems.push(`${where}: values must be an object of control values.`);
|
|
260
|
+
});
|
|
261
|
+
if (shot.transition !== void 0) {
|
|
262
|
+
const t = shot.transition;
|
|
263
|
+
if (i === 0) problems.push(`${at} has a transition, but there is no shot before it.`);
|
|
264
|
+
if (!isObject(t) || typeof t.effect !== "string" || !t.effect) problems.push(`${at}: transition needs an effect id.`);
|
|
265
|
+
else {
|
|
266
|
+
if (t.ms !== void 0 && !(typeof t.ms === "number" && t.ms > 0)) problems.push(`${at}: transition ms must be > 0.`);
|
|
267
|
+
const e = _optionalChain([byId, 'optionalAccess', _2 => _2.get, 'call', _3 => _3(t.effect)]);
|
|
268
|
+
if (byId && !e) problems.push(`${at}: the provider has no transition "${t.effect}".`);
|
|
269
|
+
else if (e && !e.uses.includes("transition")) problems.push(`${at}: "${t.effect}" is not a transition (its uses are ${e.uses.join(", ")}).`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
return problems;
|
|
274
|
+
}
|
|
275
|
+
function effectSequenceEffects(sequence) {
|
|
276
|
+
const out = /* @__PURE__ */ new Set();
|
|
277
|
+
for (const shot of sequence.shots) {
|
|
278
|
+
for (const l of shot.layers) if (l.effect) out.add(l.effect);
|
|
279
|
+
if (shot.transition) out.add(shot.transition.effect);
|
|
280
|
+
}
|
|
281
|
+
return [...out];
|
|
282
|
+
}
|
|
283
|
+
function effectSequenceSlots(sequence) {
|
|
284
|
+
const out = /* @__PURE__ */ new Set();
|
|
285
|
+
for (const shot of sequence.shots) for (const l of shot.layers) if (l.subject && "slot" in l.subject) out.add(l.subject.slot);
|
|
286
|
+
return [...out];
|
|
287
|
+
}
|
|
288
|
+
|
|
55
289
|
// src/effects/conformance.ts
|
|
56
|
-
var codeOf = (e) =>
|
|
290
|
+
var codeOf = (e) => _chunk2K5TELHVcjs.isEffectError.call(void 0, e) ? e.code : e instanceof Error ? `untyped ${e.name}: ${e.message}` : String(e);
|
|
57
291
|
async function rejectsWith(code, run) {
|
|
58
292
|
try {
|
|
59
293
|
await run();
|
|
@@ -67,26 +301,26 @@ function checkSummary(e, issues) {
|
|
|
67
301
|
const at = (message) => issues.push({ effectId: e.id, message });
|
|
68
302
|
if (!e.id || typeof e.id !== "string") at("summary has no id");
|
|
69
303
|
if (!e.name) at("summary has no name");
|
|
70
|
-
if (!
|
|
304
|
+
if (!_chunk2K5TELHVcjs.EFFECT_KINDS.includes(e.kind)) at(`kind "${e.kind}" is not one of ${_chunk2K5TELHVcjs.EFFECT_KINDS.join(", ")}`);
|
|
71
305
|
if (!e.category) at("summary has no category");
|
|
72
306
|
if (!Array.isArray(e.uses) || !e.uses.length) at("summary has no uses");
|
|
73
|
-
for (const u of _nullishCoalesce(e.uses, () => ( []))) if (!
|
|
307
|
+
for (const u of _nullishCoalesce(e.uses, () => ( []))) if (!_chunk2K5TELHVcjs.EFFECT_USES.includes(u)) at(`use "${u}" is not one of ${_chunk2K5TELHVcjs.EFFECT_USES.join(", ")}`);
|
|
74
308
|
if (typeof e.transparent !== "boolean") at("transparent is not a boolean");
|
|
75
309
|
if (typeof e.loop !== "boolean") at("loop is not a boolean");
|
|
76
310
|
if (e.duration !== void 0 && !(e.duration > 0)) at("duration must be a positive number of ms when present");
|
|
77
311
|
if (e.backgroundOpacity !== void 0 && (typeof e.backgroundOpacity !== "string" || !e.backgroundOpacity)) at("backgroundOpacity must name a control when present");
|
|
78
312
|
if (e.kind === "camera") {
|
|
79
|
-
if (_optionalChain([e, 'access',
|
|
313
|
+
if (_optionalChain([e, 'access', _4 => _4.uses, 'optionalAccess', _5 => _5.length]) !== 1 || e.uses[0] !== "camera") at('a camera effect must have exactly the use "camera"');
|
|
80
314
|
const m = e.camera;
|
|
81
315
|
if (!m) at("a camera effect needs camera: { role, durationMs }");
|
|
82
316
|
else {
|
|
83
|
-
if (!
|
|
317
|
+
if (!_chunk2K5TELHVcjs.CAMERA_MOVE_ROLES.includes(m.role)) at(`camera.role "${m.role}" is not one of ${_chunk2K5TELHVcjs.CAMERA_MOVE_ROLES.join(", ")}`);
|
|
84
318
|
if (!(Number.isFinite(m.durationMs) && m.durationMs >= 0)) at("camera.durationMs must be a number of ms \u2265 0");
|
|
85
319
|
if (m.cut !== void 0 && !(m.cut >= 0 && m.cut <= 1)) at("camera.cut must be 0\u20131 when present");
|
|
86
320
|
if (e.duration !== void 0 && e.duration !== m.durationMs) at(`duration ${e.duration} differs from camera.durationMs ${m.durationMs}`);
|
|
87
321
|
}
|
|
88
322
|
} else {
|
|
89
|
-
if (_optionalChain([e, 'access',
|
|
323
|
+
if (_optionalChain([e, 'access', _6 => _6.uses, 'optionalAccess', _7 => _7.includes, 'call', _8 => _8("camera")])) at('only camera effects may have the use "camera"');
|
|
90
324
|
if (e.camera !== void 0) at("only camera effects may have camera");
|
|
91
325
|
}
|
|
92
326
|
}
|
|
@@ -95,19 +329,19 @@ function checkDescription(id, d, issues) {
|
|
|
95
329
|
if (d.id !== id) at(`describe("${id}") returned id "${d.id}"`);
|
|
96
330
|
const c = d.controls;
|
|
97
331
|
if (!c || c.type !== "object") at("controls is not an object schema");
|
|
98
|
-
if (_optionalChain([c, 'optionalAccess',
|
|
99
|
-
for (const [name, schema] of Object.entries(_nullishCoalesce(_optionalChain([c, 'optionalAccess',
|
|
332
|
+
if (_optionalChain([c, 'optionalAccess', _9 => _9.additionalProperties]) !== false) at("controls must set additionalProperties: false");
|
|
333
|
+
for (const [name, schema] of Object.entries(_nullishCoalesce(_optionalChain([c, 'optionalAccess', _10 => _10.properties]), () => ( {})))) {
|
|
100
334
|
if (!schema.description || !String(schema.description).trim()) at(`control "${name}" has no description`);
|
|
101
335
|
if (!(name in (_nullishCoalesce(d.defaults, () => ( {}))))) at(`control "${name}" has no default`);
|
|
102
336
|
}
|
|
103
|
-
for (const name of Object.keys(_nullishCoalesce(d.defaults, () => ( {})))) if (!(name in (_nullishCoalesce(_optionalChain([c, 'optionalAccess',
|
|
337
|
+
for (const name of Object.keys(_nullishCoalesce(d.defaults, () => ( {})))) if (!(name in (_nullishCoalesce(_optionalChain([c, 'optionalAccess', _11 => _11.properties]), () => ( {}))))) at(`default "${name}" is not a control`);
|
|
104
338
|
if (d.backgroundOpacity !== void 0) {
|
|
105
|
-
const control = _optionalChain([c, 'optionalAccess',
|
|
339
|
+
const control = _optionalChain([c, 'optionalAccess', _12 => _12.properties, 'optionalAccess', _13 => _13[d.backgroundOpacity]]);
|
|
106
340
|
if (!control) at(`backgroundOpacity "${d.backgroundOpacity}" is not a control`);
|
|
107
341
|
else if (control.type !== "number" || control.minimum !== 0 || control.maximum !== 1) at(`backgroundOpacity "${d.backgroundOpacity}" must be a number control from 0 to 1`);
|
|
108
342
|
}
|
|
109
|
-
for (const e of
|
|
110
|
-
for (const p of _nullishCoalesce(d.presets, () => ( []))) for (const e of
|
|
343
|
+
for (const e of _chunk2K5TELHVcjs.effectValueErrors.call(void 0, d, d.defaults)) at(`default ${e.path}: ${e.message}`);
|
|
344
|
+
for (const p of _nullishCoalesce(d.presets, () => ( []))) for (const e of _chunk2K5TELHVcjs.effectValueErrors.call(void 0, d, p.values)) at(`preset "${p.name}" ${e.path}: ${e.message}`);
|
|
111
345
|
for (const input2 of _nullishCoalesce(d.inputs, () => ( []))) {
|
|
112
346
|
if (!input2.name || !input2.description) at("every input needs a name and a description");
|
|
113
347
|
if (input2.kind !== "image" && input2.kind !== "audio") at(`input "${input2.name}" has kind "${input2.kind}"`);
|
|
@@ -118,7 +352,7 @@ function checkDescription(id, d, issues) {
|
|
|
118
352
|
}
|
|
119
353
|
}
|
|
120
354
|
function grey(size) {
|
|
121
|
-
const p =
|
|
355
|
+
const p = _chunk2K5TELHVcjs.createEffectPixels.call(void 0, size, size);
|
|
122
356
|
p.data.fill(128);
|
|
123
357
|
return p;
|
|
124
358
|
}
|
|
@@ -135,7 +369,7 @@ async function checkRender(provider, d, size, issues) {
|
|
|
135
369
|
}
|
|
136
370
|
try {
|
|
137
371
|
const out = await renderer.render({ time: 0, inputs });
|
|
138
|
-
if (!
|
|
372
|
+
if (!_chunk2K5TELHVcjs.isEffectPixels.call(void 0, out)) at("render did not return EffectPixels");
|
|
139
373
|
else if (out.width !== size || out.height !== size || out.data.length !== size * size * 4) at(`render returned ${out.width}\xD7${out.height}, not ${size}\xD7${size}`);
|
|
140
374
|
} catch (e) {
|
|
141
375
|
at(`render failed: ${codeOf(e)}`);
|
|
@@ -165,10 +399,10 @@ async function checkCamera(provider, d, issues) {
|
|
|
165
399
|
at("cameraView must be synchronous; it returned a Promise");
|
|
166
400
|
return;
|
|
167
401
|
}
|
|
168
|
-
if (!
|
|
402
|
+
if (!_chunk2K5TELHVcjs.isCameraView.call(void 0, view)) at(`cameraView at u ${u} is not a CameraView (zoom > 0, finite scrollX and scrollY): ${JSON.stringify(view)}`);
|
|
169
403
|
else views.push(view);
|
|
170
404
|
const again = provider.cameraView(d.id, ctx(u));
|
|
171
|
-
if (
|
|
405
|
+
if (_chunk2K5TELHVcjs.isCameraView.call(void 0, view) && !sameView(view, again)) at(`cameraView is not pure: two calls at u ${u} gave different views`);
|
|
172
406
|
} catch (e) {
|
|
173
407
|
at(`cameraView at u ${u} failed: ${codeOf(e)}`);
|
|
174
408
|
}
|
|
@@ -178,10 +412,10 @@ async function checkCamera(provider, d, issues) {
|
|
|
178
412
|
if (provider.sampleCameraMove && views.length === 5) {
|
|
179
413
|
try {
|
|
180
414
|
const sample = await provider.sampleCameraMove(d.id, { from: WIDE, to, ms, stage: STAGE, fps: 10 });
|
|
181
|
-
const keys = _optionalChain([sample, 'optionalAccess',
|
|
415
|
+
const keys = _optionalChain([sample, 'optionalAccess', _14 => _14.keys]);
|
|
182
416
|
if (!Array.isArray(keys) || keys.length < 2) at("sampleCameraMove returned fewer than two keys");
|
|
183
417
|
else {
|
|
184
|
-
if (keys.some((k, i) => !
|
|
418
|
+
if (keys.some((k, i) => !_chunk2K5TELHVcjs.isCameraView.call(void 0, k.view) || !Number.isFinite(k.t) || i > 0 && k.t < keys[i - 1].t)) at("sampleCameraMove keys must be CameraViews in time order");
|
|
185
419
|
if (keys[0].t !== 0 || keys[keys.length - 1].t !== ms) at(`sampleCameraMove keys must run from 0 to ${ms} ms, got ${keys[0].t} to ${keys[keys.length - 1].t}`);
|
|
186
420
|
else if (!near(keys[0].view, views[0]) || !near(keys[keys.length - 1].view, views[4])) at("sampleCameraMove disagrees with cameraView at the start or end of the move");
|
|
187
421
|
if (camera.cut !== void 0 && sample.cut === void 0) at("sampleCameraMove gave no cut for a move that cuts");
|
|
@@ -191,20 +425,107 @@ async function checkCamera(provider, d, issues) {
|
|
|
191
425
|
}
|
|
192
426
|
}
|
|
193
427
|
}
|
|
428
|
+
var wrongValue = (slot) => slot.type === "number" ? "not a number" : slot.type === "text" ? 42 : slot.type === "color" ? "blue" : 42;
|
|
429
|
+
function checkSlot(templateId, slot, issues) {
|
|
430
|
+
const at = (message) => issues.push({ templateId, message: `slot ${JSON.stringify(_optionalChain([slot, 'optionalAccess', _15 => _15.name]))}: ${message}` });
|
|
431
|
+
if (!slot || typeof slot.name !== "string" || !/^[A-Za-z][\w-]*$/.test(slot.name)) return at('needs a name of letters, digits, "-" and "_", starting with a letter');
|
|
432
|
+
if (!_chunk2K5TELHVcjs.EFFECT_TEMPLATE_SLOT_TYPES.includes(slot.type)) return at(`type "${slot.type}" is not one of ${_chunk2K5TELHVcjs.EFFECT_TEMPLATE_SLOT_TYPES.join(", ")}`);
|
|
433
|
+
if (typeof slot.label !== "string" || !slot.label) at("needs a label");
|
|
434
|
+
if (isSubjectTemplateSlot(slot)) {
|
|
435
|
+
if (typeof slot.hasDefault !== "boolean") at("a subject slot needs hasDefault (a boolean)");
|
|
436
|
+
if ("default" in slot) at("a subject slot describes hasDefault, not its default");
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
const fallback = slot.default;
|
|
440
|
+
if (fallback === void 0) return at("needs a default");
|
|
441
|
+
const problem = templateValueProblem(slot, fallback);
|
|
442
|
+
if (problem) at(`its default does not fit: ${problem}`);
|
|
443
|
+
if (slot.type === "number" && slot.min !== void 0 && slot.max !== void 0 && slot.min > slot.max) at("min is above max");
|
|
444
|
+
}
|
|
445
|
+
async function checkTemplates(provider, list, issues) {
|
|
446
|
+
const top = (message) => issues.push({ message });
|
|
447
|
+
const templates = await provider.listTemplates();
|
|
448
|
+
if (!Array.isArray(templates)) return top("listTemplates did not return a list");
|
|
449
|
+
const seen = /* @__PURE__ */ new Set();
|
|
450
|
+
for (const t of templates) if (seen.has(t.id)) top(`duplicate template id "${t.id}"`);
|
|
451
|
+
else seen.add(t.id);
|
|
452
|
+
const unknownDescribe = await rejectsWith("unknown_template", () => provider.describeTemplate("__no_such_template__"));
|
|
453
|
+
if (unknownDescribe) top(`describeTemplate of an unknown id ${unknownDescribe}`);
|
|
454
|
+
const unknownFill = await rejectsWith("unknown_template", () => provider.instantiateTemplate("__no_such_template__"));
|
|
455
|
+
if (unknownFill) top(`instantiateTemplate of an unknown id ${unknownFill}`);
|
|
456
|
+
for (const summary of templates) {
|
|
457
|
+
const id = summary.id;
|
|
458
|
+
const at = (message) => issues.push({ templateId: id, message });
|
|
459
|
+
if (!id || typeof id !== "string") top("a template has no id");
|
|
460
|
+
if (!summary.name) at("template has no name");
|
|
461
|
+
if (!summary.description) at("template has no description");
|
|
462
|
+
if (!(Number.isInteger(summary.shots) && summary.shots >= 1)) at("shots must be a whole number \u2265 1");
|
|
463
|
+
if (summary.durationMs !== void 0 && !(summary.durationMs > 0)) at("durationMs must be > 0 when present");
|
|
464
|
+
let slots;
|
|
465
|
+
try {
|
|
466
|
+
const d = await provider.describeTemplate(id);
|
|
467
|
+
if (d.id !== id) at(`describeTemplate returned id "${d.id}"`);
|
|
468
|
+
if (!Array.isArray(d.slots)) {
|
|
469
|
+
at("describeTemplate gave no slots list");
|
|
470
|
+
continue;
|
|
471
|
+
}
|
|
472
|
+
slots = d.slots;
|
|
473
|
+
const names = /* @__PURE__ */ new Set();
|
|
474
|
+
for (const slot of slots) {
|
|
475
|
+
if (names.has(_optionalChain([slot, 'optionalAccess', _16 => _16.name]))) at(`slot "${slot.name}" is declared twice`);
|
|
476
|
+
names.add(_optionalChain([slot, 'optionalAccess', _17 => _17.name]));
|
|
477
|
+
checkSlot(id, slot, issues);
|
|
478
|
+
}
|
|
479
|
+
} catch (e) {
|
|
480
|
+
at(`describeTemplate failed: ${codeOf(e)}`);
|
|
481
|
+
continue;
|
|
482
|
+
}
|
|
483
|
+
try {
|
|
484
|
+
const result = await provider.instantiateTemplate(id);
|
|
485
|
+
if (!result.ok) at(`instantiateTemplate with the defaults failed: ${result.errors.join(" ")}`);
|
|
486
|
+
else {
|
|
487
|
+
for (const p of checkEffectSequence(result.sequence, list)) at(`with the defaults, ${p}`);
|
|
488
|
+
if (_optionalChain([result, 'access', _18 => _18.sequence, 'optionalAccess', _19 => _19.shots, 'optionalAccess', _20 => _20.length]) !== summary.shots) at(`listTemplates says ${summary.shots} shots; the sequence has ${_optionalChain([result, 'access', _21 => _21.sequence, 'optionalAccess', _22 => _22.shots, 'optionalAccess', _23 => _23.length])}`);
|
|
489
|
+
if (!Array.isArray(result.openSlots) || !Array.isArray(result.notes)) at("instantiateTemplate needs openSlots and notes lists");
|
|
490
|
+
else {
|
|
491
|
+
const open = Array.isArray(_optionalChain([result, 'access', _24 => _24.sequence, 'optionalAccess', _25 => _25.shots])) ? effectSequenceSlots(result.sequence) : [];
|
|
492
|
+
if (open.some((s) => !result.openSlots.includes(s))) at(`openSlots ${JSON.stringify(result.openSlots)} misses slots the sequence leaves open (${open.join(", ")})`);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
} catch (e) {
|
|
496
|
+
at(`instantiateTemplate with the defaults failed: ${codeOf(e)}`);
|
|
497
|
+
}
|
|
498
|
+
const bad = { __no_such_slot__: "x", ...slots[0] ? { [slots[0].name]: wrongValue(slots[0]) } : {} };
|
|
499
|
+
try {
|
|
500
|
+
const result = await provider.instantiateTemplate(id, bad);
|
|
501
|
+
if (result.ok) at("instantiateTemplate accepted an unknown slot and a value of the wrong type");
|
|
502
|
+
else if (!result.errors.length || result.errors.some((e) => typeof e !== "string" || !e)) at("instantiateTemplate refused bad values without a sentence for each");
|
|
503
|
+
else if (slots[0] && result.errors.length < 2) at("instantiateTemplate should refuse every bad value at once (an unknown slot and a wrong type gave one error)");
|
|
504
|
+
} catch (e) {
|
|
505
|
+
at(`instantiateTemplate with bad values threw (${codeOf(e)}) instead of returning { ok: false, errors }`);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
194
509
|
async function checkEffectProvider(provider, options = {}) {
|
|
195
510
|
const issues = [];
|
|
196
511
|
const top = (message) => issues.push({ message });
|
|
197
512
|
if (!provider.id) top("provider has no id");
|
|
198
513
|
const caps = provider.capabilities;
|
|
199
514
|
for (const k of ["supportsWorker", "supportsFloat", "supportsMask", "supportsHostImages", "supportsVector"]) {
|
|
200
|
-
if (typeof _optionalChain([caps, 'optionalAccess',
|
|
515
|
+
if (typeof _optionalChain([caps, 'optionalAccess', _26 => _26[k]]) !== "boolean") top(`capabilities.${k} is not a boolean`);
|
|
201
516
|
}
|
|
202
|
-
if (_optionalChain([caps, 'optionalAccess',
|
|
203
|
-
if (_optionalChain([caps, 'optionalAccess',
|
|
204
|
-
if (_optionalChain([caps, 'optionalAccess',
|
|
205
|
-
if (_optionalChain([caps, 'optionalAccess',
|
|
206
|
-
if (_optionalChain([caps, 'optionalAccess',
|
|
517
|
+
if (_optionalChain([caps, 'optionalAccess', _27 => _27.supportsAuthoring]) !== void 0 && typeof caps.supportsAuthoring !== "boolean") top("capabilities.supportsAuthoring is not a boolean");
|
|
518
|
+
if (_optionalChain([caps, 'optionalAccess', _28 => _28.supportsVector]) && typeof provider.applyVectorEffect !== "function") top("supportsVector is set but applyVectorEffect is missing");
|
|
519
|
+
if (_optionalChain([caps, 'optionalAccess', _29 => _29.supportsAuthoring]) && typeof provider.openAuthoring !== "function") top("supportsAuthoring is set but openAuthoring is missing");
|
|
520
|
+
if (_optionalChain([caps, 'optionalAccess', _30 => _30.supportsCamera]) !== void 0 && typeof caps.supportsCamera !== "boolean") top("capabilities.supportsCamera is not a boolean");
|
|
521
|
+
if (_optionalChain([caps, 'optionalAccess', _31 => _31.supportsCamera]) && typeof provider.cameraView !== "function") top("supportsCamera is set but cameraView is missing");
|
|
207
522
|
if (provider.sampleCameraMove && typeof provider.cameraView !== "function") top("sampleCameraMove is present but cameraView is missing");
|
|
523
|
+
if (_optionalChain([caps, 'optionalAccess', _32 => _32.supportsTemplates]) !== void 0 && typeof caps.supportsTemplates !== "boolean") top("capabilities.supportsTemplates is not a boolean");
|
|
524
|
+
const templateMethods = ["listTemplates", "describeTemplate", "instantiateTemplate"];
|
|
525
|
+
if (_optionalChain([caps, 'optionalAccess', _33 => _33.supportsTemplates])) {
|
|
526
|
+
for (const m of templateMethods) if (typeof provider[m] !== "function") top(`supportsTemplates is set but ${m} is missing`);
|
|
527
|
+
}
|
|
528
|
+
if (!_optionalChain([caps, 'optionalAccess', _34 => _34.supportsTemplates]) && templateMethods.some((m) => typeof provider[m] === "function")) top("template methods are present but capabilities.supportsTemplates is not set");
|
|
208
529
|
const list = await provider.list();
|
|
209
530
|
const ids = /* @__PURE__ */ new Set();
|
|
210
531
|
for (const e of list) {
|
|
@@ -212,10 +533,10 @@ async function checkEffectProvider(provider, options = {}) {
|
|
|
212
533
|
ids.add(e.id);
|
|
213
534
|
checkSummary(e, issues);
|
|
214
535
|
}
|
|
215
|
-
if (!_optionalChain([caps, 'optionalAccess',
|
|
536
|
+
if (!_optionalChain([caps, 'optionalAccess', _35 => _35.supportsCamera]) && list.some((e) => e.kind === "camera")) top("the catalog lists camera effects but capabilities.supportsCamera is not set");
|
|
216
537
|
const all = await provider.search("");
|
|
217
538
|
if (all.length !== list.length) top(`search("") returned ${all.length} effects, list() ${list.length}`);
|
|
218
|
-
const firstUse = _optionalChain([list, 'access',
|
|
539
|
+
const firstUse = _optionalChain([list, 'access', _36 => _36[0], 'optionalAccess', _37 => _37.uses, 'access', _38 => _38[0]]);
|
|
219
540
|
if (firstUse) {
|
|
220
541
|
const filtered = await provider.search("", { use: firstUse });
|
|
221
542
|
if (filtered.some((e) => !e.uses.includes(firstUse))) top(`search("", { use: "${firstUse}" }) returned effects without that use`);
|
|
@@ -224,7 +545,7 @@ async function checkEffectProvider(provider, options = {}) {
|
|
|
224
545
|
if (unknown) top(`describe of an unknown id ${unknown}`);
|
|
225
546
|
const unknownRenderer = await rejectsWith("unknown_effect", () => provider.createRenderer("__no_such_effect__", { width: 4, height: 4 }));
|
|
226
547
|
if (unknownRenderer) top(`createRenderer of an unknown id ${unknownRenderer}`);
|
|
227
|
-
if (_optionalChain([caps, 'optionalAccess',
|
|
548
|
+
if (_optionalChain([caps, 'optionalAccess', _39 => _39.supportsCamera]) && provider.cameraView) {
|
|
228
549
|
const probe = { from: WIDE, to: CLOSE, u: 0.5, ms: 1e3, stage: STAGE };
|
|
229
550
|
const unknownCamera = await rejectsWith("unknown_effect", () => provider.cameraView("__no_such_effect__", probe));
|
|
230
551
|
if (unknownCamera) top(`cameraView of an unknown id ${unknownCamera}`);
|
|
@@ -256,7 +577,7 @@ async function checkEffectProvider(provider, options = {}) {
|
|
|
256
577
|
if (bad) issues.push({ effectId: id, message: `applyVectorEffect with an unknown control ${bad}` });
|
|
257
578
|
}
|
|
258
579
|
}
|
|
259
|
-
if (_optionalChain([caps, 'optionalAccess',
|
|
580
|
+
if (_optionalChain([caps, 'optionalAccess', _40 => _40.supportsAuthoring]) && options.authoring !== false && typeof provider.openAuthoring === "function") {
|
|
260
581
|
const targetEffect = (await Promise.all((_nullishCoalesce(options.ids, () => ( [...ids]))).map((id) => provider.describe(id)))).find(
|
|
261
582
|
(d) => d.kind !== "motion" && d.kind !== "vector" && d.kind !== "camera"
|
|
262
583
|
);
|
|
@@ -307,9 +628,125 @@ async function checkEffectProvider(provider, options = {}) {
|
|
|
307
628
|
}
|
|
308
629
|
}
|
|
309
630
|
}
|
|
631
|
+
if (_optionalChain([caps, 'optionalAccess', _41 => _41.supportsTemplates]) && options.templates !== false && templateMethods.every((m) => typeof provider[m] === "function")) await checkTemplates(provider, list, issues);
|
|
310
632
|
return issues;
|
|
311
633
|
}
|
|
312
634
|
|
|
635
|
+
// src/effects/fake-templates.ts
|
|
636
|
+
var PLACEHOLDER = /\{\{([A-Za-z][\w-]*)\}\}/g;
|
|
637
|
+
var WHOLE = /^\{\{([A-Za-z][\w-]*)\}\}$/;
|
|
638
|
+
var picture = (label, tint) => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 90" width="160" height="90"><rect width="160" height="90" fill="${tint}"/><text x="80" y="50" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#fff">${label}</text></svg>`;
|
|
639
|
+
var TEMPLATES = [
|
|
640
|
+
{
|
|
641
|
+
summary: { id: "fake.title-sequence", name: "Title sequence", description: "A gradient behind a title with a lower-third bar, then a crossfade to a closing shot with a caption.", tags: ["title", "intro"], shots: 2, durationMs: 4600 },
|
|
642
|
+
slots: [
|
|
643
|
+
{ name: "title", type: "text", label: "Title", default: "Hello", maxLength: 40 },
|
|
644
|
+
{ name: "subtitle", type: "text", label: "Closing caption", default: "See you soon", maxLength: 60 },
|
|
645
|
+
{ name: "accent", type: "color", label: "Accent colour", default: "#0ea5e9" },
|
|
646
|
+
{ name: "holdMs", type: "number", label: "Time on each shot (ms)", default: 2e3, min: 500, max: 1e4, integer: true }
|
|
647
|
+
],
|
|
648
|
+
sequence: {
|
|
649
|
+
name: "title-sequence",
|
|
650
|
+
title: "{{title}}",
|
|
651
|
+
stage: { width: 1280, height: 720 },
|
|
652
|
+
shots: [
|
|
653
|
+
{
|
|
654
|
+
hold: "{{holdMs}}",
|
|
655
|
+
title: "{{title}}",
|
|
656
|
+
layers: [
|
|
657
|
+
{ id: "backdrop", effect: "fake.gradient", role: "background", values: { from: "{{accent}}" }, until: { shots: 1 } },
|
|
658
|
+
{ id: "bar", effect: "fake.bar", role: "overlay", values: { color: "{{accent}}" }, from: 200 }
|
|
659
|
+
]
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
hold: "{{holdMs}}",
|
|
663
|
+
caption: "{{subtitle}}",
|
|
664
|
+
transition: { effect: "fake.crossfade", ms: 600 },
|
|
665
|
+
layers: [{ id: "closing", effect: "fake.gradient", role: "background", values: { from: "#111827", to: "{{accent}}" } }]
|
|
666
|
+
}
|
|
667
|
+
]
|
|
668
|
+
}
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
summary: { id: "fake.picture-reveal", name: "Picture reveal", description: "A tinted picture, then a crossfade to the picture in full colour with a logo over it and a caption.", tags: ["product", "reveal"], shots: 2, durationMs: 4800 },
|
|
672
|
+
slots: [
|
|
673
|
+
{ name: "picture", type: "image", label: "Picture", description: "The picture to reveal.", hasDefault: true, subjectDefault: picture("Picture", "#64748b") },
|
|
674
|
+
{ name: "logo", type: "image", label: "Logo", description: "A logo shown over the second shot; the host fills it when none is given.", hasDefault: false },
|
|
675
|
+
{ name: "caption", type: "text", label: "Caption", default: "Now in colour", maxLength: 50 },
|
|
676
|
+
{ name: "holdMs", type: "number", label: "Time on each shot (ms)", default: 2e3, min: 500, max: 1e4, integer: true }
|
|
677
|
+
],
|
|
678
|
+
sequence: {
|
|
679
|
+
name: "picture-reveal",
|
|
680
|
+
stage: { width: 1280, height: 720 },
|
|
681
|
+
shots: [
|
|
682
|
+
{ hold: "{{holdMs}}", layers: [{ id: "tinted", effect: "fake.tint", subject: { slot: "picture" }, values: { color: "#704214", amount: 0.6 } }] },
|
|
683
|
+
{
|
|
684
|
+
hold: "{{holdMs}}",
|
|
685
|
+
caption: "{{caption}}",
|
|
686
|
+
transition: { effect: "fake.crossfade", ms: 800 },
|
|
687
|
+
layers: [
|
|
688
|
+
{ id: "picture", subject: { slot: "picture" }, role: "background" },
|
|
689
|
+
{ id: "logo", subject: { slot: "logo" }, role: "overlay", rect: { x: 1040, y: 40, width: 200, height: 112 }, fade: 300 }
|
|
690
|
+
]
|
|
691
|
+
}
|
|
692
|
+
]
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
];
|
|
696
|
+
var describeOf = (t) => ({
|
|
697
|
+
...t.summary,
|
|
698
|
+
slots: t.slots.map(({ subjectDefault: _d, ...slot }) => slot)
|
|
699
|
+
});
|
|
700
|
+
function subjectOf(type, value) {
|
|
701
|
+
if (typeof value !== "string") return value;
|
|
702
|
+
if (value.trimStart().startsWith("<svg") || type === "svg") return { svg: value };
|
|
703
|
+
return type === "video" ? { video: value } : { image: value };
|
|
704
|
+
}
|
|
705
|
+
function fill(t, values) {
|
|
706
|
+
const slots = new Map(t.slots.map((s) => [s.name, s]));
|
|
707
|
+
const valueOf = (name) => {
|
|
708
|
+
const s = slots.get(name);
|
|
709
|
+
return _nullishCoalesce(values[name], () => ( (isSubjectTemplateSlot(s) ? s.subjectDefault : s.default)));
|
|
710
|
+
};
|
|
711
|
+
const walk = (v, key) => {
|
|
712
|
+
if (typeof v === "string") {
|
|
713
|
+
const whole = WHOLE.exec(v);
|
|
714
|
+
if (whole && slots.has(whole[1])) return valueOf(whole[1]);
|
|
715
|
+
return v.replace(PLACEHOLDER, (m, name) => slots.has(name) ? String(valueOf(name)) : m);
|
|
716
|
+
}
|
|
717
|
+
if (Array.isArray(v)) return v.map((x) => walk(x));
|
|
718
|
+
if (!v || typeof v !== "object") return v;
|
|
719
|
+
if (key === "subject" && typeof v.slot === "string") {
|
|
720
|
+
const s = slots.get(v.slot);
|
|
721
|
+
const value = s ? valueOf(s.name) : void 0;
|
|
722
|
+
return s && value !== void 0 ? subjectOf(s.type, value) : v;
|
|
723
|
+
}
|
|
724
|
+
return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, walk(x, k)]));
|
|
725
|
+
};
|
|
726
|
+
return walk(t.sequence);
|
|
727
|
+
}
|
|
728
|
+
function fakeTemplateMethods() {
|
|
729
|
+
const byId = new Map(TEMPLATES.map((t) => [t.summary.id, t]));
|
|
730
|
+
const get = (id) => {
|
|
731
|
+
const t = byId.get(id);
|
|
732
|
+
if (!t) throw new (0, _chunk2K5TELHVcjs.UnknownTemplateError)(id, "the fake provider");
|
|
733
|
+
return t;
|
|
734
|
+
};
|
|
735
|
+
return {
|
|
736
|
+
listTemplates: (options) => searchTemplateSummaries(TEMPLATES.map((t) => t.summary), options).map((s) => structuredClone(s)),
|
|
737
|
+
describeTemplate: (id) => structuredClone(describeOf(get(id))),
|
|
738
|
+
instantiateTemplate(id, values = {}, options = {}) {
|
|
739
|
+
const t = get(id);
|
|
740
|
+
const errors = checkTemplateValues(describeOf(t).slots, values);
|
|
741
|
+
if (options.name !== void 0 && (typeof options.name !== "string" || !EFFECT_SEQUENCE_NAME.test(options.name))) errors.push(`The sequence name is lowercase words and dashes (like "${t.summary.id.replace(/^fake\./, "")}").`);
|
|
742
|
+
if (errors.length) return { ok: false, errors };
|
|
743
|
+
const sequence = fill(t, values);
|
|
744
|
+
if (options.name) sequence.name = options.name;
|
|
745
|
+
return { ok: true, sequence, openSlots: effectSequenceSlots(sequence), notes: [] };
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
|
|
313
750
|
// src/effects/fake.ts
|
|
314
751
|
var HEX = "^#[0-9a-fA-F]{6}$";
|
|
315
752
|
var colour = (description) => ({ type: "string", pattern: HEX, description });
|
|
@@ -550,16 +987,16 @@ var hexToRgb = (hex) => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16));
|
|
|
550
987
|
var smooth = (t) => t * t * (3 - 2 * t);
|
|
551
988
|
var clamp01 = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
|
|
552
989
|
function input(request, name, id, width, height) {
|
|
553
|
-
const src = _optionalChain([request, 'access',
|
|
554
|
-
if (!src) throw new (0,
|
|
555
|
-
if (!
|
|
990
|
+
const src = _optionalChain([request, 'access', _42 => _42.inputs, 'optionalAccess', _43 => _43[name]]);
|
|
991
|
+
if (!src) throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)(`Effect "${id}" needs an input named "${name}".`, id);
|
|
992
|
+
if (!_chunk2K5TELHVcjs.isEffectPixels.call(void 0, src)) throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)(`The fake provider only takes EffectPixels inputs ("${name}").`, id);
|
|
556
993
|
if (src.width !== width || src.height !== height) {
|
|
557
|
-
throw new (0,
|
|
994
|
+
throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)(`Input "${name}" is ${src.width}\xD7${src.height}; the renderer is ${width}\xD7${height}.`, id);
|
|
558
995
|
}
|
|
559
996
|
return src;
|
|
560
997
|
}
|
|
561
998
|
function renderPixels(d, v, request, width, height) {
|
|
562
|
-
const out =
|
|
999
|
+
const out = _chunk2K5TELHVcjs.createEffectPixels.call(void 0, width, height);
|
|
563
1000
|
const o = out.data;
|
|
564
1001
|
switch (d.id) {
|
|
565
1002
|
case "fake.invert": {
|
|
@@ -625,7 +1062,7 @@ function renderPixels(d, v, request, width, height) {
|
|
|
625
1062
|
break;
|
|
626
1063
|
}
|
|
627
1064
|
default:
|
|
628
|
-
throw new (0,
|
|
1065
|
+
throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)(`"${d.id}" is a ${d.kind} effect; use applyVectorEffect.`, d.id);
|
|
629
1066
|
}
|
|
630
1067
|
return out;
|
|
631
1068
|
}
|
|
@@ -655,22 +1092,22 @@ function cameraViewOf(d, ctx, v) {
|
|
|
655
1092
|
case "fake.drift":
|
|
656
1093
|
return viewAt(x0, y0, from.zoom * lerp(1, v.scale, smooth(u)), ctx);
|
|
657
1094
|
default:
|
|
658
|
-
throw new (0,
|
|
1095
|
+
throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)(`"${d.id}" is a ${d.kind} effect, not a camera move.`, d.id);
|
|
659
1096
|
}
|
|
660
1097
|
}
|
|
661
1098
|
function toFloat(p) {
|
|
662
1099
|
const f = new Float32Array(p.data.length);
|
|
663
1100
|
for (let i = 0; i < f.length; i += 4) {
|
|
664
|
-
f[i] =
|
|
665
|
-
f[i + 1] =
|
|
666
|
-
f[i + 2] =
|
|
1101
|
+
f[i] = _chunk2K5TELHVcjs.srgbToLinear.call(void 0, p.data[i] / 255);
|
|
1102
|
+
f[i + 1] = _chunk2K5TELHVcjs.srgbToLinear.call(void 0, p.data[i + 1] / 255);
|
|
1103
|
+
f[i + 2] = _chunk2K5TELHVcjs.srgbToLinear.call(void 0, p.data[i + 2] / 255);
|
|
667
1104
|
f[i + 3] = p.data[i + 3] / 255;
|
|
668
1105
|
}
|
|
669
|
-
return
|
|
1106
|
+
return _chunk2K5TELHVcjs.encodeEffectFloat.call(void 0, { ...p, float: f });
|
|
670
1107
|
}
|
|
671
1108
|
function maskResult(out, mask, source, id) {
|
|
672
|
-
if (!
|
|
673
|
-
throw new (0,
|
|
1109
|
+
if (!_chunk2K5TELHVcjs.isEffectPixels.call(void 0, mask) || mask.width !== out.width || mask.height !== out.height) {
|
|
1110
|
+
throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)("The mask must be EffectPixels the size of the renderer.", id);
|
|
674
1111
|
}
|
|
675
1112
|
const o = out.data;
|
|
676
1113
|
for (let i = 0; i < o.length; i += 4) {
|
|
@@ -689,6 +1126,7 @@ function createFakeEffectProvider(options = {}) {
|
|
|
689
1126
|
supportsVector: true,
|
|
690
1127
|
supportsAuthoring,
|
|
691
1128
|
...options.camera ? { supportsCamera: true } : {},
|
|
1129
|
+
...options.templates ? { supportsTemplates: true } : {},
|
|
692
1130
|
maxSize: 8192,
|
|
693
1131
|
...options.capabilities
|
|
694
1132
|
};
|
|
@@ -696,32 +1134,32 @@ function createFakeEffectProvider(options = {}) {
|
|
|
696
1134
|
const byId = new Map(all.map((d) => [d.id, d]));
|
|
697
1135
|
const get = (id) => {
|
|
698
1136
|
const d = byId.get(id);
|
|
699
|
-
if (!d) throw new (0,
|
|
1137
|
+
if (!d) throw new (0, _chunk2K5TELHVcjs.UnknownEffectError)(id, "the fake provider");
|
|
700
1138
|
return d;
|
|
701
1139
|
};
|
|
702
1140
|
const summaries = all.map(summaryOf);
|
|
703
1141
|
const camera = (id, ctx, values) => {
|
|
704
1142
|
const d = get(id);
|
|
705
|
-
if (d.kind !== "camera") throw new (0,
|
|
706
|
-
if (!(ctx.u >= 0 && ctx.u <= 1)) throw new (0,
|
|
707
|
-
return cameraViewOf(d, ctx,
|
|
1143
|
+
if (d.kind !== "camera") throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect, not a camera move.`, id);
|
|
1144
|
+
if (!(ctx.u >= 0 && ctx.u <= 1)) throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)(`u must be 0\u20131 through the move, got ${ctx.u}.`, id);
|
|
1145
|
+
return cameraViewOf(d, ctx, _chunk2K5TELHVcjs.resolveEffectValues.call(void 0, d, values));
|
|
708
1146
|
};
|
|
709
1147
|
const provider = {
|
|
710
1148
|
id: "fake",
|
|
711
1149
|
name: "Fake effects",
|
|
712
1150
|
version: "1",
|
|
713
1151
|
capabilities,
|
|
714
|
-
list: (o) =>
|
|
715
|
-
search: (q, o) =>
|
|
1152
|
+
list: (o) => _chunk2K5TELHVcjs.searchEffectSummaries.call(void 0, summaries, "", o),
|
|
1153
|
+
search: (q, o) => _chunk2K5TELHVcjs.searchEffectSummaries.call(void 0, summaries, q, o),
|
|
716
1154
|
describe: (id) => structuredClone(get(id)),
|
|
717
1155
|
createRenderer(id, ro) {
|
|
718
1156
|
const d = get(id);
|
|
719
|
-
if (d.kind === "camera") throw new (0,
|
|
720
|
-
if (d.kind !== "shader") throw new (0,
|
|
1157
|
+
if (d.kind === "camera") throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)(`"${id}" is a camera move: it moves a scene's camera and draws no pixels. Use cameraView.`, id);
|
|
1158
|
+
if (d.kind !== "shader") throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect; use applyVectorEffect.`, id);
|
|
721
1159
|
const { width, height } = ro;
|
|
722
1160
|
const depth = _nullishCoalesce(ro.depth, () => ( 8));
|
|
723
1161
|
if (!(width > 0 && height > 0) || width > capabilities.maxSize || height > capabilities.maxSize) {
|
|
724
|
-
throw new (0,
|
|
1162
|
+
throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)(`Renderer size ${width}\xD7${height} is outside 1\u2013${capabilities.maxSize}.`, id);
|
|
725
1163
|
}
|
|
726
1164
|
let disposed = false;
|
|
727
1165
|
return {
|
|
@@ -730,16 +1168,16 @@ function createFakeEffectProvider(options = {}) {
|
|
|
730
1168
|
height,
|
|
731
1169
|
depth,
|
|
732
1170
|
async render(request) {
|
|
733
|
-
if (disposed) throw new (0,
|
|
1171
|
+
if (disposed) throw new (0, _chunk2K5TELHVcjs.EffectDisposedError)(id);
|
|
734
1172
|
if (!Number.isFinite(request.time) || request.time < 0) {
|
|
735
|
-
throw new (0,
|
|
1173
|
+
throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)(`time must be a finite number of ms \u2265 0, got ${request.time}.`, id);
|
|
736
1174
|
}
|
|
737
|
-
const values =
|
|
738
|
-
_optionalChain([options, 'access',
|
|
1175
|
+
const values = _chunk2K5TELHVcjs.resolveEffectValues.call(void 0, d, request.values);
|
|
1176
|
+
_optionalChain([options, 'access', _44 => _44.onRender, 'optionalCall', _45 => _45(id, request)]);
|
|
739
1177
|
const out = renderPixels(d, values, request, width, height);
|
|
740
1178
|
if (request.mask) {
|
|
741
|
-
if (!capabilities.supportsMask) throw new (0,
|
|
742
|
-
const source = d.uses.includes("filter") ? _optionalChain([request, 'access',
|
|
1179
|
+
if (!capabilities.supportsMask) throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)("This provider does not take masks.", id);
|
|
1180
|
+
const source = d.uses.includes("filter") ? _optionalChain([request, 'access', _46 => _46.inputs, 'optionalAccess', _47 => _47.source]) : void 0;
|
|
743
1181
|
maskResult(out, request.mask, source, id);
|
|
744
1182
|
}
|
|
745
1183
|
return depth > 8 && capabilities.supportsFloat ? toFloat(out) : out;
|
|
@@ -751,8 +1189,8 @@ function createFakeEffectProvider(options = {}) {
|
|
|
751
1189
|
},
|
|
752
1190
|
applyVectorEffect(id, target, values) {
|
|
753
1191
|
const d = get(id);
|
|
754
|
-
if (d.kind !== "motion" && d.kind !== "vector") throw new (0,
|
|
755
|
-
const v =
|
|
1192
|
+
if (d.kind !== "motion" && d.kind !== "vector") throw new (0, _chunk2K5TELHVcjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect, not a vector one.`, id);
|
|
1193
|
+
const v = _chunk2K5TELHVcjs.resolveEffectValues.call(void 0, d, values);
|
|
756
1194
|
if (d.kind === "vector") {
|
|
757
1195
|
return { svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100"><circle id="badge" cx="50" cy="50" r="40" fill="${v.color}"/></svg>`, animate: [{ id: "badge", ms: v.ms, attrs: { opacity: [0, 1] } }], duration: v.ms, loop: false };
|
|
758
1196
|
}
|
|
@@ -772,11 +1210,12 @@ function createFakeEffectProvider(options = {}) {
|
|
|
772
1210
|
sampleCameraMove: (id, request) => {
|
|
773
1211
|
const d = get(id);
|
|
774
1212
|
const { from, to, ms, stage, fps, values } = request;
|
|
775
|
-
return
|
|
1213
|
+
return _chunk2K5TELHVcjs.sampleCameraViews.call(void 0, (u) => camera(id, { from, to, u, ms, stage }, values), { ms, fps, cut: _optionalChain([d, 'access', _48 => _48.camera, 'optionalAccess', _49 => _49.cut]) });
|
|
776
1214
|
}
|
|
777
1215
|
} : {},
|
|
1216
|
+
...options.templates ? fakeTemplateMethods() : {},
|
|
778
1217
|
...supportsAuthoring ? {
|
|
779
|
-
openAuthoring: (from) =>
|
|
1218
|
+
openAuthoring: (from) => _chunkRG4O6K2Acjs.createEffectAuthoringSession.call(void 0, from, { provider })
|
|
780
1219
|
} : {}
|
|
781
1220
|
};
|
|
782
1221
|
return provider;
|
|
@@ -812,7 +1251,7 @@ function jsonTypeOf(value) {
|
|
|
812
1251
|
function effectControlField(name, schema, fallback, options = {}) {
|
|
813
1252
|
const base = { id: name, ...schema.title ? { label: schema.title } : {}, ...schema.description ? { description: schema.description } : {} };
|
|
814
1253
|
const def = _nullishCoalesce(schema.default, () => ( fallback));
|
|
815
|
-
const type = _nullishCoalesce(typeOf(schema), () => ( typeOf(_nullishCoalesce(_optionalChain([schema, 'access',
|
|
1254
|
+
const type = _nullishCoalesce(typeOf(schema), () => ( typeOf(_nullishCoalesce(_optionalChain([schema, 'access', _50 => _50.anyOf, 'optionalAccess', _51 => _51.find, 'call', _52 => _52((s) => typeOf(s) === jsonTypeOf(def))]), () => ( {})))));
|
|
816
1255
|
if (Array.isArray(schema.enum) && schema.enum.length) {
|
|
817
1256
|
const options2 = schema.enum.filter((v) => typeof v === "string" || typeof v === "number");
|
|
818
1257
|
return { ...base, type: "choice", options: options2, default: typeof def === "string" || typeof def === "number" ? def : options2[0], control: options2.length <= 4 ? "segmented" : "select" };
|
|
@@ -826,7 +1265,7 @@ function effectControlField(name, schema, fallback, options = {}) {
|
|
|
826
1265
|
if (isEffectFontControl(schema)) {
|
|
827
1266
|
const fonts = _nullishCoalesce(options.fonts, () => ( _chunk4XSBOGMKcjs.SYSTEM_FONT_CATALOG));
|
|
828
1267
|
const opts = fonts.map((f) => ({ value: f.family, label: f.family, description: f.category }));
|
|
829
|
-
const current = typeof def === "string" && def ? def : _nullishCoalesce(_optionalChain([opts, 'access',
|
|
1268
|
+
const current = typeof def === "string" && def ? def : _nullishCoalesce(_optionalChain([opts, 'access', _53 => _53[0], 'optionalAccess', _54 => _54.value]), () => ( "sans-serif"));
|
|
830
1269
|
if (!opts.some((o) => o.value.toLowerCase() === current.toLowerCase())) opts.unshift({ value: current, label: current, description: "current" });
|
|
831
1270
|
return { ...base, type: "choice", options: opts, default: opts.find((o) => o.value.toLowerCase() === current.toLowerCase()).value, control: "select" };
|
|
832
1271
|
}
|
|
@@ -835,7 +1274,7 @@ function effectControlField(name, schema, fallback, options = {}) {
|
|
|
835
1274
|
return { ...base, type: "text", default: typeof def === "string" ? def : "", ...schema.maxLength ? { maxLength: schema.maxLength } : {} };
|
|
836
1275
|
}
|
|
837
1276
|
if (type === "array" && Array.isArray(def) && def.length >= 2 && def.length <= 4 && def.every((n) => typeof n === "number")) {
|
|
838
|
-
const items = _nullishCoalesce(_nullishCoalesce(schema.items, () => ( _optionalChain([schema, 'access',
|
|
1277
|
+
const items = _nullishCoalesce(_nullishCoalesce(schema.items, () => ( _optionalChain([schema, 'access', _55 => _55.anyOf, 'optionalAccess', _56 => _56.find, 'call', _57 => _57((s) => typeOf(s) === "array"), 'optionalAccess', _58 => _58.items]))), () => ( {}));
|
|
839
1278
|
return { ...base, type: "vector", size: def.length, default: [...def], ...items.minimum !== void 0 ? { min: items.minimum } : {}, ...items.maximum !== void 0 ? { max: items.maximum } : {} };
|
|
840
1279
|
}
|
|
841
1280
|
return null;
|
|
@@ -857,7 +1296,7 @@ var effectFieldValue = (field, value) => {
|
|
|
857
1296
|
return value === void 0 || value === null || typeof value === "object" && !Array.isArray(value) ? field.default : value;
|
|
858
1297
|
};
|
|
859
1298
|
function effectSamplePicture(width, height, variant = 0) {
|
|
860
|
-
const p =
|
|
1299
|
+
const p = _chunk2K5TELHVcjs.createEffectPixels.call(void 0, width, height);
|
|
861
1300
|
for (let y = 0, i = 0; y < height; y++) {
|
|
862
1301
|
for (let x = 0; x < width; x++, i += 4) {
|
|
863
1302
|
const u = x / Math.max(1, width - 1);
|
|
@@ -948,11 +1387,11 @@ var EASING_SCHEMA = {
|
|
|
948
1387
|
};
|
|
949
1388
|
var NO_SESSION = "No effect authoring session is currently open. Open an effect using EffectProvider.openAuthoring() or in an authoring editor before calling effect authoring tools.";
|
|
950
1389
|
function createEffectAuthoringToolProvider(host, options) {
|
|
951
|
-
const id = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
952
|
-
const namespace = _optionalChain([options, 'optionalAccess',
|
|
953
|
-
const title = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
954
|
-
const description = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
955
|
-
const skill = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
1390
|
+
const id = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _59 => _59.id]), () => ( "effect-authoring"));
|
|
1391
|
+
const namespace = _optionalChain([options, 'optionalAccess', _60 => _60.namespace]);
|
|
1392
|
+
const title = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _61 => _61.title]), () => ( "Effect authoring"));
|
|
1393
|
+
const description = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _62 => _62.description]), () => ( "Author shaders and procedural effects, inspect parameters, adjust values, and manage keyframe animations."));
|
|
1394
|
+
const skill = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _63 => _63.skill]), () => ( "pixerate-effect-authoring"));
|
|
956
1395
|
const requireSession = () => {
|
|
957
1396
|
const s = host.session();
|
|
958
1397
|
if (!s) throw new Error(NO_SESSION);
|
|
@@ -973,7 +1412,7 @@ function createEffectAuthoringToolProvider(host, options) {
|
|
|
973
1412
|
sourceLanguage: state.sourceLanguage,
|
|
974
1413
|
controls: effectParameterFields(state.description),
|
|
975
1414
|
values: state.values,
|
|
976
|
-
presets: _nullishCoalesce(_optionalChain([state, 'access',
|
|
1415
|
+
presets: _nullishCoalesce(_optionalChain([state, 'access', _64 => _64.description, 'access', _65 => _65.presets, 'optionalAccess', _66 => _66.map, 'call', _67 => _67((p) => p.name)]), () => ( [])),
|
|
977
1416
|
tracks: Object.entries(state.tracks).map(([control, track]) => ({
|
|
978
1417
|
control,
|
|
979
1418
|
keyframes: track.length
|
|
@@ -1280,7 +1719,7 @@ function createEffectAuthoringToolProvider(host, options) {
|
|
|
1280
1719
|
const tools = [
|
|
1281
1720
|
describeTool,
|
|
1282
1721
|
getSourceTool,
|
|
1283
|
-
..._optionalChain([session, 'optionalAccess',
|
|
1722
|
+
..._optionalChain([session, 'optionalAccess', _68 => _68.setSource]) ? [setSourceTool] : [],
|
|
1284
1723
|
setValuesTool,
|
|
1285
1724
|
resetValuesTool,
|
|
1286
1725
|
applyPresetTool,
|
|
@@ -1352,4 +1791,28 @@ function createEffectAuthoringToolProvider(host, options) {
|
|
|
1352
1791
|
|
|
1353
1792
|
|
|
1354
1793
|
|
|
1355
|
-
|
|
1794
|
+
|
|
1795
|
+
|
|
1796
|
+
|
|
1797
|
+
|
|
1798
|
+
|
|
1799
|
+
|
|
1800
|
+
|
|
1801
|
+
|
|
1802
|
+
|
|
1803
|
+
|
|
1804
|
+
|
|
1805
|
+
|
|
1806
|
+
|
|
1807
|
+
|
|
1808
|
+
|
|
1809
|
+
|
|
1810
|
+
|
|
1811
|
+
|
|
1812
|
+
|
|
1813
|
+
|
|
1814
|
+
|
|
1815
|
+
|
|
1816
|
+
|
|
1817
|
+
|
|
1818
|
+
exports.CAMERA_MOVE_MAX_MS = _chunk2K5TELHVcjs.CAMERA_MOVE_MAX_MS; exports.CAMERA_MOVE_ROLES = _chunk2K5TELHVcjs.CAMERA_MOVE_ROLES; exports.EFFECT_ERROR_CODES = _chunk2K5TELHVcjs.EFFECT_ERROR_CODES; exports.EFFECT_KINDS = _chunk2K5TELHVcjs.EFFECT_KINDS; exports.EFFECT_LAYER_ROLES = _chunk2K5TELHVcjs.EFFECT_LAYER_ROLES; exports.EFFECT_LAYER_USES = EFFECT_LAYER_USES; exports.EFFECT_SEQUENCE_NAME = EFFECT_SEQUENCE_NAME; exports.EFFECT_SUBJECT_KINDS = _chunk2K5TELHVcjs.EFFECT_SUBJECT_KINDS; exports.EFFECT_TEMPLATE_SLOT_TYPES = _chunk2K5TELHVcjs.EFFECT_TEMPLATE_SLOT_TYPES; exports.EFFECT_TRANSITION_MS = _chunk2K5TELHVcjs.EFFECT_TRANSITION_MS; exports.EFFECT_USES = _chunk2K5TELHVcjs.EFFECT_USES; exports.EFFECT_USE_LABELS = EFFECT_USE_LABELS; exports.EffectControlError = _chunk2K5TELHVcjs.EffectControlError; exports.EffectDisposedError = _chunk2K5TELHVcjs.EffectDisposedError; exports.EffectError = _chunk2K5TELHVcjs.EffectError; exports.EffectRendererPool = _chunkPY4GWSE2cjs.EffectRendererPool; exports.EffectUnsupportedError = _chunk2K5TELHVcjs.EffectUnsupportedError; exports.EffectsSlot = _chunk2K5TELHVcjs.EffectsSlot; exports.NoEffectsProviderError = _chunk2K5TELHVcjs.NoEffectsProviderError; exports.UnknownEffectError = _chunk2K5TELHVcjs.UnknownEffectError; exports.UnknownTemplateError = _chunk2K5TELHVcjs.UnknownTemplateError; exports.applyEffectMask = _chunk2K5TELHVcjs.applyEffectMask; exports.cameraBoxOfView = _chunk2K5TELHVcjs.cameraBoxOfView; exports.cameraMoveField = _chunk2K5TELHVcjs.cameraMoveField; exports.cameraMoveIdList = _chunk2K5TELHVcjs.cameraMoveIdList; exports.cameraMoveParts = _chunk2K5TELHVcjs.cameraMoveParts; exports.cameraMovesFor = _chunk2K5TELHVcjs.cameraMovesFor; exports.cameraViewOfBox = _chunk2K5TELHVcjs.cameraViewOfBox; exports.checkEffectProvider = checkEffectProvider; exports.checkEffectSequence = checkEffectSequence; exports.checkTemplateValues = checkTemplateValues; exports.countEffectTags = _chunk2K5TELHVcjs.countEffectTags; exports.createEffectAuthoringSession = _chunkRG4O6K2Acjs.createEffectAuthoringSession; exports.createEffectAuthoringToolProvider = createEffectAuthoringToolProvider; exports.createEffectPixels = _chunk2K5TELHVcjs.createEffectPixels; exports.createEffectToolProvider = _chunk2K5TELHVcjs.createEffectToolProvider; exports.createFakeEffectProvider = createFakeEffectProvider; exports.effectControlField = effectControlField; exports.effectFieldValue = effectFieldValue; exports.effectFontFamilies = effectFontFamilies; exports.effectLayerInput = effectLayerInput; exports.effectLayerOffered = effectLayerOffered; exports.effectLayerRole = effectLayerRole; exports.effectOffered = _chunk2K5TELHVcjs.effectOffered; exports.effectParameterFields = effectParameterFields; exports.effectSampleInputs = effectSampleInputs; exports.effectSamplePicture = effectSamplePicture; exports.effectSequenceEffects = effectSequenceEffects; exports.effectSequenceSlots = effectSequenceSlots; exports.effectSubjectKind = effectSubjectKind; exports.effectSubjectProblem = effectSubjectProblem; exports.effectValueErrors = _chunk2K5TELHVcjs.effectValueErrors; exports.encodeEffectFloat = _chunk2K5TELHVcjs.encodeEffectFloat; exports.groupEffectsByCategory = groupEffectsByCategory; exports.hasEffectTags = _chunk2K5TELHVcjs.hasEffectTags; exports.isCameraView = _chunk2K5TELHVcjs.isCameraView; exports.isEffectError = _chunk2K5TELHVcjs.isEffectError; exports.isEffectFontControl = isEffectFontControl; exports.isEffectPixels = _chunk2K5TELHVcjs.isEffectPixels; exports.isSubjectTemplateSlot = isSubjectTemplateSlot; exports.linearToSrgb = _chunk2K5TELHVcjs.linearToSrgb; exports.normaliseEffectTag = _chunk2K5TELHVcjs.normaliseEffectTag; exports.renderEffectThumbnail = renderEffectThumbnail; exports.resolveCameraMoveSpec = _chunk2K5TELHVcjs.resolveCameraMoveSpec; exports.resolveEffectValues = _chunk2K5TELHVcjs.resolveEffectValues; exports.sampleCameraViews = _chunk2K5TELHVcjs.sampleCameraViews; exports.sampleEffectCameraMove = _chunk2K5TELHVcjs.sampleEffectCameraMove; exports.searchEffectSummaries = _chunk2K5TELHVcjs.searchEffectSummaries; exports.searchTemplateSummaries = searchTemplateSummaries; exports.srgbToLinear = _chunk2K5TELHVcjs.srgbToLinear; exports.templateDefaultValues = templateDefaultValues; exports.templateSlotSchema = templateSlotSchema; exports.templateSlotSummary = templateSlotSummary; exports.templateSlotTakes = templateSlotTakes; exports.templateValueProblem = templateValueProblem; exports.templateValuesSchema = templateValuesSchema;
|