1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
//! `amethyst` rendering ecs resources use amethyst_assets::{PrefabData, PrefabError}; use amethyst_core::specs::{Entity, Write}; use smallvec::SmallVec; use winit::Window; use color::Rgba; /// The ambient color of a scene #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct AmbientColor(pub Rgba); impl AsRef<Rgba> for AmbientColor { fn as_ref(&self) -> &Rgba { &self.0 } } impl<'a> PrefabData<'a> for AmbientColor { type SystemData = Write<'a, AmbientColor>; type Result = (); fn load_prefab( &self, _: Entity, ambient: &mut Self::SystemData, _: &[Entity], ) -> Result<(), PrefabError> { ambient.0 = self.0.clone(); Ok(()) } } /// This specs resource with id 0 permits sending commands to the /// renderer internal window. #[derive(Default)] pub struct WindowMessages { // It's unlikely we'll get more than one command per frame // 1 Box also makes this the same size as a Vec, so this costs // no more space in the structure than a Vec would. // // NOTE TO FUTURE AUTHORS: This could be an FnOnce but that's not possible // right now as of 2017-10-02 because FnOnce isn't object safe. It might // be possible as soon as FnBox stabilizes. For now I'll use FnMut instead. pub(crate) queue: SmallVec<[Box<FnMut(&Window) + Send + Sync + 'static>; 2]>, } impl WindowMessages { /// Create a new `WindowMessages` pub fn new() -> Self { Default::default() } /// Execute this closure on the `winit::Window` next frame. pub fn send_command<F>(&mut self, command: F) where F: FnMut(&Window) + Send + Sync + 'static, { self.queue.push(Box::new(command)); } } /// World resource that stores screen dimensions. #[derive(Debug)] pub struct ScreenDimensions { /// Screen width in pixels (px). w: f32, /// Screen height in pixels (px). h: f32, /// Width divided by height. aspect_ratio: f32, /// The ratio between the backing framebuffer resolution and the window size in screen pixels. /// This is typically one for a normal display and two for a retina display. hidpi: f32, pub(crate) dirty: bool, } impl ScreenDimensions { /// Creates a new screen dimensions object with the given width and height. pub fn new(w: u32, h: u32, hidpi: f32) -> ScreenDimensions { ScreenDimensions { w: w as f32, h: h as f32, aspect_ratio: w as f32 / h as f32, hidpi, dirty: false, } } /// Returns the current width of the window. /// /// This is returned as a float for user convenience, as this is typically used with other /// float values. This will only ever be a non-negative integer though. pub fn width(&self) -> f32 { self.w } /// Returns the current height of the window. /// /// This is returned as a float for user convenience, as this is typically used with other /// float values. This will only ever be a non-negative integer though. pub fn height(&self) -> f32 { self.h } /// Returns the current aspect ratio of the window. pub fn aspect_ratio(&self) -> f32 { self.aspect_ratio } /// Returns the ratio between the backing framebuffer resolution and the window size in screen pixels. /// This is typically one for a normal display and two for a retina display. pub fn hidpi_factor(&self) -> f32 { self.hidpi } /// Updates the width and height of the screen and recomputes the aspect /// ratio. /// /// Only use this if you need to programmatically set the resolution of your game. /// This resource is updated automatically by the engine when a resize occurs so you don't need /// this unless you want to resize the game window. pub fn update(&mut self, w: u32, h: u32) { self.w = w as f32; self.h = h as f32; self.aspect_ratio = w as f32 / h as f32; self.dirty = true; } }