Skip to content

Migrate to trait based inspector - #127

Merged
nixonyh merged 2 commits into
mainfrom
nixon/trait-based-inspector
Aug 4, 2026
Merged

Migrate to trait based inspector#127
nixonyh merged 2 commits into
mainfrom
nixon/trait-based-inspector

Conversation

@nixonyh

@nixonyh nixonyh commented Aug 4, 2026

Copy link
Copy Markdown
Member

No description provided.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4d918f09-70fa-4bda-8db9-31f7e7e75c82

📥 Commits

Reviewing files that changed from the base of the PR and between 68bcff8 and 43c5a68.

📒 Files selected for processing (1)
  • editor/motiongfx_editor_ui/src/inspector/widget.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • editor/motiongfx_editor_ui/src/inspector/widget.rs

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Introduced a reflection-based inspector supporting both resources and components.
    • Added editable controls for boolean, signed numeric, and unsigned numeric values.
    • Added dynamic widget selection based on the inspected data type.
    • Improved inspector updates while editing, preserving focused inputs and synchronizing changes.
    • Added support for inspecting component data directly within editor scenes.

Walkthrough

The editor inspector now supports resource and component targets through reflection. Registered ReflectInspect implementations build field widgets. The editor registers default boolean and numeric inspectors and passes an explicit resource target for editor settings.

Changes

Inspector generalization

Layer / File(s) Summary
Widget contracts and primitive inspectors
editor/motiongfx_editor_ui/src/inspector/widget.rs
Added reflection-based inspection contracts and registry registration. Added checkbox and numeric widgets with reflected reads, writes, and synchronization.
Target-based inspector state
editor/motiongfx_editor_ui/src/inspector.rs
Added resource and component targets, reflective field access, registry-driven widget construction, tuple-struct traversal, change tracking, and shape-aware rebuilding.
Editor inspector integration
editor/motiongfx_editor/src/lib.rs, editor/motiongfx_editor/src/scene.rs
Registered default inspectors and passed InspectorTarget::resource::<EditorSettings>() to the settings panel.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant EditorPlugin
  participant InspectorFields
  participant InspectorTarget
  participant TypeRegistry
  participant InspectorWidget
  EditorPlugin->>TypeRegistry: register_default_inspects()
  EditorPlugin->>InspectorFields: pass resource target
  InspectorFields->>InspectorTarget: resolve reflected resource
  InspectorTarget->>TypeRegistry: access registered inspector
  TypeRegistry->>InspectorWidget: build field widget
  InspectorWidget->>InspectorTarget: read and write field values
Loading

Possibly related PRs

Poem

A rabbit checks each reflected field,
While number inputs read and yield.
Resources and components align,
With registered widgets in a line.
The editor follows the new design.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive No pull request description was provided, so the changeset intent is not documented beyond the title. Add a short description that explains the trait-based inspector migration and the new resource and component inspection support.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the migration from the existing inspector implementation to a trait-based inspector framework.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
editor/motiongfx_editor_ui/src/inspector/widget.rs (1)

95-105: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The comment does not match the behavior.

The comment says the checkbox state moves only after the write lands. The code inserts or removes Checked unconditionally, in the same observer, without checking that field.set succeeded. If the path no longer resolves, field.set only logs a warning, and the checkbox still flips until the next target_changed poll corrects it.

Either drop the claim from the comment, or move the Checked update into the queued command after a successful write.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@editor/motiongfx_editor_ui/src/inspector/widget.rs` around lines 95 - 105,
Update the observer around field.set and the Checked component so the checkbox
state changes only after a successful write, moving the Checked insert/remove
into the queued command that follows a successful field.set; alternatively,
revise the misleading comment to describe the current unconditional behavior.
Keep target_changed correction behavior unchanged.
editor/motiongfx_editor_ui/src/inspector.rs (2)

350-382: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The row label is the raw reflect path.

label is leaf.path verbatim. For a nested leaf the panel shows physical_size.x, and for a tuple-struct leaf it shows a bare index such as 0. Both read poorly in the settings panel.

Consider labelling with the last path segment and keeping the full path as a tooltip or debug detail.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@editor/motiongfx_editor_ui/src/inspector.rs` around lines 350 - 382, Update
the label construction in build_fields so nested leaves display only the final
path segment rather than the full leaf.path, while tuple-struct indices receive
a readable field label instead of a bare number. Preserve the complete path
separately for a tooltip or debug detail if the existing UI supports one.

249-279: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Fields of unsupported reflect kinds disappear without a trace.

collect_leaves descends into Struct and TupleStruct only. An enum, list, map, tuple, or opaque field with no registered ReflectInspect matches the _ => {} arm, so the inspector renders no row and logs nothing. A user cannot tell the field from a field that does not exist.

Consider a debug! on the fallthrough arm with the path and type name. It keeps the walk unchanged and makes a missing row explainable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@editor/motiongfx_editor_ui/src/inspector.rs` around lines 249 - 279, The
fallthrough arm in collect_leaves currently drops unsupported reflected fields
silently. Add a debug-level log there that includes the current path and
reflected type name, while leaving traversal behavior unchanged for Struct and
TupleStruct and retaining the empty fallthrough logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@editor/motiongfx_editor_ui/src/inspector.rs`:
- Around line 72-96: Update accessor and the related read/write/changed_tick
paths to resolve reflection data according to the InspectorTarget variant: use
ReflectResource for Resource targets and ReflectComponent for Component targets.
Preserve the existing cloned accessor behavior and ensure resources annotated
only with #[reflect(Resource)] remain supported as documented.

