Skip to content

Add peniko (2d graphics) animation support#103

Draft
nixonyh wants to merge 13 commits intonixon/lazy-registrationfrom
nixon/kurbo-support
Draft

Add peniko (2d graphics) animation support#103
nixonyh wants to merge 13 commits intonixon/lazy-registrationfrom
nixon/kurbo-support

Conversation

@nixonyh
Copy link
Copy Markdown
Member

@nixonyh nixonyh commented May 3, 2026

Stack on top of #100

  • Added peniko_motiongfx crate that covers common interpolation & tracing implementations
  • Move Interpolation<M> trait into motiongfx and add a marker type to workaround the orphan rule.
  • Add Tracer<T> type in peniko_motiongfx to handle tracing operations.
  • Add examples to showcase animations using peniko, rendered via vello.

@nixonyh nixonyh requested a review from Jaghov May 3, 2026 14:20
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2798c928-ef5b-4ba7-b4ea-00fc03fa47f1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title claims to add 'peniko' animation support, but the actual changes implement 'kurbo' animation support (a new kurbo_motiongfx crate with kurbo geometry interpolation and tracing). Update the PR title to accurately reflect the changes: 'Add kurbo (2d geometry) animation support' or similar, as confirmed by the PR objectives and crate implementation details.
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description clearly describes the main objectives: adding kurbo animation support via a new crate, moving the Interpolation trait, and updating the API.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch nixon/kurbo-support

Comment @coderabbitai help to get the list of available commands and usage tips.

@nixonyh nixonyh changed the base branch from main to nixon/lazy-registration May 3, 2026 14:20
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/motiongfx/src/timeline.rs (1)

438-472: ⚠️ Potential issue | 🔴 Critical

Add the missing 'static bound to both act and act_step methods.

Both methods call ActionBuilder::with_interp, which requires T: 'static (defined at crates/motiongfx/src/action.rs:380). The current signatures omit this bound and will fail to compile.

🔧 Suggested fix
 pub fn act<I, S, T, M>(
     &mut self,
     target: I,
     field_acc: FieldAccessor<S, T>,
     action: impl Action<T>,
 ) -> InterpActionBuilder<'_, T>
 where
     W: SubjectSource<M, I, S> + 'static,
     I: SubjectId,
     S: 'static,
-    T: Interpolation<M> + Clone + ThreadSafe,
+    T: Interpolation<M> + Clone + ThreadSafe + 'static,
@@
     action: impl Action<T>,
 ) -> InterpActionBuilder<'_, T>
 where
     W: SubjectSource<M, I, S> + 'static,
     I: SubjectId,
     S: 'static,
-    T: Clone + ThreadSafe,
+    T: Clone + ThreadSafe + 'static,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/motiongfx/src/timeline.rs` around lines 438 - 472, The act and
act_step methods call ActionBuilder::with_interp which requires the interpolated
type T to be 'static, so add the missing T: 'static bound to both function
where-clauses (the act(...) and act_step(...) methods) so their generics include
T: 'static alongside the existing bounds; ensure the signatures for act and
act_step mirror the required trait bounds used by ActionBuilder::with_interp.
🧹 Nitpick comments (1)
crates/motiongfx/src/interpolation.rs (1)

1-8: ⚡ Quick win

Clarify the t contract in docs.

At Line 7, please document whether t is expected in [0.0, 1.0] or whether extrapolation is intentionally supported. That will prevent divergent downstream implementations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/motiongfx/src/interpolation.rs` around lines 1 - 8, Document the
contract for the interpolation parameter `t` on the Interpolation trait: update
the doc comment for trait Interpolation and the interp method
(Interpolation::interp) to state explicitly whether `t` is clamped to [0.0, 1.0]
or if extrapolation outside that range is allowed, and if clamped describe who
is responsible for clamping (caller or implementor); include expected behavior
for edge cases (e.g., t == 0.0 returns a, t == 1.0 returns b) so downstream
implementors have a single authoritative spec to follow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/kurbo_motiongfx/src/trace.rs`:
- Around line 24-26: The public function trace_bez_path currently treats
multi-subpath BezPath as a single stroke; fix by either preserving subpaths or
enforcing single-subpath input: implement detection of MoveTo elements and split
the input BezPath into subpaths, call the existing single-subpath tracing logic
for each subpath, and append results to a new output BezPath preserving MoveTo
boundaries (ensuring you handle closing/First/ClosePath logic), or change
trace_bez_path to return a Result/Option or panic when more than one subpath is
detected and document the behavior; locate and update trace_bez_path and any
helpers that operate on path elements (see comments around lines 44–55) to
perform the split-or-validate step and then aggregate per-subpath traces into
the final BezPath (or return an error) accordingly.
- Around line 7-17: The trace_cubic_bez and trace_quad_bez helpers currently
take an unbounded t and forward it to curve.subsegment, causing inconsistent
behavior with trace_bez_path which clamps t; update both trace_cubic_bez and
trace_quad_bez to clamp t into the [0.0, 1.0] range (e.g. min(max(t, 0.0), 1.0))
before converting to f64 and calling curve.subsegment so their prefix semantics
match trace_bez_path.

