@pixerate/editor 0.67.0 → 0.67.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.
@@ -1501,7 +1501,7 @@ function checkMotionScene(scene) {
1501
1501
  if (scene.trigger) {
1502
1502
  if ((_nullishCoalesce(scene.loop, () => ( "none"))) !== "none") issues.push(motionIssue("trigger-loop", `The scene plays on ${scene.trigger}, so its "${scene.loop}" loop does not apply; set loop to "none" or remove the trigger.`, {}));
1503
1503
  if (scene.trigger === "click") {
1504
- if (scene.shots.length === 1) issues.push(motionIssue("click-one-shot", "The scene plays on click but has one shot, so every click replays it from the start; split it into shots (the first plays on load, each click plays the next).", { shot: scene.shots[0].id }));
1504
+ if (scene.shots.length === 1) issues.push(motionIssue("click-one-shot", "The scene plays on click but has one shot, so every click replays it from the start; split it into shots (each click plays the next one).", { shot: scene.shots[0].id }));
1505
1505
  scene.shots.forEach((shot, i) => {
1506
1506
  if (i > 0 && shot.at) issues.push(motionIssue("click-cue", `Shot "${shot.id}" is cued, but on click a shot starts when it is clicked to; remove its "at" or the trigger.`, { shot: shot.id }));
1507
1507
  });
@@ -2065,7 +2065,7 @@ function toFlairSvgMotion(scene, options = {}) {
2065
2065
  animate.sort((x, y) => (_nullishCoalesce(x.delay, () => ( 0))) - (_nullishCoalesce(y.delay, () => ( 0))));
2066
2066
  const lastChange = animate.reduce((m, a) => Math.max(m, (_nullishCoalesce(a.delay, () => ( 0))) + (_nullishCoalesce(a.ms, () => ( 0)))), 0);
2067
2067
  const trigger = options.trigger === null ? void 0 : _nullishCoalesce(options.trigger, () => ( scene.trigger));
2068
- if (trigger === "click" && timeline.shots.length > 1) {
2068
+ if (trigger === "click" && timeline.shots.length) {
2069
2069
  for (const a of animate) {
2070
2070
  const at = _nullishCoalesce(a.delay, () => ( 0));
2071
2071
  let step = 0;
@@ -2075,7 +2075,7 @@ function toFlairSvgMotion(scene, options = {}) {
2075
2075
  const delay = round2(at - timeline.shots[step].start);
2076
2076
  delete a.delay;
2077
2077
  if (delay > 0) a.delay = delay;
2078
- if (step > 0) a.step = step;
2078
+ a.step = step + 1;
2079
2079
  }
2080
2080
  animate.sort((x, y) => (_nullishCoalesce(x.step, () => ( 0))) - (_nullishCoalesce(y.step, () => ( 0))) || (_nullishCoalesce(x.delay, () => ( 0))) - (_nullishCoalesce(y.delay, () => ( 0))));
2081
2081
  }
@@ -2260,7 +2260,8 @@ function fromFlairSvgMotion(input, options = {}) {
2260
2260
  const nodes = indexMotionNodes(artwork.nodes);
2261
2261
  const byStep = /* @__PURE__ */ new Map();
2262
2262
  for (const anim of _nullishCoalesce(motion.animate, () => ( []))) {
2263
- const step = Math.max(0, Math.floor(_nullishCoalesce(anim.step, () => ( 0))));
2263
+ const raw = Math.max(0, Math.floor(_nullishCoalesce(anim.step, () => ( 0))));
2264
+ const step = options.clickSteps ? Math.max(1, raw) : raw;
2264
2265
  if (!byStep.has(step)) byStep.set(step, []);
2265
2266
  byStep.get(step).push(anim);
2266
2267
  }
@@ -2311,7 +2312,7 @@ function presetColor(value) {
2311
2312
  }
2312
2313
  function fromFlairVectorEffect(effect, options = {}) {
2313
2314
  if (!effect || effect.kind !== "vector" || !effect.motion) throw new Error('Give a Flair vector effect: { kind: "vector", id, name, motion: { svg, animate } }.');
2314
- const result = fromFlairSvgMotion(effect.motion, { name: _nullishCoalesce(_nullishCoalesce(options.name, () => ( effect.id)), () => ( effect.name)), hold: _nullishCoalesce(options.hold, () => ( effect.hold)) });
2315
+ const result = fromFlairSvgMotion(effect.motion, { name: _nullishCoalesce(_nullishCoalesce(options.name, () => ( effect.id)), () => ( effect.name)), hold: _nullishCoalesce(options.hold, () => ( effect.hold)), ...effect.trigger === "click" ? { clickSteps: true } : {} });
2315
2316
  const names = new Set((_nullishCoalesce(result.scene.controls, () => ( []))).map((c) => c.name));
2316
2317
  const presets = (_nullishCoalesce(effect.presets, () => ( []))).map((p) => ({ name: p.name, values: Object.fromEntries(Object.entries(p.values).flatMap(([k, v]) => names.has(k) && presetColor(v) ? [[k, presetColor(v)]] : [])) })).filter((p) => Object.keys(p.values).length);
2317
2318
  const scene = { ...result.scene, ...effect.description ? { description: effect.description } : {}, ...presets.length ? { presets } : {}, ...effect.trigger ? { trigger: effect.trigger } : {} };
@@ -3025,7 +3026,7 @@ var SETTINGS = {
3025
3026
  loop: { type: "string", enum: ["none", "loop", "ping-pong"], description: "Playback past the end (default none)." },
3026
3027
  trigger: {
3027
3028
  anyOf: [{ type: "string", enum: ["click", "hover", "press", "scroll"] }, { type: "null" }],
3028
- description: "Play in answer to the viewer when exported to Flair: click (the first shot plays on load, each click plays the next shot), hover or press (plays while the pointer is over or down, rewinds when it leaves), scroll (scrubs as it scrolls past). null plays on its own (default). The editor previews it played through."
3029
+ description: "Play in answer to the viewer when exported to Flair: click (nothing plays until a click; each click plays the next shot, then the first again), hover or press (plays while the pointer is over or down, rewinds when it leaves), scroll (scrubs as it scrolls past). null plays on its own (default). The editor previews it played through."
3029
3030
  },
3030
3031
  fps: { type: "number", minimum: 1, maximum: 120, description: "Sampling rate for exports (default 30)." },
3031
3032
  steps: { anyOf: [{ type: "number", exclusiveMinimum: 0, maximum: 120 }, { type: "null" }], description: 'Stepped time for every command without its own: changes hold on a grid of this many frames per second (12 = "on twos" at 24 fps) for a hand-drawn look; null makes it smooth again (default).' },
@@ -3621,7 +3622,7 @@ Working method
3621
3622
  1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).
3622
3623
  2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).
3623
3624
  3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + "end") to look at the result; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.
3624
- - For something the viewer plays (a button, a toggle, a step-by-step explainer), set "trigger" with set_animation_settings: click plays the next shot on each click (make the last shot lead back to how the first ended for a toggle), hover or press plays and rewinds, scroll scrubs.
3625
+ - For something the viewer plays (a button, a toggle, a step-by-step explainer), set "trigger" with set_animation_settings: click plays the next shot on each click and then starts over (make the last shot put things back for a toggle), hover or press plays and rewinds, scroll scrubs.
3625
3626
  4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.
3626
3627
 
3627
3628
  Keep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.`;