From 9163a3e4cecc0c33f9300aa6ee99e10790deb476 Mon Sep 17 00:00:00 2001 From: sam edelsten <samedelsten1@gmail.com> Date: Thu, 14 Sep 2023 14:53:23 +0100 Subject: [PATCH] remove editor from CosmicEdit*Bundle removes CosmicEditor::set_text in favor of a set_text CosmicText component --- examples/basic_sprite.rs | 16 ++--- examples/basic_ui.rs | 16 ++--- examples/every_option.rs | 93 ++++++++++++++++++++++++ examples/font_per_widget.rs | 24 ++----- examples/multiple_sprites.rs | 24 ++----- examples/readonly.rs | 16 ++--- examples/restricted_input.rs | 62 +++++++--------- src/lib.rs | 135 ++++++++++++++++------------------- 8 files changed, 205 insertions(+), 181 deletions(-) create mode 100644 examples/every_option.rs diff --git a/examples/basic_sprite.rs b/examples/basic_sprite.rs index ef0b9e3..cbba5fe 100644 --- a/examples/basic_sprite.rs +++ b/examples/basic_sprite.rs @@ -1,15 +1,11 @@ use bevy::{core_pipeline::clear_color::ClearColorConfig, prelude::*, window::PrimaryWindow}; use bevy_cosmic_edit::{ ActiveEditor, CosmicAttrs, CosmicEditPlugin, CosmicEditSpriteBundle, CosmicFontConfig, - CosmicFontSystem, CosmicMetrics, CosmicText, CosmicTextPosition, + CosmicMetrics, CosmicText, CosmicTextPosition, }; use cosmic_text::AttrsOwned; -fn setup( - mut commands: Commands, - windows: Query<&Window, With<PrimaryWindow>>, - mut font_system: ResMut<CosmicFontSystem>, -) { +fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) { let primary_window = windows.single(); let camera_bundle = Camera2dBundle { camera_2d: Camera2d { @@ -37,13 +33,9 @@ fn setup( }, text_position: CosmicTextPosition::Center, cosmic_attrs: CosmicAttrs(AttrsOwned::new(attrs)), + text: CosmicText::OneStyle("馃榾馃榾馃榾 x => y".to_string()), ..default() - } - .set_text( - CosmicText::OneStyle("馃榾馃榾馃榾 x => y".to_string()), - AttrsOwned::new(attrs), - &mut font_system.0, - ); + }; let cosmic_edit = commands.spawn(cosmic_edit).id(); diff --git a/examples/basic_ui.rs b/examples/basic_ui.rs index 54bfdb5..40dde82 100644 --- a/examples/basic_ui.rs +++ b/examples/basic_ui.rs @@ -1,15 +1,11 @@ use bevy::{core_pipeline::clear_color::ClearColorConfig, prelude::*, window::PrimaryWindow}; use bevy_cosmic_edit::{ ActiveEditor, CosmicAttrs, CosmicEditPlugin, CosmicEditUiBundle, CosmicEditor, - CosmicFontConfig, CosmicFontSystem, CosmicMetrics, CosmicText, CosmicTextPosition, + CosmicFontConfig, CosmicMetrics, CosmicText, CosmicTextPosition, }; use cosmic_text::AttrsOwned; -fn setup( - mut commands: Commands, - windows: Query<&Window, With<PrimaryWindow>>, - mut font_system: ResMut<CosmicFontSystem>, -) { +fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) { let primary_window = windows.single(); let camera_bundle = Camera2dBundle { camera_2d: Camera2d { @@ -38,13 +34,9 @@ fn setup( }, text_position: CosmicTextPosition::Center, cosmic_attrs: CosmicAttrs(AttrsOwned::new(attrs)), + set_text: CosmicText::OneStyle("馃榾馃榾馃榾 x => y".to_string()), ..default() - } - .set_text( - CosmicText::OneStyle("馃榾馃榾馃榾 x => y".to_string()), - AttrsOwned::new(attrs), - &mut font_system.0, - ); + }; let cosmic_edit = commands.spawn(cosmic_edit).id(); diff --git a/examples/every_option.rs b/examples/every_option.rs new file mode 100644 index 0000000..83385a4 --- /dev/null +++ b/examples/every_option.rs @@ -0,0 +1,93 @@ +use bevy::{prelude::*, ui::FocusPolicy, window::PrimaryWindow}; +use bevy_cosmic_edit::{ + change_active_editor_sprite, change_active_editor_ui, ActiveEditor, CosmicAttrs, + CosmicBackground, CosmicEditPlugin, CosmicEditUiBundle, CosmicMaxChars, CosmicMaxLines, + CosmicMetrics, CosmicText, CosmicTextPosition, +}; +use cosmic_text::{Attrs, AttrsOwned}; + +#[derive(Resource)] +struct TextChangeTimer(pub Timer); + +fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) { + commands.spawn(Camera2dBundle::default()); + + let attrs = AttrsOwned::new(Attrs::new().color(cosmic_text::Color::rgb(69, 69, 69))); + let primary_window = windows.single(); + + let editor = commands + .spawn(CosmicEditUiBundle { + node: Node::default(), + button: Button, + visibility: Visibility::Visible, + computed_visibility: ComputedVisibility::default(), + z_index: ZIndex::default(), + image: UiImage::default(), + transform: Transform::default(), + interaction: Interaction::default(), + cosmic_edit_history: bevy_cosmic_edit::CosmicEditHistory::default(), + focus_policy: FocusPolicy::default(), + text_position: CosmicTextPosition::default(), + background_color: BackgroundColor::default(), + global_transform: GlobalTransform::default(), + background_image: CosmicBackground::default(), + border_color: Color::LIME_GREEN.into(), + style: Style { + // Size and position of text box + border: UiRect::all(Val::Px(4.)), + width: Val::Percent(20.), + height: Val::Px(50.), + left: Val::Percent(40.), + top: Val::Px(100.), + ..default() + }, + cosmic_attrs: CosmicAttrs(attrs.clone()), + cosmic_metrics: CosmicMetrics { + font_size: 16., + line_height: 16., + scale_factor: primary_window.scale_factor() as f32, + }, + max_chars: CosmicMaxChars(15), + max_lines: CosmicMaxLines(1), + set_text: CosmicText::OneStyle("BANANA IS THE CODEWORD!".into()), + }) + .id(); + + commands.insert_resource(ActiveEditor { + entity: Some(editor), + }); + + commands.insert_resource(TextChangeTimer(Timer::from_seconds( + 1., + TimerMode::Repeating, + ))); +} + +// Test for update_buffer_text +fn text_swapper( + mut timer: ResMut<TextChangeTimer>, + time: Res<Time>, + mut cosmic_q: Query<&mut CosmicText>, + mut count: Local<usize>, +) { + timer.0.tick(time.delta()); + if !timer.0.just_finished() { + return; + } + + *count += 1; + for mut text in cosmic_q.iter_mut() { + text.set_if_neq(CosmicText::OneStyle(format!("TIMER {}", *count))); + } +} + +fn main() { + App::new() + .add_plugins(DefaultPlugins) + .add_plugins(CosmicEditPlugin::default()) + .add_systems(Startup, setup) + .add_systems(Update, change_active_editor_ui) + .add_systems(Update, change_active_editor_sprite) + .add_systems(Update, text_swapper) + .run(); +} diff --git a/examples/font_per_widget.rs b/examples/font_per_widget.rs index c3580c5..73f2b48 100644 --- a/examples/font_per_widget.rs +++ b/examples/font_per_widget.rs @@ -5,15 +5,11 @@ use bevy_cosmic_edit::change_active_editor_sprite; use bevy_cosmic_edit::change_active_editor_ui; use bevy_cosmic_edit::{ ActiveEditor, CosmicAttrs, CosmicEditPlugin, CosmicEditUiBundle, CosmicFontConfig, - CosmicFontSystem, CosmicMetrics, CosmicText, CosmicTextPosition, + CosmicMetrics, CosmicText, CosmicTextPosition, }; use cosmic_text::{Attrs, AttrsOwned, Family}; -fn setup( - mut commands: Commands, - windows: Query<&Window, With<PrimaryWindow>>, - mut font_system: ResMut<CosmicFontSystem>, -) { +fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) { commands.spawn(Camera2dBundle::default()); let root = commands .spawn(NodeBundle { @@ -239,13 +235,9 @@ fn setup( ..default() }, background_color: BackgroundColor(Color::WHITE), + set_text: CosmicText::MultiStyle(lines), ..default() - } - .set_text( - CosmicText::MultiStyle(lines), - AttrsOwned::new(attrs), - &mut font_system.0, - ); + }; let mut attrs_2 = cosmic_text::Attrs::new(); attrs_2 = attrs_2.family(cosmic_text::Family::Name("Times New Roman")); @@ -265,13 +257,9 @@ fn setup( height: Val::Percent(100.), ..default() }, + set_text: CosmicText::OneStyle("Widget 2.\nClick on me =>".to_string()), ..default() - } - .set_text( - CosmicText::OneStyle("Widget 2.\nClick on me =>".to_string()), - AttrsOwned::new(attrs_2), - &mut font_system.0, - ); + }; let mut id = None; // Spawn the CosmicEditUiBundles as children of root diff --git a/examples/multiple_sprites.rs b/examples/multiple_sprites.rs index d71e6b5..32c10b5 100644 --- a/examples/multiple_sprites.rs +++ b/examples/multiple_sprites.rs @@ -3,15 +3,11 @@ use bevy_cosmic_edit::change_active_editor_sprite; use bevy_cosmic_edit::change_active_editor_ui; use bevy_cosmic_edit::{ ActiveEditor, CosmicAttrs, CosmicEditPlugin, CosmicEditSpriteBundle, CosmicFontConfig, - CosmicFontSystem, CosmicMetrics, CosmicText, CosmicTextPosition, + CosmicMetrics, CosmicText, CosmicTextPosition, }; use cosmic_text::AttrsOwned; -fn setup( - mut commands: Commands, - windows: Query<&Window, With<PrimaryWindow>>, - mut font_system: ResMut<CosmicFontSystem>, -) { +fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) { let primary_window = windows.single(); let camera_bundle = Camera2dBundle { camera_2d: Camera2d { @@ -43,13 +39,9 @@ fn setup( transform: Transform::from_translation(Vec3::new(-primary_window.width() / 4., 0., 1.)), text_position: CosmicTextPosition::Center, background_color: BackgroundColor(Color::ALICE_BLUE), + text: CosmicText::OneStyle("馃榾馃榾馃榾 x => y".to_string()), ..default() - } - .set_text( - CosmicText::OneStyle("馃榾馃榾馃榾 x => y".to_string()), - AttrsOwned::new(attrs), - &mut font_system.0, - ); + }; let cosmic_edit_2 = CosmicEditSpriteBundle { cosmic_attrs: CosmicAttrs(AttrsOwned::new(attrs)), @@ -68,13 +60,9 @@ fn setup( )), text_position: CosmicTextPosition::Center, background_color: BackgroundColor(Color::GRAY.with_a(0.5)), + text: CosmicText::OneStyle("Widget_2. Click on me".to_string()), ..default() - } - .set_text( - CosmicText::OneStyle("Widget_2. Click on me".to_string()), - AttrsOwned::new(attrs), - &mut font_system.0, - ); + }; let id = commands.spawn(cosmic_edit_1).id(); diff --git a/examples/readonly.rs b/examples/readonly.rs index 049d043..870b3b9 100644 --- a/examples/readonly.rs +++ b/examples/readonly.rs @@ -1,15 +1,11 @@ use bevy::{prelude::*, window::PrimaryWindow}; use bevy_cosmic_edit::{ ActiveEditor, CosmicAttrs, CosmicEditPlugin, CosmicEditUiBundle, CosmicFontConfig, - CosmicFontSystem, CosmicMetrics, CosmicText, CosmicTextPosition, ReadOnly, + CosmicMetrics, CosmicText, CosmicTextPosition, ReadOnly, }; use cosmic_text::AttrsOwned; -fn setup( - mut commands: Commands, - windows: Query<&Window, With<PrimaryWindow>>, - mut font_system: ResMut<CosmicFontSystem>, -) { +fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) { let primary_window = windows.single(); commands.spawn(Camera2dBundle::default()); let root = commands @@ -42,13 +38,9 @@ fn setup( line_height: 18., scale_factor: primary_window.scale_factor() as f32, }, + set_text: CosmicText::OneStyle("馃榾馃榾馃榾 x => y\nRead only widget".to_string()), ..default() - } - .set_text( - CosmicText::OneStyle("馃榾馃榾馃榾 x => y\nRead only widget".to_string()), - AttrsOwned::new(attrs), - &mut font_system.0, - ); + }; let mut id = None; // Spawn the CosmicEditUiBundle as a child of root diff --git a/examples/restricted_input.rs b/examples/restricted_input.rs index 01a1301..13b5e7c 100644 --- a/examples/restricted_input.rs +++ b/examples/restricted_input.rs @@ -1,53 +1,43 @@ use bevy::{prelude::*, window::PrimaryWindow}; use bevy_cosmic_edit::{ change_active_editor_sprite, change_active_editor_ui, ActiveEditor, CosmicAttrs, - CosmicEditPlugin, CosmicEditUiBundle, CosmicFontSystem, CosmicMaxChars, CosmicMaxLines, - CosmicMetrics, CosmicText, + CosmicEditPlugin, CosmicEditUiBundle, CosmicMaxChars, CosmicMaxLines, CosmicMetrics, + CosmicText, }; use cosmic_text::{Attrs, AttrsOwned}; -fn setup( - mut commands: Commands, - mut font_system: ResMut<CosmicFontSystem>, - windows: Query<&Window, With<PrimaryWindow>>, -) { +fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) { commands.spawn(Camera2dBundle::default()); let attrs = AttrsOwned::new(Attrs::new().color(cosmic_text::Color::rgb(69, 69, 69))); let primary_window = windows.single(); let editor = commands - .spawn( - CosmicEditUiBundle { - border_color: Color::LIME_GREEN.into(), - style: Style { - // Size and position of text box - border: UiRect::all(Val::Px(4.)), - width: Val::Percent(20.), - height: Val::Px(50.), - left: Val::Percent(40.), - top: Val::Px(100.), - ..default() - }, - cosmic_attrs: CosmicAttrs(attrs.clone()), - cosmic_metrics: CosmicMetrics { - font_size: 16., - line_height: 16., - scale_factor: primary_window.scale_factor() as f32, - }, - max_chars: CosmicMaxChars(15), - max_lines: CosmicMaxLines(1), + .spawn(CosmicEditUiBundle { + border_color: Color::LIME_GREEN.into(), + style: Style { + // Size and position of text box + border: UiRect::all(Val::Px(4.)), + width: Val::Percent(20.), + height: Val::Px(50.), + left: Val::Percent(40.), + top: Val::Px(100.), ..default() - } - .set_text( - CosmicText::OneStyle( - "1 line 15 chars! But this\n is longer\n than is\n allowed by\n the limits.\n" - .into(), - ), - attrs, - &mut font_system.0, + }, + cosmic_attrs: CosmicAttrs(attrs.clone()), + cosmic_metrics: CosmicMetrics { + font_size: 16., + line_height: 16., + scale_factor: primary_window.scale_factor() as f32, + }, + max_chars: CosmicMaxChars(15), + max_lines: CosmicMaxLines(1), + set_text: CosmicText::OneStyle( + "1 line 15 chars! But this\n is longer\n than is\n allowed by\n the limits.\n" + .into(), ), - ) + ..default() + }) .id(); commands.insert_resource(ActiveEditor { diff --git a/src/lib.rs b/src/lib.rs index 3c5dca7..4ffbc85 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,12 +19,18 @@ use cosmic_text::{ }; use image::{imageops::FilterType, GenericImageView}; -#[derive(Clone)] +#[derive(Clone, Component, PartialEq)] pub enum CosmicText { OneStyle(String), MultiStyle(Vec<Vec<(String, AttrsOwned)>>), } +impl Default for CosmicText { + fn default() -> Self { + Self::OneStyle(String::new()) + } +} + /// Enum representing the position of the cosmic text. #[derive(Clone, Component, Default)] pub enum CosmicTextPosition { @@ -60,20 +66,14 @@ pub struct ReadOnly; // tag component #[derive(Component)] pub struct CosmicEditor(pub Editor); -impl Default for CosmicEditor { - fn default() -> Self { - Self(Editor::new(Buffer::new_empty(Metrics::new(12., 14.)))) - } -} - impl CosmicEditor { - pub fn set_text( + fn set_text( &mut self, text: CosmicText, attrs: AttrsOwned, - // i'd like to get the font system + attrs automagically but i'm too 3head -bytemunch font_system: &mut FontSystem, ) -> &mut Self { + // TODO invoke trim_text here let editor = &mut self.0; editor.buffer_mut().lines.clear(); match text { @@ -136,39 +136,31 @@ impl CosmicEditor { fn cosmic_editor_builder( mut added_editors: Query< ( - &mut CosmicEditor, + Entity, + &mut CosmicText, &CosmicAttrs, &CosmicMetrics, + &CosmicMaxChars, + &CosmicMaxLines, Option<&ReadOnly>, Option<&Node>, Option<&Sprite>, ), - Added<CosmicEditor>, + Added<CosmicText>, >, mut font_system: ResMut<CosmicFontSystem>, + mut commands: Commands, ) { - for (mut editor, attrs, metrics, readonly, node, sprite) in added_editors.iter_mut() { - // keep old text if set - let mut text = editor.get_text(); - - if text.is_empty() { - text = "".into(); - editor.0.buffer_mut().set_text( - &mut font_system.0, - text.as_str(), - attrs.0.as_attrs(), - Shaping::Advanced, - ); - } - - editor.0.buffer_mut().set_metrics( + for (entity, text, attrs, metrics, max_chars, max_lines, readonly, node, sprite) in + added_editors.iter_mut() + { + let mut editor = Editor::new(Buffer::new( &mut font_system.0, Metrics::new(metrics.font_size, metrics.line_height).scale(metrics.scale_factor), - ); + )); if let Some(node) = node { editor - .0 .buffer_mut() .set_size(&mut font_system.0, node.size().x, node.size().y) } @@ -176,18 +168,45 @@ fn cosmic_editor_builder( if let Some(sprite) = sprite { if let Some(size) = sprite.custom_size { editor - .0 .buffer_mut() .set_size(&mut font_system.0, size.x, size.y) } } // hide cursor on readonly buffers - let mut cursor = editor.0.cursor(); + // TODO do this seperately, allow for readonly to be toggled + let mut cursor = editor.cursor(); if readonly.is_some() { cursor.color = Some(cosmic_text::Color::rgba(0, 0, 0, 0)); } - editor.0.set_cursor(cursor); + editor.set_cursor(cursor); + + let mut editor_component = CosmicEditor(editor); + + let text = trim_text(text.to_owned(), max_chars.0, max_lines.0); + editor_component.set_text(text, attrs.0.clone(), &mut font_system.0); + + commands.entity(entity).insert(editor_component); + } +} + +/// Updates editor buffer when text component changes +fn update_buffer_text( + mut editor_q: Query< + ( + &mut CosmicEditor, + &mut CosmicText, + &CosmicAttrs, + &CosmicMaxChars, + &CosmicMaxLines, + ), + Changed<CosmicText>, + >, + mut font_system: ResMut<CosmicFontSystem>, +) { + for (mut editor, text, attrs, max_chars, max_lines) in editor_q.iter_mut() { + let text = trim_text(text.to_owned(), max_chars.0, max_lines.0); + editor.set_text(text, attrs.0.clone(), &mut font_system.0); } } @@ -246,8 +265,6 @@ pub struct CosmicEditUiBundle { /// Indicates the depth at which the node should appear in the UI pub z_index: ZIndex, // cosmic bits - /// cosmic-text Editor, holds the text buffer + font system - pub editor: CosmicEditor, /// text positioning enum pub text_position: CosmicTextPosition, /// text metrics @@ -262,19 +279,9 @@ pub struct CosmicEditUiBundle { pub max_lines: CosmicMaxLines, /// How many characters are allowed in buffer, 0 for no limit pub max_chars: CosmicMaxChars, -} - -impl CosmicEditUiBundle { - pub fn set_text( - mut self, - text: CosmicText, - attrs: AttrsOwned, - font_system: &mut FontSystem, - ) -> Self { - let text = trim_text(text, self.max_chars.0, self.max_lines.0); - self.editor.set_text(text, attrs, font_system); - self - } + /// Setting this will update the buffer's text + // TODO sync this with the buffer to allow getting from here as well as setting + pub set_text: CosmicText, } fn trim_text(text: CosmicText, max_chars: usize, max_lines: usize) -> CosmicText { @@ -374,7 +381,6 @@ impl Default for CosmicEditUiBundle { visibility: Default::default(), computed_visibility: Default::default(), z_index: Default::default(), - editor: Default::default(), text_position: Default::default(), cosmic_metrics: Default::default(), cosmic_edit_history: Default::default(), @@ -382,6 +388,7 @@ impl Default for CosmicEditUiBundle { background_image: Default::default(), max_lines: Default::default(), max_chars: Default::default(), + set_text: Default::default(), } } } @@ -400,8 +407,6 @@ pub struct CosmicEditSpriteBundle { // pub background_color: BackgroundColor, // cosmic bits - /// cosmic-text Editor, holds the text buffer + font system - pub editor: CosmicEditor, /// text positioning enum pub text_position: CosmicTextPosition, /// text metrics @@ -416,19 +421,7 @@ pub struct CosmicEditSpriteBundle { pub max_lines: CosmicMaxLines, /// How many characters are allowed in buffer, 0 for no limit pub max_chars: CosmicMaxChars, -} - -impl CosmicEditSpriteBundle { - pub fn set_text( - mut self, - text: CosmicText, - attrs: AttrsOwned, - font_system: &mut FontSystem, - ) -> Self { - let text = trim_text(text, self.max_chars.0, self.max_lines.0); - self.editor.set_text(text, attrs, font_system); - self - } + pub text: CosmicText, } impl Default for CosmicEditSpriteBundle { @@ -441,7 +434,6 @@ impl Default for CosmicEditSpriteBundle { visibility: Visibility::Hidden, computed_visibility: Default::default(), background_color: Default::default(), - editor: Default::default(), text_position: Default::default(), cosmic_metrics: Default::default(), cosmic_edit_history: Default::default(), @@ -449,6 +441,7 @@ impl Default for CosmicEditSpriteBundle { background_image: Default::default(), max_lines: Default::default(), max_chars: Default::default(), + text: Default::default(), } } } @@ -475,7 +468,7 @@ impl Plugin for CosmicEditPlugin { fn build(&self, app: &mut App) { let font_system = create_cosmic_font_system(self.font_config.clone()); - app.add_systems(PreUpdate, cosmic_editor_builder) + app.add_systems(PreUpdate, (cosmic_editor_builder, update_buffer_text)) .add_systems( Update, ( @@ -1490,15 +1483,11 @@ fn draw_pixel( mod tests { use crate::*; - fn test_spawn_cosmic_edit_system( - mut commands: Commands, - mut font_system: ResMut<CosmicFontSystem>, - ) { - commands.spawn(CosmicEditUiBundle::default().set_text( - CosmicText::OneStyle("Blah".into()), - AttrsOwned::new(Attrs::new()), - &mut font_system.0, - )); + fn test_spawn_cosmic_edit_system(mut commands: Commands) { + commands.spawn(CosmicEditUiBundle { + set_text: CosmicText::OneStyle("Blah".into()), + ..Default::default() + }); } #[test] -- GitLab