Skip to content
Snippets Groups Projects
Unverified Commit c7074a24 authored by sam's avatar sam Committed by GitHub
Browse files

text cursor hover example (#64)


* text cursor hover example

* move cursor modify fns to src

caveats:
 - only hides cursor when typing if cursor is in app window
 - only acts on primary window

* add config for cursor changes

cursor hide does not work on WASM

* Update src/cursor.rs

Co-authored-by: default avatarStaffEngineer <111751109+StaffEngineer@users.noreply.github.com>

* fix focus handling in cursor.rs

* Update src/lib.rs

Co-authored-by: default avatarStaffEngineer <111751109+StaffEngineer@users.noreply.github.com>

* add none | events | default options for cursor

* stop sprites sending hover events per frame

* commit missed example

---------

Co-authored-by: default avatarStaffEngineer <111751109+StaffEngineer@users.noreply.github.com>
parent 55afc689
No related branches found
No related tags found
No related merge requests found
......@@ -51,7 +51,10 @@ fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(CosmicEditPlugin { font_config })
.add_plugins(CosmicEditPlugin {
font_config,
..default()
})
.add_systems(Startup, setup)
.run();
}
......@@ -66,7 +66,10 @@ fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(CosmicEditPlugin { font_config })
.add_plugins(CosmicEditPlugin {
font_config,
..default()
})
.add_systems(Startup, setup)
.add_systems(Update, print_text)
.run();
......
......@@ -17,6 +17,7 @@ fn setup(mut commands: Commands) {
cosmic_attrs: CosmicAttrs(AttrsOwned::new(
Attrs::new().color(bevy_color_to_cosmic(Color::GREEN)),
)),
max_lines: CosmicMaxLines(1),
..default()
});
......@@ -92,12 +93,32 @@ fn change_active_editor_sprite(
}
}
fn ev_test(
mut evr_on: EventReader<TextHoverIn>,
mut evr_out: EventReader<TextHoverOut>,
mut evr_type: EventReader<CosmicTextChanged>,
) {
for _ev in evr_on.iter() {
println!("IN");
}
for _ev in evr_out.iter() {
println!("OUT");
}
for _ev in evr_type.iter() {
println!("TYPE");
}
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(CosmicEditPlugin::default())
.add_plugins(CosmicEditPlugin {
change_cursor: CursorConfig::Default,
..default()
})
.add_systems(Startup, setup)
.add_systems(Update, change_active_editor_ui)
.add_systems(Update, change_active_editor_sprite)
.add_systems(Update, ev_test)
.run();
}
......@@ -293,7 +293,10 @@ fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(CosmicEditPlugin { font_config })
.add_plugins(CosmicEditPlugin {
font_config,
..default()
})
.add_systems(Startup, setup)
.add_systems(Update, change_active_editor_ui)
.run();
......
......@@ -114,7 +114,10 @@ fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(CosmicEditPlugin { font_config })
.add_plugins(CosmicEditPlugin {
font_config,
..default()
})
.add_systems(Startup, setup)
.add_systems(Update, change_active_editor_sprite)
.run();
......
......@@ -66,7 +66,10 @@ fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(CosmicEditPlugin { font_config })
.add_plugins(CosmicEditPlugin {
font_config,
..default()
})
.add_systems(Startup, setup)
.run();
}
use bevy::{input::mouse::MouseMotion, prelude::*, window::PrimaryWindow};
use crate::{CosmicEditor, CosmicTextChanged, ReadOnly};
/// For use with custom cursor control; Event is emitted when cursor enters a text widget
#[derive(Event)]
pub struct TextHoverIn;
/// For use with custom cursor control; Event is emitted when cursor leaves a text widget
#[derive(Event)]
pub struct TextHoverOut;
pub fn change_cursor(
evr_hover_in: EventReader<TextHoverIn>,
evr_hover_out: EventReader<TextHoverOut>,
evr_text_changed: EventReader<CosmicTextChanged>,
evr_mouse_motion: EventReader<MouseMotion>,
mouse_buttons: Res<Input<MouseButton>>,
mut windows: Query<&mut Window, With<PrimaryWindow>>,
) {
let mut window = windows.single_mut();
if !evr_hover_in.is_empty() {
window.cursor.icon = CursorIcon::Text;
}
if !evr_hover_out.is_empty() {
window.cursor.icon = CursorIcon::Default;
}
if !evr_text_changed.is_empty() {
window.cursor.visible = false;
}
if mouse_buttons.get_just_pressed().len() != 0 || !evr_mouse_motion.is_empty() {
window.cursor.visible = true;
}
}
// TODO: Only emit events; If configured to, have a fn to act on the events
pub fn hover_sprites(
windows: Query<&Window, With<PrimaryWindow>>,
mut cosmic_edit_query: Query<
(&mut Sprite, &GlobalTransform),
(With<CosmicEditor>, Without<ReadOnly>),
>,
camera_q: Query<(&Camera, &GlobalTransform)>,
mut hovered: Local<bool>,
mut last_hovered: Local<bool>,
mut evw_hover_in: EventWriter<TextHoverIn>,
mut evw_hover_out: EventWriter<TextHoverOut>,
) {
*hovered = false;
let window = windows.single();
let (camera, camera_transform) = camera_q.single();
for (sprite, node_transform) in &mut cosmic_edit_query.iter_mut() {
let size = sprite.custom_size.unwrap_or(Vec2::new(1., 1.));
let x_min = node_transform.affine().translation.x - size.x / 2.;
let y_min = node_transform.affine().translation.y - size.y / 2.;
let x_max = node_transform.affine().translation.x + size.x / 2.;
let y_max = node_transform.affine().translation.y + size.y / 2.;
if let Some(pos) = window.cursor_position() {
if let Some(pos) = camera.viewport_to_world_2d(camera_transform, pos) {
if x_min < pos.x && pos.x < x_max && y_min < pos.y && pos.y < y_max {
*hovered = true;
}
}
}
}
if *last_hovered != *hovered {
if *hovered {
evw_hover_in.send(TextHoverIn);
} else {
evw_hover_out.send(TextHoverOut);
}
}
*last_hovered = *hovered;
}
pub fn hover_ui(
mut interaction_query: Query<
&Interaction,
(
Changed<Interaction>,
(With<CosmicEditor>, Without<ReadOnly>),
),
>,
mut evw_hover_in: EventWriter<TextHoverIn>,
mut evw_hover_out: EventWriter<TextHoverOut>,
) {
for interaction in interaction_query.iter_mut() {
match interaction {
Interaction::None => {
evw_hover_out.send(TextHoverOut);
}
Interaction::Hovered => {
evw_hover_in.send(TextHoverIn);
}
_ => {}
}
}
}
#![allow(clippy::type_complexity)]
mod cursor;
use std::{collections::VecDeque, path::PathBuf, time::Duration};
use bevy::{
......@@ -18,6 +20,8 @@ pub use cosmic_text::{
use cosmic_text::{
Affinity, AttrsList, Buffer, BufferLine, Editor, FontSystem, Metrics, Shaping, SwashCache,
};
use cursor::{change_cursor, hover_sprites, hover_ui};
pub use cursor::{TextHoverIn, TextHoverOut};
use image::{imageops::FilterType, GenericImageView};
#[derive(Clone, Component, PartialEq, Debug)]
......@@ -369,10 +373,19 @@ pub struct CosmicEditHistory {
pub current_edit: usize,
}
#[derive(Default)]
pub enum CursorConfig {
#[default]
Default,
Events,
None,
}
/// Plugin struct that adds systems and initializes resources related to cosmic edit functionality.
#[derive(Default)]
pub struct CosmicEditPlugin {
pub font_config: CosmicFontConfig,
pub change_cursor: CursorConfig,
}
impl Plugin for CosmicEditPlugin {
......@@ -408,6 +421,20 @@ impl Plugin for CosmicEditPlugin {
})
.insert_resource(CosmicFontSystem(font_system))
.add_event::<CosmicTextChanged>();
match self.change_cursor {
CursorConfig::Default => {
app.add_systems(Update, (hover_sprites, hover_ui, change_cursor))
.add_event::<TextHoverIn>()
.add_event::<TextHoverOut>();
}
CursorConfig::Events => {
app.add_systems(Update, (hover_sprites, hover_ui))
.add_event::<TextHoverIn>()
.add_event::<TextHoverOut>();
}
CursorConfig::None => {}
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment