Skip to content

Add lazy registration support!#100

Open
nixonyh wants to merge 27 commits intomainfrom
nixon/lazy-registration
Open

Add lazy registration support!#100
nixonyh wants to merge 27 commits intomainfrom
nixon/lazy-registration

Conversation

@nixonyh
Copy link
Copy Markdown
Member

@nixonyh nixonyh commented Apr 30, 2026

MotionGfx used to require you to register all fields and pipelines before creating any animations.

Closes #98 (This PR aims to address it too!)

Now it's GONE!

This PR introduces fully autonomous Pipeline/FieldAccessor registration (or shud I say lazy registration) by lazily registering them during each TimelineBuilder::act(..) calls.

This is achieved through a few changes:

  1. PipelineRegistry is now W world agnostic.
  2. A new Registry type is added to unify both AccessorRegistry & PipelineRegistry.
  3. PipelineRegistry::register() now does not take in any value, instead the entire creation of the PipelineKey & Pipeline is automated via the SubjectSource trait.
  4. SubjectSource trait allows the Pipeline to create the BakerFn & SampleFn parameter-less.
  5. TimelineBuilder now takes in a compulsory mutable reference of a &mut Registry for lazy registration. It is crucial that the same Registry is later used to bake & sample the compiled Timeline. (It is advised to just keep a global Registry at all times to prevent bugs / confusion)
  6. Each call to TimelineBuilder::act(..) will attempt to register the given path. If it is already registered before, we simply skip registering it.
  7. Timeline<W> & TimelineBuilder<W> is now W bound. This ensure better correctness and prevent Timeline to be multi-world, making it hard to determine which world to bake / sample from.

@nixonyh nixonyh requested a review from Jaghov April 30, 2026 09:42
@nixonyh nixonyh added documentation Improvements or additions to documentation enhancement New feature or request labels May 1, 2026
@nixonyh nixonyh marked this pull request as ready for review May 1, 2026 08:22
Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@nixonyh
Copy link
Copy Markdown
Member Author

nixonyh commented May 1, 2026

@CodeRabbit full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Manager-based timeline resource (create/add timelines, lifecycle/events).
    • Added path! macro for field/path targeting.
    • New SubjectSource trait for integrating custom worlds as animation data sources.
  • Refactor

    • Builder/registry-driven pipeline model; builders created via manager/registry.
    • Timelines and pipelines now operate per-concrete world for safer, type-driven dispatch.
  • Documentation

    • READMEs and examples updated to the manager/registry workflow and path! usage.

Walkthrough

Unifies runtime around a type‑erased Registry and world‑generic timelines (Timeline). Introduces SubjectSource for world read/write, replaces closure pipelines with function‑pointer pipelines, moves Bevy integration from MotionGfxWorld to MotionGfxManager, updates builders to use FieldAccessor/path! and updates docs/examples. Workspace dependency bumped.

Changes

Registry & Bevy manager rework

