diff --git a/crates/bevy_internal/src/default_plugins.rs b/crates/bevy_internal/src/default_plugins.rs index e416c8b17ad7d6..86214b3abde9be 100644 --- a/crates/bevy_internal/src/default_plugins.rs +++ b/crates/bevy_internal/src/default_plugins.rs @@ -41,6 +41,9 @@ impl PluginGroup for DefaultPlugins { #[cfg(feature = "bevy_winit")] group.add(bevy_winit::WinitPlugin::default()); + #[cfg(feature = "bevy_winit")] + group.add(bevy_winit::FileDragAndDropPlugin::default()); + #[cfg(feature = "bevy_wgpu")] group.add(bevy_wgpu::WgpuPlugin::default()); } diff --git a/crates/bevy_winit/src/drag_and_drop.rs b/crates/bevy_winit/src/drag_and_drop.rs new file mode 100644 index 00000000000000..cfec442efe4782 --- /dev/null +++ b/crates/bevy_winit/src/drag_and_drop.rs @@ -0,0 +1,71 @@ +use std::path::PathBuf; + +use bevy_app::prelude::*; + +use bevy_app::EventReader; +use bevy_ecs::{IntoSystem, Local, Res, ResMut}; +use bevy_window::{DroppedFile, HoveredFile, HoveredFileCancelled, WindowId}; + +type FilePath = (PathBuf, WindowId); +#[derive(Debug, Default)] +pub struct FileDragAndDrop { + hovered_files: Vec, + dropped_files: Vec, +} + +impl FileDragAndDrop { + pub fn drain(&mut self) -> std::vec::Drain<'_, FilePath> { + self.dropped_files.drain(0..) + } + + pub fn is_hovered(&self) -> bool { + !self.hovered_files.is_empty() + } +} + +#[derive(Default)] +struct DroppedFileSystemState { + dropped_filed_event_reader: EventReader, + hovered_file_event_reader: EventReader, + // hovered_file_canceled_event_reader: EventReader, +} + +// NOTE: in winit, each Dropped, Hovered, and Canceled are raised once for EACH file +fn drag_and_drop_system( + mut state: Local, + mut drag_and_drop: ResMut, + dropped_file_events: Res>, + hovered_file_events: Res>, + mut hovered_file_canceled_events: ResMut>, +) { + for dropped_file in state.dropped_filed_event_reader.iter(&dropped_file_events) { + let DroppedFile { id, path_buf } = dropped_file; + drag_and_drop.dropped_files.push((path_buf.clone(), *id)) + } + + for hovered_file in state.hovered_file_event_reader.iter(&hovered_file_events) { + let HoveredFile { id, path_buf } = hovered_file; + drag_and_drop.hovered_files.push((path_buf.clone(), *id)); + } + + // Since we only deal with one mouse, we can assume that a cancelled event + // means all hovered files are gone. + if hovered_file_canceled_events.drain().next().is_some() { + hovered_file_canceled_events.clear(); + drag_and_drop.hovered_files.clear(); + } +} + +#[derive(Default)] +pub struct FileDragAndDropPlugin {} + +impl Plugin for FileDragAndDropPlugin { + fn build(&self, app: &mut AppBuilder) { + app.init_resource::() + .add_system_to_stage(bevy_app::stage::EVENT, drag_and_drop_system.system()); + } + + fn name(&self) -> &str { + std::any::type_name::() + } +} diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index 1e7e0190cb2716..34747a03cdd222 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -1,6 +1,11 @@ mod converters; +mod drag_and_drop; mod winit_config; mod winit_windows; + +pub use drag_and_drop::FileDragAndDrop; +pub use drag_and_drop::FileDragAndDropPlugin; + use bevy_input::{ keyboard::KeyboardInput, mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel}, diff --git a/examples/app/drag_and_drop.rs b/examples/app/drag_and_drop.rs index f68fb78a5d52b4..1a8b6a5c64601a 100644 --- a/examples/app/drag_and_drop.rs +++ b/examples/app/drag_and_drop.rs @@ -1,11 +1,4 @@ -use bevy::prelude::*; - -#[derive(Default)] -struct DroppedFileSystemState { - dropped_filed_event_reader: EventReader, - hovered_file_event_reader: EventReader, - hovered_file_canceled_event_reader: EventReader, -} +use bevy::{prelude::*, winit::FileDragAndDrop}; fn main() { App::build() @@ -14,24 +7,8 @@ fn main() { .run(); } -fn dropped_file_system( - mut state: Local, - dropped_file_events: Res>, - hovered_file_events: Res>, - hovered_file_canceled_events: Res>, -) { - for event in state.dropped_filed_event_reader.iter(&dropped_file_events) { - println!("Dropped file{:?}", event); - } - - for event in state.hovered_file_event_reader.iter(&hovered_file_events) { - println!("Hovered file{:?}", event); - } - - for event in state - .hovered_file_canceled_event_reader - .iter(&hovered_file_canceled_events) - { - println!("Dropped file{:?}", event); +fn dropped_file_system(mut drag_and_drop: ResMut) { + for file in drag_and_drop.drain() { + println!("Dropped path {:?}", file); } }