bevy_editor_prototypes icon indicating copy to clipboard operation
bevy_editor_prototypes copied to clipboard

Simple single line text field

Open rewin123 opened this issue 1 year ago • 6 comments
trafficstars

Motivation

Currently, we don't have any widget that allows editing text or component values. So I decided to create a simple version of such a field.

Proposal

I created two components

LineTextField

  • Single-line text editing
  • Cursor positioning and text selection
  • Clipboard operations (copy, cut, paste, select all | Ctrl-C,X,V,A)
  • Support for text longer than field width
  • Customizable allowed characters

NumericField<T>

  • Supports multiple numeric types (u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64)
  • Text-based input for precise value entry
  • Mouse drag functionality for quick value adjustments
  • Configurable min/max value constraints
  • Customizable drag step (drag step can be less then 1 val per logical pixel)

And three crates

bevy_focus

This crate contains input focus managment

bevy_text_field

This crate contains text field logic. Builded on top of bevy_focus.

bevy_numeric_field

This crate builded on top of bevy_text_field and contains logic for NumericField<T>

Usage

// LineTextField
commands.spawn((
    NodeBundle { /* ... */ },
    LineTextField::new("Initial text"),
)).observ(|trigger: Trigger<TextChanged>| {
  let text  = trigger.event().0; //Do whatever with text
});

// Update text
let mut text_field = LineTextField::default();
text_field.set_text("bla bla bla");

// NumericField
commands.spawn((
    NodeBundle { /* ... */ },
    NumericField::<f32>::new(0.0),
)).observe(|trigger: Trigger<NewValue<f32>>| {
    let new_value = trigger.event().0;
    // Handle value change
});

// Update number
// We must use trigger because its contains complex logic for updating
commands.trigger_targets(SetValue(0.0), translation_x);

Testing

I created three examples for manual testing:

  1. single_line_text_field.rs - contains three size different single line text fields
  2. many_fields - contains all supported numeric fields
  3. transform.rs - contains mvp for changing transform with new numeric fields
  4. NumericField uses LineTextField in this work

ezgif-5-37c39e79e5

The following features are not planned for this PR

  • Multi-line editing
  • Precise cursor positioning by clicking on the text field with the mouse

Followed work

  • Move to i-cant-belive-this-is-not-bsn crate
  • Move to Required components
  • Create new SerializedField component, which allow to use LineTextField for any strut that support serialize/deserialize
  • Create design for split huge LineTextField to nice sub components, which will allow to huge customization of this text field
  • Unhardcode key bindings for copy/paste/cut
  • Change cursor from byte position into char number position for more safety for non-english text
  • Found a way to avoid invisible text nodes and text splitting

rewin123 avatar Oct 06 '24 08:10 rewin123