Skip to content
Snippets Groups Projects
window.rs 1.58 KiB
Newer Older
Louis's avatar
Louis committed
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;

use crate::system::camera::GameCamera;

/// A struct that provides several convenience methods for getting mouse and
/// window related information
#[derive(SystemParam)]
pub struct WindowManager<'w, 's> {
	mouse: Res<'w, Input<MouseButton>>,
	windows: Res<'w, Windows>,
	cam_query: ParamSet<'w, 's, (Query<'w, 's, &'static Transform, With<GameCamera>>,)>,
}

impl<'w, 's> WindowManager<'w, 's> {
	/// Conditionally run a function with the primary window. The function will not
	/// run if the primary window does not exist - typically this is the desired behaviour.
	///
	/// ## Arguments
	/// - `func`: an `FnOnce` callback that is given a [`bevy::prelude::Window`]
	pub fn with_primary_window<Func: FnOnce(&Window)>(&self, func: Func) {
		match self.windows.get_primary() {
			Some(window) => func(window),
			None => {}
		}
	}
	pub fn get_primary_window(&self) -> Option<&Window> {
		self.windows.get_primary()
	}
	pub fn get_mouse_press(&mut self) -> Option<Vec2> {
		if self.mouse.just_pressed(MouseButton::Left) {
			if let Some(window) = self.windows.get_primary() {
				if let Some(position) = window.cursor_position() {
					let window_size = Vec2::new(window.width() as f32, window.height() as f32);
					let adjusted_position = position - window_size / 2.0;
					if let Ok(camera_transform) = self.cam_query.p0().get_single() {
						let world_position = camera_transform.compute_matrix()
							* adjusted_position.extend(0.0).extend(1.0);

						return Some(Vec2::new(world_position.x, world_position.y));
					}
				}
			}
		}
		None
	}
}