In `@editor/motiongfx_editor_ui/src/inspector/widget.rs`:
- Around line 197-201: Update the u32 conversion closure in the numeric format
mappings to clamp the i64 input to the full u32 range before casting, preventing
values above u32::MAX from truncating. Keep the existing lower-bound behavior
and use the same shared clamp approach for the u64 row so both conversions
remain uniform.

---

Nitpick comments:
In `@editor/motiongfx_editor_ui/src/inspector.rs`:
- Around line 350-382: Update the label construction in build_fields so nested
leaves display only the final path segment rather than the full leaf.path, while
tuple-struct indices receive a readable field label instead of a bare number.
Preserve the complete path separately for a tooltip or debug detail if the
existing UI supports one.
- Around line 249-279: The fallthrough arm in collect_leaves currently drops
unsupported reflected fields silently. Add a debug-level log there that includes
the current path and reflected type name, while leaving traversal behavior
unchanged for Struct and TupleStruct and retaining the empty fallthrough logic.

In `@editor/motiongfx_editor_ui/src/inspector/widget.rs`:
- Around line 95-105: Update the observer around field.set and the Checked
component so the checkbox state changes only after a successful write, moving
the Checked insert/remove into the queued command that follows a successful
field.set; alternatively, revise the misleading comment to describe the current
unconditional behavior. Keep target_changed correction behavior unchanged.
🪄 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: 5f58721f-3709-4706-903c-de81a06e2e7c

📥 Commits

Reviewing files that changed from the base of the PR and between 7218dcb and 68bcff8.

📒 Files selected for processing (4)
  • editor/motiongfx_editor/src/lib.rs
  • editor/motiongfx_editor/src/scene.rs
  • editor/motiongfx_editor_ui/src/inspector.rs
  • editor/motiongfx_editor_ui/src/inspector/widget.rs

Comment on lines +72 to +96
/// The accessor for this target's type, cloned out so the registry
/// guard is never held while the caller runs. Nesting two read
/// guards on one thread can deadlock the moment a writer queues
/// between them, and callers here reach for the registry again.
fn accessor(&self, world: &World) -> Option<ReflectComponent> {
let registry = world.resource::<AppTypeRegistry>().read();
registry
.get_type_data::<ReflectComponent>(self.type_id())
.cloned()
}

/// Runs `read` against the value, or returns `None` when the
/// target is gone or its type was never registered with
/// `#[reflect(Component)]` / `#[reflect(Resource)]`.
pub fn read<R>(
&self,
world: &World,
read: impl FnOnce(&dyn Reflect) -> R,
) -> Option<R> {
let entity = self.entity(world)?;
let component = self.accessor(world)?;
let value =
component.reflect(world.get_entity(entity).ok()?)?;
Some(read(value))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how EditorSettings and other inspector targets are reflected.
fd -e rs . editor | xargs rg -n -B6 'struct EditorSettings'
# Any type registered with reflect(Resource) but not reflect(Component).
rg -n -C4 'reflect\((Resource|Component)' --type=rs editor
# Confirm ReflectResource is never consulted by the inspector.
rg -n 'ReflectResource|ReflectComponent' --type=rs editor

Repository: voxell-tech/motiongfx

Length of output: 683


🏁 Script executed:

#!/bin/bash
set -e

echo "Files matching inspector.rs:"
fd -e rs 'inspector\.rs$' . || true

echo
echo "EditorSettings definition:"
fd -e rs 'lib\.rs$' . | xargs rg -n -B8 'struct EditorSettings' || true

echo
echo "Reflect annotations in editor:"
find . -type f -name '*.rs' | xargs rg -n -C4 'reflect\((Resource|Component|SettingsGroup)\)' || true

echo
echo "ReflectResource/ReflectComponent in editor:"
find . -type f -name '*.rs' | xargs rg -n 'ReflectResource|ReflectComponent' || true

echo
echo "inspector snippets if present:"
for f in $(fd -e rs 'inspector\.rs$' .); do
  echo "--- $f ---"
  sed -n '1,130p' "$f"
done

Repository: voxell-tech/motiongfx

Length of output: 7588


Use ReflectResource for the resource path.

accessor() always resolves ReflectComponent, so #[reflect(Resource)] targets such as EditorSettings return None through read()/write()/changed_tick(). The doc says either annotation works, but EditorSettings uses only #[reflect(Resource, SettingsGroup, Default)]. Guard by target variant: use ReflectResource for InspectorTarget::Resource (or document that resources must also use #[reflect(Component)]).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@editor/motiongfx_editor_ui/src/inspector.rs` around lines 72 - 96, Update
accessor and the related read/write/changed_tick paths to resolve reflection
data according to the InspectorTarget variant: use ReflectResource for Resource
targets and ReflectComponent for Component targets. Preserve the existing cloned
accessor behavior and ensure resources annotated only with #[reflect(Resource)]
remain supported as documented.

Comment thread editor/motiongfx_editor_ui/src/inspector/widget.rs
@nixonyh
nixonyh merged commit ec409fe into main Aug 4, 2026
8 checks passed
@nixonyh
nixonyh deleted the nixon/trait-based-inspector branch August 4, 2026 06:58
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