Layer / File(s) Summary
Data shape / New traits
crates/motiongfx/src/registry.rs, crates/motiongfx/src/world.rs
Adds Registry { accessor, pipeline } and SubjectSource<I,S> trait for world read/write.
Pipeline key & func-pointer layer
crates/motiongfx/src/pipeline/func_pointers.rs, crates/motiongfx/src/pipeline.rs
Introduces BakeFnPtr/SampleFnPtr, Pipeline<W,I,S,T> with typed fn pointers, PipelineUntyped, and PipelineKey with world_id.
Timeline generics & builder
crates/motiongfx/src/timeline.rs, crates/bevy_motiongfx/src/interpolation.rs
Makes Timeline<W> and TimelineBuilder<'a, W> with registry: &mut Registry; builder APIs now accept FieldAccessor<S,T> and require W: SubjectSource<I,S>.
Registry wiring / bake & sample flow
crates/motiongfx/src/registry.rs, crates/motiongfx/src/pipeline.rs, crates/motiongfx/src/timeline.rs
Registry::register inserts accessor and pipeline; Timeline::bake_actions/sample_queued_actions call into registry.pipeline.bake/sample with BakeCtx/SampleCtx that carry concrete world and accessor_registry.
Bevy integration: manager & world wrapper
crates/bevy_motiongfx/src/manager.rs, crates/bevy_motiongfx/src/world.rs, crates/bevy_motiongfx/src/lib.rs
Adds MotionGfxManager resource and MotionGfxManagerPlugin (pending→active loading, sampling, completion), and BevyWorld(pub World) implementing SubjectSource for components and assets.
Public surface / preludes / macros
crates/motiongfx/src/lib.rs, crates/bevy_motiongfx/src/lib.rs
Adds registry module and path! macro; prelude now exports Registry, AccessorRegistry, PipelineRegistry, PipelineKey, SubjectSource, and FieldAccessor; removes old MotionGfxWorld-related prelude items.
Action ID consts & small API tweaks
crates/motiongfx/src/action.rs, crates/motiongfx/src/track.rs
Makes UntypedSubjectId constructors/accessors const fn, adds PLACEHOLDER const; test usages updated.
Examples & docs
crates/motiongfx/README.md, crates/bevy_motiongfx/README.md, examples/..., crates/motiongfx/examples/*, crates/bevy_motiongfx/examples/*
Docs rewritten to Quick Start using Registry and path!; Bevy examples switched to ResMut<MotionGfxManager>, motiongfx.create_builder(), path!, and motiongfx.add_timeline(timeline).
Removals / deletions
crates/bevy_motiongfx/src/pipeline.rs, crates/bevy_motiongfx/src/registry.rs (deleted)
Removes prior Bevy World pipeline wiring, register_fields! helper, and MotionGfxWorld surface.
Workspace manifest
Cargo.toml
Bumps workspace dependency field_path from 0.30.4.1.

Sequence Diagram(s)

sequenceDiagram
  participant Builder as TimelineBuilder<'_, W>
  participant Registry as Registry
  participant PipelineReg as PipelineRegistry (untyped)
  participant Pipeline as PipelineUntyped
  participant BakeFn as BakeFnPtr
  participant World as SubjectSource (W)

  Builder->>Registry: register::<W,I,S,T>(FieldAccessor)
  Registry->>PipelineReg: ensure PipelineKey::<W,I,S,T>
  Builder->>PipelineReg: request pipeline by key
  PipelineReg-->>Pipeline: return PipelineUntyped
  Pipeline->>BakeFn: invoke .bake::<W>(BakeCtx{ world, accessor_registry, ... })
  BakeFn->>World: get_source(id) / apply_source(id, f)
  World-->>BakeFn: source read / target written
  BakeFn-->>Pipeline: bake/sample complete
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇
I hopped through registries, swapped field! for path!,
A manager tends timelines, pending then dispatched,
Untyped pointers scurry where typed ones once sat,
World answers get and apply — pipelines now untyped and fast,
I nibble a carrot — the refactor finished at last!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 49.52% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add lazy registration support!' directly summarizes the main change—introducing autonomous field and pipeline registration during TimelineBuilder::act() calls instead of requiring pre-registration.
Description check ✅ Passed The description clearly explains the lazy registration feature, the architectural changes (new Registry type, SubjectSource integration), and how TimelineBuilder now requires a Registry reference for autonomous registration.
Linked Issues check ✅ Passed The PR addresses issue #98 by updating README files (crates/motiongfx/README.md and crates/bevy_motiongfx/README.md) to present concepts in a beginner-friendly order with Quick Start guides and updated examples reflecting the new lazy registration API.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing lazy registration, updating Registry/Pipeline architecture, and refactoring examples/documentation to use the new API. No unrelated functionality or scope creep is evident.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch nixon/lazy-registration

Review rate limit: 9/10 reviews remaining, refill in 6 minutes.

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

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)

508-534: ⚠️ Potential issue | 🟠 Major

try_compile() evaluates compile() eagerly even when tracks are empty, allowing release builds to construct an invalid Timeline.

then_some(self.compile()) eagerly evaluates self.compile() before then_some() executes. When self.tracks.is_empty() is true:

  • Debug builds: hits debug_assert! as expected
  • Release builds: debug_assert! is a no-op; compile() constructs and returns a Timeline<W> with empty tracks (later discarded), violating the documented invariant that other methods like curr_track() and set_target_time() depend on

The documented panic contract is not enforced in release builds.

Suggested fix
     pub fn compile(self) -> Timeline<W> {
-        // TODO(nixon): What happens when track is empty?
-        debug_assert!(
+        assert!(
             !self.tracks.is_empty(),
             "Track cannot be empty!"
         );

         Timeline {
             action_world: self.action_world,
@@
     /// Similar to [`Self::compile()`] but return `None` instead of
     /// panicking.
     pub fn try_compile(self) -> Option<Timeline<W>> {
-        (!self.tracks.is_empty()).then_some(self.compile())
+        if self.tracks.is_empty() {
+            None
+        } else {
+            Some(self.compile())
+        }
     }
🤖 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 508 - 534, try_compile
currently calls compile() eagerly via then_some(self.compile()), which
constructs an invalid Timeline in release builds because debug_assert! is a
no-op; replace the eager call with a lazy one so compile() is only invoked when
tracks is non-empty—i.e. change the return expression in try_compile from
(!self.tracks.is_empty()).then_some(self.compile()) to a lazy variant such as
(!self.tracks.is_empty()).then(|| self.compile()) or an explicit if
self.tracks.is_empty() { None } else { Some(self.compile()) }, referencing
try_compile, compile, self.tracks and debug_assert! to locate the code to
change.
🤖 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/motiongfx/src/action.rs`:
- Around line 124-127: The crate currently uses const TypeId::of::<I>() inside
const fn new<I: SubjectId> in action.rs which requires Rust 1.91.0; update this
crate's Cargo.toml to declare the minimum supported Rust version by adding
rust-version = "1.91.0" (or the workspace Cargo.toml if you manage MSRV at
workspace level) so consumers using older compilers won't fail to build; ensure
the change is added to the same crate that defines Action::new (the const fn
using TypeId::of::<I>()).

In `@crates/motiongfx/src/pipeline.rs`:
- Around line 153-163: PipelineUntyped::bake and ::sample unsafely cast erased
function pointers based solely on the caller-provided generic W (unsafe contract
unenforced); fix by enforcing a runtime type check or changing API safety:
either store the original TypeId when creating PipelineUntyped and validate it
against TypeId::of::<W>() before doing the unsafe typed_unchecked call, or mark
bake/sample as unsafe and document the caller responsibility, or restrict
visibility so callers obtain a typed Pipeline<W> (e.g., make
PipelineRegistry::get private or return Pipeline<W>), and update
PipelineRegistry::get, PipelineUntyped, and the creation code to include the
chosen approach.

---

Outside diff comments:
In `@crates/motiongfx/src/timeline.rs`:
- Around line 508-534: try_compile currently calls compile() eagerly via
then_some(self.compile()), which constructs an invalid Timeline in release
builds because debug_assert! is a no-op; replace the eager call with a lazy one
so compile() is only invoked when tracks is non-empty—i.e. change the return
expression in try_compile from
(!self.tracks.is_empty()).then_some(self.compile()) to a lazy variant such as
(!self.tracks.is_empty()).then(|| self.compile()) or an explicit if
self.tracks.is_empty() { None } else { Some(self.compile()) }, referencing
try_compile, compile, self.tracks and debug_assert! to locate the code to
change.
🪄 Autofix (Beta)

❌ Autofix failed (check again to retry)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8f6710ce-a886-4cae-ab3d-ad2793ac1b69

📥 Commits

Reviewing files that changed from the base of the PR and between 89213f1 and aaad04e.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (23)
  • Cargo.toml
  • crates/bevy_motiongfx/README.md
  • crates/bevy_motiongfx/src/interpolation.rs
  • crates/bevy_motiongfx/src/lib.rs
  • crates/bevy_motiongfx/src/pipeline.rs
  • crates/bevy_motiongfx/src/registry.rs
  • crates/bevy_motiongfx/src/world.rs
  • crates/motiongfx/README.md
  • crates/motiongfx/examples/custom_world.rs
  • crates/motiongfx/src/action.rs
  • crates/motiongfx/src/lib.rs
  • crates/motiongfx/src/pipeline.rs
  • crates/motiongfx/src/pipeline/func_pointers.rs
  • crates/motiongfx/src/registry.rs
  • crates/motiongfx/src/timeline.rs
  • crates/motiongfx/src/track.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/registry.rs

Comment thread crates/motiongfx/src/action.rs
Comment thread crates/motiongfx/src/pipeline.rs
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

⚠️ Branch updated during autofix.

The branch was updated while autofix was in progress. Please try again.

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: 1

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)

509-513: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

compile() does not uphold its own panic contract in release builds.

Line 510 uses debug_assert!, so compile() accepts empty tracks in release despite docs saying it panics. That creates an invalid Timeline state and shifts failure to later indexing paths.

Suggested fix
-        // TODO(nixon): What happens when track is empty?
-        debug_assert!(
+        assert!(
             !self.tracks.is_empty(),
-            "Track cannot be empty!"
+            "Track cannot be empty! Use try_compile() when empty tracks are possible."
         );
🤖 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 509 - 513, The compile()
function currently uses debug_assert! to check for empty tracks, so in release
builds it can accept empty tracks contrary to its documented panic contract;
update the check in Timeline::compile (the
debug_assert!(!self.tracks.is_empty(), "Track cannot be empty!")) to enforce the
invariant in all builds (replace with assert! or an explicit panic/early return
that triggers on self.tracks.is_empty()) so an empty tracks vector cannot
produce an invalid Timeline state.
🤖 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/motiongfx/src/timeline.rs`:
- Around line 50-52: The code currently silently skips when
registry.pipeline.get(key) returns None; instead enforce the registry invariant
by failing fast: replace the `continue` with an explicit panic or error return
(e.g., panic! or Err) that includes the missing key and context (e.g., "missing
pipeline for key {:?}"), and do the same for the other occurrence where
registry.pipeline.get(key) is used; ensure the error message references
`registry.pipeline.get(key)` / the pipeline key so diagnostics point to the
exact missing registry entry.

---

Outside diff comments:
In `@crates/motiongfx/src/timeline.rs`:
- Around line 509-513: The compile() function currently uses debug_assert! to
check for empty tracks, so in release builds it can accept empty tracks contrary
to its documented panic contract; update the check in Timeline::compile (the
debug_assert!(!self.tracks.is_empty(), "Track cannot be empty!")) to enforce the
invariant in all builds (replace with assert! or an explicit panic/early return
that triggers on self.tracks.is_empty()) so an empty tracks vector cannot
produce an invalid Timeline state.
🪄 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: 15d97e65-73c4-4a1e-b43b-b66e7082e19a

📥 Commits

Reviewing files that changed from the base of the PR and between aaad04e and f5a0e5f.

📒 Files selected for processing (1)
  • crates/motiongfx/src/timeline.rs

Comment thread crates/motiongfx/src/timeline.rs Outdated
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 (2)
examples/bevy_examples/examples/minimal.rs (1)

4-4: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Update the TimelineComplete import path.

TimelineComplete no longer exists in bevy_motiongfx::world; it is defined in the new manager module, so this example does not compile as written.

Suggested fix
-use bevy_motiongfx::world::TimelineComplete;
+use bevy_motiongfx::manager::TimelineComplete;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/bevy_examples/examples/minimal.rs` at line 4, The example imports
TimelineComplete from the old module; update the use statement to import
TimelineComplete from the new manager module (replace
bevy_motiongfx::world::TimelineComplete with
bevy_motiongfx::manager::TimelineComplete) so the example compiles with the
relocated symbol.
examples/bevy_examples/examples/recording.rs (1)

8-8: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix the stale TimelineComplete module path.

After this refactor, TimelineComplete is no longer exported from bevy_motiongfx::world, so this import breaks the example build.

Suggested fix
-use bevy_motiongfx::world::TimelineComplete;
+use bevy_motiongfx::manager::TimelineComplete;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/bevy_examples/examples/recording.rs` at line 8, The import use
bevy_motiongfx::world::TimelineComplete is stale and should be updated: locate
where TimelineComplete is now exported in the crate (search the codebase for the
TimelineComplete type) and replace the broken import with the correct module
path (or remove the import and reference the type with its new fully-qualified
path where used). Ensure the example references the TimelineComplete symbol from
its current export location instead of bevy_motiongfx::world.
🤖 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/bevy_motiongfx/src/manager.rs`:
- Around line 97-111: The add_timeline method accepts any BevyTimeline which
allows timelines from a different Registry to be inserted and later used in
load_pending_timelines()/sample_timelines(), violating registry affinity; make
MotionGfxManager the only producer of insertable timelines by either (a)
changing add_timeline to accept a builder-produced wrapper/token type (e.g., a
ManagerOwnedBevyTimeline or TimelineHandle returned by
create_builder()/create_bevy_builder) instead of raw BevyTimeline, or (b) attach
and verify a Registry token on BevyTimeline and check that token inside
add_timeline (compare against self.registry’s token) and reject/move/convert
mismatched timelines; update create_builder/create_bevy_builder to produce the
token-wrapped timeline type or provide a creation API that returns the
manager-bound timeline so cross-registry timelines cannot be passed into
add_timeline.

In `@crates/motiongfx/src/pipeline.rs`:
- Around line 168-175: The types BakeCtx and SampleCtx are declared with a
lifetime parameter (BakeCtx<'a, W> / SampleCtx<'a, W>) but are used without the
lifetime in function signatures; update all usages (e.g., the bake function
signature `pub fn bake<W, I, S, T>(ctx: BakeCtx<W>)` and any `SampleCtx<W>`
usages around line 223) to include the appropriate lifetime parameter (e.g.,
`BakeCtx<'a, W>` / `SampleCtx<'a, W>` or introduce a matching generic lifetime
like `<'a, W>` on the function) so the declared structs and their uses match and
compile under stable Rust.

---

Outside diff comments:
In `@examples/bevy_examples/examples/minimal.rs`:
- Line 4: The example imports TimelineComplete from the old module; update the
use statement to import TimelineComplete from the new manager module (replace
bevy_motiongfx::world::TimelineComplete with
bevy_motiongfx::manager::TimelineComplete) so the example compiles with the
relocated symbol.

In `@examples/bevy_examples/examples/recording.rs`:
- Line 8: The import use bevy_motiongfx::world::TimelineComplete is stale and
should be updated: locate where TimelineComplete is now exported in the crate
(search the codebase for the TimelineComplete type) and replace the broken
import with the correct module path (or remove the import and reference the type
with its new fully-qualified path where used). Ensure the example references the
TimelineComplete symbol from its current export location instead of
bevy_motiongfx::world.
🪄 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: 01e529a1-3cfd-493f-8cb1-f51aebf720f0

📥 Commits

Reviewing files that changed from the base of the PR and between f5a0e5f and b93f3a3.

📒 Files selected for processing (14)
  • crates/bevy_motiongfx/README.md
  • crates/bevy_motiongfx/src/controller.rs
  • crates/bevy_motiongfx/src/lib.rs
  • crates/bevy_motiongfx/src/manager.rs
  • crates/bevy_motiongfx/src/pipeline.rs
  • crates/bevy_motiongfx/src/world.rs
  • crates/motiongfx/src/pipeline.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/pipeline.rs
🚧 Files skipped from review as they are similar to previous changes (4)
  • examples/bevy_examples/examples/custom_ease.rs
  • crates/bevy_motiongfx/README.md
  • examples/bevy_examples/examples/slide_basic.rs
  • crates/bevy_motiongfx/src/lib.rs

Comment thread crates/bevy_motiongfx/src/manager.rs
Comment thread crates/motiongfx/src/pipeline.rs
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

✅ Created PR with unit tests: #102

Comment thread examples/bevy_examples/examples/slide_basic.rs Outdated
Comment thread examples/bevy_examples/examples/slide_basic.rs Outdated
Comment thread examples/bevy_examples/examples/slide_basic.rs
Comment thread examples/bevy_examples/examples/slide_basic.rs Outdated
Comment thread crates/motiongfx/src/timeline.rs
Comment thread crates/motiongfx/src/timeline.rs
@nixonyh nixonyh requested a review from Jaghov May 2, 2026 14:34
@nixonyh nixonyh force-pushed the nixon/lazy-registration branch 2 times, most recently from 8c65031 to d699aa0 Compare May 3, 2026 13:45
@nixonyh nixonyh force-pushed the nixon/lazy-registration branch from d699aa0 to f95e9a0 Compare May 3, 2026 13:46
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: 4

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)

514-526: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Enforce the non-empty-track invariant in release builds too.

Line 523 uses debug_assert!, so compile() can still produce an empty Timeline<W> in release builds even though the rest of the type assumes at least one track. That turns the documented failure into later panics in methods like last_track_index(), set_target_time(), and is_complete().

Proposed fix
-        debug_assert!(
+        assert!(
             !self.tracks.is_empty(),
             "Track cannot be empty!"
         );
🤖 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 514 - 526, The compile()
method currently uses debug_assert! which is disabled in release builds,
allowing an empty Timeline to be created; change the check to enforce the
invariant in all builds by replacing debug_assert! with a hard assertion or
explicit panic (e.g., assert!(!self.tracks.is_empty(), "Track cannot be empty!")
or if self.tracks.is_empty() { panic!("Track cannot be empty!") }) inside
Timeline::compile so it panics as documented when tracks is empty; keep mention
of Self::try_compile in the docs if you want a non-panicking alternative.
🤖 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/bevy_motiongfx/src/manager.rs`:
- Around line 102-107: The add_timeline() path currently wraps the incoming
BevyTimeline in MutDetect::new which clears its mutation flag and causes
preconfigured timelines to be skipped by sample_timelines(); change
add_timeline() so the MutDetect wrapper is marked mutated on insert (e.g.,
construct or update the MutDetect for the timeline in pending_timelines so its
mutated() returns true) so load_pending_timelines() will bake the timeline and
sample_timelines() will process it; reference pending_timelines, add_timeline,
MutDetect, load_pending_timelines, and sample_timelines when making the change.

In `@crates/motiongfx/README.md`:
- Around line 333-334: The README uses absolute-root links "/LICENSE-MIT" and
"/LICENSE-APACHE" which can break in rendered docs; update the license links to
be repository-relative (e.g., "LICENSE-MIT" and "LICENSE-APACHE" or
"./LICENSE-MIT" and "./LICENSE-APACHE") so the link targets "LICENSE-MIT" and
"LICENSE-APACHE" resolve correctly in all contexts; change the two occurrences
that reference "LICENSE-MIT" and "LICENSE-APACHE" in the README header lines
accordingly.

In `@crates/motiongfx/src/pipeline.rs`:
- Around line 61-108: PipelineKey currently omits the orphan-rule marker `M`
used by the SubjectSource trait, causing different marker impls to collide; fix
this by adding a marker_id: TypeId field to PipelineKey and populate it from the
marker type in constructors: update struct PipelineKey to include marker_id:
TypeId, change PipelineKey::new to accept an M: 'static generic and set
marker_id = TypeId::of::<M>(), update PipelineKey::from_action_key to be generic
over M: 'static and set marker_id = TypeId::of::<M>(), and add a pub(crate) fn
marker_id(&self) -> TypeId accessor; this ensures register::<W,I,S,T,M1>() and
register::<W,I,S,T,M2>() produce distinct keys.

In `@examples/bevy_examples/examples/hello_world.rs`:
- Around line 58-62: The index calculation for the grid is using the wrong
stride: replace the expression c = w * WIDTH + h with c = w * HEIGHT + h so the
computed index into cube_ids uses the correct row stride; update the loop that
iterates w and h (variables w, h and constants WIDTH, HEIGHT, and the cube_ids
access/cube_id variable) accordingly to ensure correct indexing when WIDTH !=
HEIGHT.

---

Outside diff comments:
In `@crates/motiongfx/src/timeline.rs`:
- Around line 514-526: The compile() method currently uses debug_assert! which
is disabled in release builds, allowing an empty Timeline to be created; change
the check to enforce the invariant in all builds by replacing debug_assert! with
a hard assertion or explicit panic (e.g., assert!(!self.tracks.is_empty(),
"Track cannot be empty!") or if self.tracks.is_empty() { panic!("Track cannot be
empty!") }) inside Timeline::compile so it panics as documented when tracks is
empty; keep mention of Self::try_compile in the docs if you want a non-panicking
alternative.
🪄 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: a72279ea-68d3-4c84-9488-b0b77e73b94f

📥 Commits

Reviewing files that changed from the base of the PR and between 56311c9 and f95e9a0.

📒 Files selected for processing (17)
  • crates/bevy_motiongfx/README.md
  • crates/bevy_motiongfx/src/interpolation.rs
  • crates/bevy_motiongfx/src/manager.rs
  • crates/bevy_motiongfx/src/world.rs
  • crates/motiongfx/README.md
  • crates/motiongfx/docs/world.rs
  • crates/motiongfx/examples/custom_world.rs
  • crates/motiongfx/src/pipeline.rs
  • crates/motiongfx/src/registry.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 skipped from review as they are similar to previous changes (3)
  • crates/bevy_motiongfx/README.md
  • examples/bevy_examples/examples/easings.rs
  • crates/bevy_motiongfx/src/interpolation.rs

Comment on lines +102 to +107
pub fn add_timeline(
&mut self,
timeline: BevyTimeline,
) -> TimelineId {
let id = self.id;
self.pending_timelines.insert(id, MutDetect::new(timeline));
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 | 🟠 Major | ⚡ Quick win

Mark inserted timelines as dirty.

Line 107 wraps the incoming timeline in MutDetect::new, which resets the mutation flag even if the caller already changed the timeline before add_timeline(). A timeline preconfigured with set_target_time or set_target_track will be baked in load_pending_timelines() and then skipped by sample_timelines() because only mutated() entries are sampled.

Proposed fix
     pub fn add_timeline(
         &mut self,
         timeline: BevyTimeline,
     ) -> TimelineId {
         let id = self.id;
-        self.pending_timelines.insert(id, MutDetect::new(timeline));
+        let mut timeline = MutDetect::new(timeline);
+        timeline.mutated = true;
+        self.pending_timelines.insert(id, timeline);
 
         self.id.0 = self.id.0.wrapping_add(1);
         id
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/bevy_motiongfx/src/manager.rs` around lines 102 - 107, The
add_timeline() path currently wraps the incoming BevyTimeline in MutDetect::new
which clears its mutation flag and causes preconfigured timelines to be skipped
by sample_timelines(); change add_timeline() so the MutDetect wrapper is marked
mutated on insert (e.g., construct or update the MutDetect for the timeline in
pending_timelines so its mutated() returns true) so load_pending_timelines()
will bake the timeline and sample_timelines() will process it; reference
pending_timelines, add_timeline, MutDetect, load_pending_timelines, and
sample_timelines when making the change.

Comment on lines +333 to +334
- MIT License ([LICENSE-MIT](/LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
- Apache License, Version 2.0 ([LICENSE-APACHE](/LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
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

License links are brittle due absolute-root paths.

Line 333 and Line 334 use /LICENSE-*, which can resolve incorrectly in rendered docs. Prefer repo-relative links.

Proposed fix
-- MIT License ([LICENSE-MIT](/LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
-- Apache License, Version 2.0 ([LICENSE-APACHE](/LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
+- MIT License ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
+- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- MIT License ([LICENSE-MIT](/LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
- Apache License, Version 2.0 ([LICENSE-APACHE](/LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
- MIT License ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/motiongfx/README.md` around lines 333 - 334, The README uses
absolute-root links "/LICENSE-MIT" and "/LICENSE-APACHE" which can break in
rendered docs; update the license links to be repository-relative (e.g.,
"LICENSE-MIT" and "LICENSE-APACHE" or "./LICENSE-MIT" and "./LICENSE-APACHE") so
the link targets "LICENSE-MIT" and "LICENSE-APACHE" resolve correctly in all
contexts; change the two occurrences that reference "LICENSE-MIT" and
"LICENSE-APACHE" in the README header lines accordingly.

Comment thread crates/motiongfx/src/pipeline.rs Outdated
Comment on lines 58 to 62
for w in 0..WIDTH {
for h in 0..HEIGHT {
let c = w * WIDTH + h;
let cube = cubes[c];
let cube_id = cube_ids[c];

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

Fix grid index calculation for non-square dimensions.

Line 60 uses w * WIDTH + h; this should use the row stride (HEIGHT) to stay correct if dimensions diverge.

Proposed fix
-            let c = w * WIDTH + h;
+            let c = w * HEIGHT + h;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/bevy_examples/examples/hello_world.rs` around lines 58 - 62, The
index calculation for the grid is using the wrong stride: replace the expression
c = w * WIDTH + h with c = w * HEIGHT + h so the computed index into cube_ids
uses the correct row stride; update the loop that iterates w and h (variables w,
h and constants WIDTH, HEIGHT, and the cube_ids access/cube_id variable)
accordingly to ensure correct indexing when WIDTH != HEIGHT.

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.

♻️ Duplicate comments (4)
crates/motiongfx/src/timeline.rs (2)

517-525: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Enforce the non-empty-track invariant in release builds.

compile() documents a panic here, but debug_assert! disappears in release and still builds a Timeline<W> that later indexes self.tracks[0]. This should be an unconditional assert! or a try_compile().expect(...).

Suggested fix
-        debug_assert!(
-            !self.tracks.is_empty(),
-            "Track cannot be empty!"
-        );
+        assert!(
+            !self.tracks.is_empty(),
+            "Track cannot be empty! Use `try_compile()` if empty tracks are expected."
+        );
🤖 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 517 - 525, The compile()
function currently uses debug_assert! to check !self.tracks.is_empty(), which is
removed in release builds and leads to indexing self.tracks[0] later; change
this to enforce the invariant unconditionally by either replacing debug_assert!
with assert!(!self.tracks.is_empty(), "Track cannot be empty!") or by
implementing compile() as self.try_compile().expect("Track cannot be empty!") so
the empty-track case always panics in release and debug; update the compile()
body around the existing check and the call sites to use the chosen approach
(functions: compile, try_compile, and access to self.tracks).

50-62: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail fast on missing pipelines instead of only debug_assert!ing.

In release builds this becomes a silent no-op, so a registry mismatch just drops baking/sampling work. Given this API now depends on registry affinity, this should be a hard failure or an error return, not a debug-only check.

Suggested fix
-                let ok = registry.pipeline.bake(
+                let ok = registry.pipeline.bake(
                     key,
                     BakeCtx {
                         world: subject_world,
                         track,
                         action_world: &mut self.action_world,
                         accessor_registry: &registry.accessor,
                     },
                 );
-                debug_assert!(
-                    ok,
-                    "pipeline not found for key {key:?}"
-                );
+                assert!(ok, "pipeline not found for key {key:?}");
-            let ok = registry.pipeline.sample(
+            let ok = registry.pipeline.sample(
                 key,
                 SampleCtx {
                     world: subject_world,
                     action_world: &self.action_world,
                     accessor_registry: &registry.accessor,
                 },
             );
-            debug_assert!(ok, "pipeline not found for key {key:?}");
+            assert!(ok, "pipeline not found for key {key:?}");

Also applies to: 237-245

🤖 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 50 - 62, The code currently
calls registry.pipeline.bake(...) and only does a debug_assert!(ok, ...) which
becomes a no-op in release; change this to a hard failure or proper error
propagation: if the surrounding function can return a Result, change its
signature to return Result<..., Error> and propagate the failure from
registry.pipeline.bake by returning an Err with a clear message including key
(replace the debug_assert! after the bake call with return Err(format!("pipeline
not found for key {:?}", key).into())); if the surrounding API cannot return a
Result, replace the debug_assert! with an unconditional panic!(...) that
includes the same message. Apply the same change to the other occurrence around
lines 237-245 where registry.pipeline.bake / debug_assert! is used so missing
pipelines never silently drop work.
crates/bevy_motiongfx/src/manager.rs (1)

102-107: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Mark newly added timelines as mutated.

Wrapping the incoming timeline with MutDetect::new(...) clears its dirty flag, so preconfigured timelines can be baked and then skipped by sample_timelines() on their first pass.

Suggested fix
     pub fn add_timeline(
         &mut self,
         timeline: BevyTimeline,
     ) -> TimelineId {
         let id = self.id;
-        self.pending_timelines.insert(id, MutDetect::new(timeline));
+        let mut timeline = MutDetect::new(timeline);
+        timeline.mutated = true;
+        self.pending_timelines.insert(id, timeline);
 
         self.id.0 = self.id.0.wrapping_add(1);
         id
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/bevy_motiongfx/src/manager.rs` around lines 102 - 107, The new
timeline is wrapped with MutDetect::new(...) which leaves it non-dirty and
causes sample_timelines() to skip it; update add_timeline (and the
pending_timelines insertion) to mark the inserted MutDetect as mutated (e.g.,
create it with the MutDetect variant/constructor that marks dirty or call its
mark_mutated()/set_dirty() method immediately after inserting) so the freshly
added timeline is recognized as changed by sample_timelines(); touch the
MutDetect instance produced for timeline in add_timeline (function name:
add_timeline, collection: pending_timelines, type: MutDetect) to set its dirty
flag.
crates/motiongfx/README.md (1)

299-300: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use repo-relative license links.

These absolute-root paths can break in rendered docs. Relative links are safer here.

Suggested fix
-- MIT License ([LICENSE-MIT](/LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
-- Apache License, Version 2.0 ([LICENSE-APACHE](/LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
+- MIT License ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
+- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/motiongfx/README.md` around lines 299 - 300, Update the two license
markdown links so they use repo-relative paths instead of absolute-root paths:
replace the link targets in the lines containing "MIT License
([LICENSE-MIT](/LICENSE-MIT)..." and "Apache License, Version 2.0
([LICENSE-APACHE](/LICENSE-APACHE)..." with relative targets (e.g.
"./LICENSE-MIT" or "LICENSE-MIT" and "./LICENSE-APACHE" or "LICENSE-APACHE") so
the README uses repo-relative links that won’t break in rendered docs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@crates/bevy_motiongfx/src/manager.rs`:
- Around line 102-107: The new timeline is wrapped with MutDetect::new(...)
which leaves it non-dirty and causes sample_timelines() to skip it; update
add_timeline (and the pending_timelines insertion) to mark the inserted
MutDetect as mutated (e.g., create it with the MutDetect variant/constructor
that marks dirty or call its mark_mutated()/set_dirty() method immediately after
inserting) so the freshly added timeline is recognized as changed by
sample_timelines(); touch the MutDetect instance produced for timeline in
add_timeline (function name: add_timeline, collection: pending_timelines, type:
MutDetect) to set its dirty flag.

In `@crates/motiongfx/README.md`:
- Around line 299-300: Update the two license markdown links so they use
repo-relative paths instead of absolute-root paths: replace the link targets in
the lines containing "MIT License ([LICENSE-MIT](/LICENSE-MIT)..." and "Apache
License, Version 2.0 ([LICENSE-APACHE](/LICENSE-APACHE)..." with relative
targets (e.g. "./LICENSE-MIT" or "LICENSE-MIT" and "./LICENSE-APACHE" or
"LICENSE-APACHE") so the README uses repo-relative links that won’t break in
rendered docs.

In `@crates/motiongfx/src/timeline.rs`:
- Around line 517-525: The compile() function currently uses debug_assert! to
check !self.tracks.is_empty(), which is removed in release builds and leads to
indexing self.tracks[0] later; change this to enforce the invariant
unconditionally by either replacing debug_assert! with
assert!(!self.tracks.is_empty(), "Track cannot be empty!") or by implementing
compile() as self.try_compile().expect("Track cannot be empty!") so the
empty-track case always panics in release and debug; update the compile() body
around the existing check and the call sites to use the chosen approach
(functions: compile, try_compile, and access to self.tracks).
- Around line 50-62: The code currently calls registry.pipeline.bake(...) and
only does a debug_assert!(ok, ...) which becomes a no-op in release; change this
to a hard failure or proper error propagation: if the surrounding function can
return a Result, change its signature to return Result<..., Error> and propagate
the failure from registry.pipeline.bake by returning an Err with a clear message
including key (replace the debug_assert! after the bake call with return
Err(format!("pipeline not found for key {:?}", key).into())); if the surrounding
API cannot return a Result, replace the debug_assert! with an unconditional
panic!(...) that includes the same message. Apply the same change to the other
occurrence around lines 237-245 where registry.pipeline.bake / debug_assert! is
used so missing pipelines never silently drop work.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1382d8e2-770e-4cd2-a56a-2f6a52a9f09d

📥 Commits

Reviewing files that changed from the base of the PR and between f95e9a0 and 949bbc8.

📒 Files selected for processing (11)
  • crates/bevy_motiongfx/src/interpolation.rs
  • crates/bevy_motiongfx/src/manager.rs
  • crates/bevy_motiongfx/src/world.rs
  • crates/motiongfx/README.md
  • crates/motiongfx/docs/world.rs
  • crates/motiongfx/examples/custom_world.rs
  • crates/motiongfx/src/lib.rs
  • crates/motiongfx/src/pipeline.rs
  • crates/motiongfx/src/registry.rs
  • crates/motiongfx/src/timeline.rs
  • crates/motiongfx/src/world.rs
🚧 Files skipped from review as they are similar to previous changes (4)
  • crates/bevy_motiongfx/src/interpolation.rs
  • crates/motiongfx/src/registry.rs
  • crates/motiongfx/examples/custom_world.rs
  • crates/motiongfx/src/lib.rs

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.

🧹 Nitpick comments (1)
examples/bevy_examples/examples/custom_interp.rs (1)

76-76: Track the arc_lerp_3d optimization TODO.

This is fine to land as-is, but the inline TODO is easy to lose. If you want, I can help turn it into a tracked follow-up or sketch a tighter implementation.

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

In `@examples/bevy_examples/examples/custom_interp.rs` at line 76, Replace the
loose "// TODO(nixon): Optimize this." comment for arc_lerp_3d with a tracked
follow-up: open a short issue describing the performance goal and proposed
approach for optimizing arc_lerp_3d, then update the comment to reference that
issue number or URL (e.g., "TODO(nixon): optimize arc_lerp_3d — tracked in issue
`#NNN`") so the work isn't lost; optionally add the issue to the project board or
changelog to ensure follow-up.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@examples/bevy_examples/examples/custom_interp.rs`:
- Line 76: Replace the loose "// TODO(nixon): Optimize this." comment for
arc_lerp_3d with a tracked follow-up: open a short issue describing the
performance goal and proposed approach for optimizing arc_lerp_3d, then update
the comment to reference that issue number or URL (e.g., "TODO(nixon): optimize
arc_lerp_3d — tracked in issue `#NNN`") so the work isn't lost; optionally add the
issue to the project board or changelog to ensure follow-up.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0313531a-140c-4bc7-84f5-9133eba23bc4

📥 Commits

Reviewing files that changed from the base of the PR and between 949bbc8 and 5d75d17.

📒 Files selected for processing (1)
  • examples/bevy_examples/examples/custom_interp.rs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve motiongfx's README to be more beginner friendly

2 participants