---

Outside diff comments:
In `@crates/motiongfx/src/timeline.rs`:
- Around line 438-472: The act and act_step methods call
ActionBuilder::with_interp which requires the interpolated type T to be 'static,
so add the missing T: 'static bound to both function where-clauses (the act(...)
and act_step(...) methods) so their generics include T: 'static alongside the
existing bounds; ensure the signatures for act and act_step mirror the required
trait bounds used by ActionBuilder::with_interp.

---

Nitpick comments:
In `@crates/motiongfx/src/interpolation.rs`:
- Around line 1-8: Document the contract for the interpolation parameter `t` on
the Interpolation trait: update the doc comment for trait Interpolation and the
interp method (Interpolation::interp) to state explicitly whether `t` is clamped
to [0.0, 1.0] or if extrapolation outside that range is allowed, and if clamped
describe who is responsible for clamping (caller or implementor); include
expected behavior for edge cases (e.g., t == 0.0 returns a, t == 1.0 returns b)
so downstream implementors have a single authoritative spec to follow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2bd8cfa6-0cff-45be-9f85-eca05403b7c1

📥 Commits

Reviewing files that changed from the base of the PR and between f95e9a0 and 8d37bd8.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (21)
  • Cargo.toml
  • crates/bevy_motiongfx/Cargo.toml
  • crates/bevy_motiongfx/src/interpolation.rs
  • crates/bevy_motiongfx/src/lib.rs
  • crates/kurbo_motiongfx/Cargo.toml
  • crates/kurbo_motiongfx/src/interpolation.rs
  • crates/kurbo_motiongfx/src/lib.rs
  • crates/kurbo_motiongfx/src/trace.rs
  • crates/motiongfx/Cargo.toml
  • crates/motiongfx/docs/world.rs
  • crates/motiongfx/examples/custom_world.rs
  • crates/motiongfx/src/interpolation.rs
  • crates/motiongfx/src/lib.rs
  • crates/motiongfx/src/timeline.rs
  • examples/bevy_examples/examples/custom_ease.rs
  • examples/bevy_examples/examples/custom_interp.rs
  • examples/bevy_examples/examples/easings.rs
  • examples/bevy_examples/examples/hello_world.rs
  • examples/bevy_examples/examples/minimal.rs
  • examples/bevy_examples/examples/recording.rs
  • examples/bevy_examples/examples/slide_basic.rs
💤 Files with no reviewable changes (1)
  • crates/bevy_motiongfx/src/lib.rs

Comment thread crates/peniko_motiongfx/src/trace.rs Outdated
Comment on lines +7 to +17
pub fn trace_cubic_bez(curve: &CubicBez, t: f32) -> CubicBez {
let t = t as f64;
curve.subsegment(0.0..t)
}

/// Returns the prefix of a [`QuadBez`] traced from start to `t`.
#[inline]
pub fn trace_quad_bez(curve: &QuadBez, t: f32) -> QuadBez {
let t = t as f64;
curve.subsegment(0.0..t)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clamp t in curve helpers for API consistency.

At Line 7 and Line 14, these functions accept raw t while trace_bez_path (Line 27/30) clamps by behavior. Align them to avoid inconsistent prefix semantics across tracing APIs.

Suggested patch
 pub fn trace_cubic_bez(curve: &CubicBez, t: f32) -> CubicBez {
-    let t = t as f64;
+    let t = t.clamp(0.0, 1.0) as f64;
     curve.subsegment(0.0..t)
 }
@@
 pub fn trace_quad_bez(curve: &QuadBez, t: f32) -> QuadBez {
-    let t = t as f64;
+    let t = t.clamp(0.0, 1.0) as f64;
     curve.subsegment(0.0..t)
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/kurbo_motiongfx/src/trace.rs` around lines 7 - 17, The trace_cubic_bez
and trace_quad_bez helpers currently take an unbounded t and forward it to
curve.subsegment, causing inconsistent behavior with trace_bez_path which clamps
t; update both trace_cubic_bez and trace_quad_bez to clamp t into the [0.0, 1.0]
range (e.g. min(max(t, 0.0), 1.0)) before converting to f64 and calling
curve.subsegment so their prefix semantics match trace_bez_path.

Comment thread crates/peniko_motiongfx/src/trace.rs Outdated
nixonyh added 10 commits May 5, 2026 00:17
- Rename interpolation module to interp
- Add CubicBez and QuadBez interpolation
- Add trace module with trace_bez_path, trace_cubic_bez, trace_quad_bez
- Remove prelude in favour of direct module imports
Make `act` first class for creating animation and use `act_builder` for custom interpolation method.
@nixonyh nixonyh force-pushed the nixon/kurbo-support branch from 535f251 to 3eacd70 Compare May 4, 2026 16:26
@nixonyh nixonyh changed the title Add kurbo animation support Add peniko (kurbo & color) animation support May 5, 2026
@nixonyh nixonyh changed the title Add peniko (kurbo & color) animation support Add peniko (2d graphics) animation support May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant