Skip to content

Add local editing to the inspector details panel - #25923

Open
jbuehler23 wants to merge 2 commits into
bevyengine:mainfrom
jbuehler23:jackdaw/inspector-editing
Open

jbuehler23 wants to merge 2 commits into
bevyengine:mainfrom
jbuehler23:jackdaw/inspector-editing

Conversation

@jbuehler23

@jbuehler23 jbuehler23 commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Objective

Part of #23013.

Let the inspector edit the selected entity's components from the details panel, instead of only showing them.

Solution

Each field widget knows which component and field path it edits. Changing it triggers a FieldEdit event, and an observer writes the value into the component through reflection. Going through an event means a remote source can apply the same edit later without the panel changing.

  • bools, all the numeric types, strings and chars, plus unit enums through the select
  • integers outside the field's range are rejected instead of wrapping
  • the widget shows the new value straight away, then the panel picks up the real component value on the next refresh
  • fields the inspector can't write log a warning and are left alone

Colours and switching to enum variants with fields are left for the next PR.

AI disclosure

Same approach as the earlier pieces. I planned the scope, AI did the mechanical port from Jackdaw and a first check for problems, and I reviewed it and tested it by hand. Testing by hand is where the main issue showed up. The edits worked in unit tests but not when clicking the real widgets, because the feathers number input and checkbox don't update themselves and the panel skipped writing the value back. The tests now drive the actual widgets headlessly for better testing coverage

Showcase

@jbuehler23
jbuehler23 force-pushed the jackdaw/inspector-editing branch 2 times, most recently from f8fe006 to ca2e64e Compare September 27, 2026 16:18
@alice-i-cecile alice-i-cecile added C-Feature A new feature, making something new possible M-Release-Note Work that should be called out in the blog due to impact A-Dev-Tools Tools used to debug Bevy applications. S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Sep 27, 2026
@alice-i-cecile
alice-i-cecile self-requested a review September 27, 2026 20:16
@Zeophlite Zeophlite added the S-Merge-Conflicts Merge conflicts :( Add this label on top of other S- labels. label Sep 28, 2026
@jbuehler23
jbuehler23 force-pushed the jackdaw/inspector-editing branch from ca2e64e to 5d4b1fb Compare September 28, 2026 11:53
@alice-i-cecile alice-i-cecile removed the S-Merge-Conflicts Merge conflicts :( Add this label on top of other S- labels. label Sep 28, 2026
@jbuehler23
jbuehler23 force-pushed the jackdaw/inspector-editing branch 5 times, most recently from a8522cf to ff64fa9 Compare October 1, 2026 21:44

@Nilirad Nilirad left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Edits that set the same value as the previous one (i.e. changes that change nothing) should not mark the component as changed in write_field_edit. That would unnecessarily pollute change detection data. For example, while dragging with the mouse pointer the event is emitted each frame the pointer moves, even for integer types whose value actually change once every 100 pixels, creating a cascade of meaningless changes.

This is caused by the writing functions for the various reflected kinds write unconditionally without checking the old value, and return a bool based on whether a write happened. I propose to instead define a FieldWrite enum with three states (written, unchanged, rejected), and instead of unconditionally set the value, wrap most changes into an assign function:

/// Describes the outcome of a field write attempt.
enum FieldWrite {
    Written,
    Unchanged,
    Rejected
}

/// Assigns `value` to `target`, reporting the change based on previous data.
///
/// If the `target`'s old value is the same of `value`,
/// returns `FieldWrite::Unchanged` without assigning the value.
fn assign<T: PartialEq>(target: &mut T, value: T) -> FieldWrite {
    if *target == value {
        FieldWrite::Unchanged
    } else {
        *target = value;
        FieldWrite::Written
    }
}

This allows replacing most of the write sites (assign(target, value) instead of *target = value; return true), apart from a couple of cases that require manual production of FieldWrite:

  • write_text_field: here the String and Cow branches take by value, and using assign would allocate before comparing. Instead, we can first check for equality, and allocate only if there is a difference. The char branch can use assign though.
  • write_variant_field: no PartialEq. FieldWrite can be done by comparing the variant string name.

@alice-i-cecile alice-i-cecile added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Oct 5, 2026
@jbuehler23
jbuehler23 force-pushed the jackdaw/inspector-editing branch from ff64fa9 to 4227b53 Compare October 6, 2026 06:52
@jbuehler23

Copy link
Copy Markdown
Contributor Author

@Nilirad adopted the FieldWrite design as you described, only Written marks the component changed now. Strings compare before allocating, variants compare by name, and floats compare by bits so NaN and -0.0 behave.

This branch has not been deployed

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

Labels

A-Dev-Tools Tools used to debug Bevy applications. C-Feature A new feature, making something new possible M-Release-Note Work that should be called out in the blog due to impact S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants