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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! Adds utility queries
//!
//! These are common queries and resources grouped up, so everything
//! done here can be replicated with a normal query. You may not
//! need or want to use them but for quick prototyping they are useful to
//! have and not pollute your systems with many and/or complex types.
//!
//! [PixelBuffers] is a [WorldQuery] intented for more than one pixel buffer.
//!
//! [QueryPixelBuffer] is a [SystemParam] that groups the [PixelBuffers] query and
//! the [image](Image) [assets](Assets) resource. It has some convenience methods
//! when working with a single pixel buffer.
//!
//! # Examples
//!
//! For many pixel buffers
//! ```
//! # use bevy::prelude::*;
//! # use bevy_pixel_buffer::prelude::*;
//! fn example_system(mut images: ResMut<Assets<Image>>, pixel_buffers: Query<PixelBuffers>) {
//!     for item in pixel_buffers.iter() {
//!         images.frame(item).per_pixel(|_, _| Pixel::random())
//!     }
//! }
//! # bevy::ecs::system::assert_is_system(example_system);
//! ```
//! Is equivalent to
//! ```
//! # use bevy::prelude::*;
//! # use bevy_pixel_buffer::prelude::*;
//! fn example_system(pixel_buffers: QueryPixelBuffer) {
//!     let (query, mut images) = pixel_buffers.split();
//!     for item in query.iter() {
//!         images.frame(item).per_pixel(|_, _| Pixel::random())
//!     }
//! }
//! # bevy::ecs::system::assert_is_system(example_system);
//! ```
//! ---
//! For a single pixel buffer
//!
//! ```
//! # use bevy::prelude::*;
//! # use bevy_pixel_buffer::prelude::*;
//! fn example_system(mut pb: QueryPixelBuffer) {
//!     pb.frame().per_pixel(|_, _| Pixel::random());
//! }
//! # bevy::ecs::system::assert_is_system(example_system);
//! ```

use std::ops::{Deref, DerefMut};

use bevy::{ecs::system::SystemParam, prelude::*};

use crate::{
    frame::{AsImageHandle, Frame, GetFrame},
    pixel_buffer::PixelBuffer,
};

// #[derive(WorldQuery)] generates structs without documentation, put them inside
// here to allow that
mod queries {
    use bevy::ecs::query::QueryData;

    use super::*;
    // cannot use #[cfg(feature = "egui")] inside the derive

    #[cfg(not(feature = "egui"))]
    /// Query to get the pixel buffers
    ///
    /// See [module documentation](crate::query).
    #[derive(QueryData)]
    #[query_data(mutable, derive(Debug))]
    pub struct PixelBuffers {
        /// [Entity] of the pixel buffer
        pub entity: Entity,
        /// [PixelBuffer] component
        pub pixel_buffer: &'static mut PixelBuffer,
        /// Image handle
        pub image_handle: &'static Handle<Image>,
    }

    #[cfg(feature = "egui")]
    /// Query to get the pixel buffers.
    ///
    /// See [module documentation](crate::query).
    #[derive(QueryData)]
    #[query_data(mutable, derive(Debug))]
    pub struct PixelBuffers {
        /// [Entity] of the pixel buffer
        pub entity: Entity,
        /// [PixelBuffer] component
        pub pixel_buffer: &'static mut PixelBuffer,
        /// Image handle
        pub image_handle: &'static Handle<Image>,
        /// [EguiTexture](crate::egui::EguiTexture) component.
        ///
        /// Only available with the `egui` feature.
        ///
        /// If the [PixelBufferEguiPlugin](crate::egui::PixelBufferEguiPlugin) is added
        /// it will always be [Some].
        pub egui_texture: Option<&'static crate::egui::EguiTexture>,
    }
}

pub use queries::*;

impl AsImageHandle for crate::query::PixelBuffersReadOnlyItem<'_> {
    fn as_image_handle(&self) -> &Handle<Image> {
        self.image_handle
    }
}

impl AsImageHandle for crate::query::PixelBuffersItem<'_> {
    fn as_image_handle(&self) -> &Handle<Image> {
        self.image_handle
    }
}

/// System parameter to use in systems
#[derive(SystemParam)]
pub struct QueryPixelBuffer<'w, 's> {
    pub(crate) query: Query<'w, 's, PixelBuffers>,
    pub(crate) images: ResMut<'w, Assets<Image>>,
}

impl<'w, 's> Deref for QueryPixelBuffer<'w, 's> {
    type Target = Query<'w, 's, PixelBuffers>;

    fn deref(&self) -> &Self::Target {
        &self.query
    }
}

impl<'w, 's> DerefMut for QueryPixelBuffer<'w, 's> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.query
    }
}

// Zheoni: Help, I can't make a way to iterate over Frame s... lifetimes
//   and so many other problems :(

impl<'w, 's> QueryPixelBuffer<'w, 's> {
    /// Get the image assets resource.
    pub fn images(&mut self) -> &mut Assets<Image> {
        &mut self.images
    }

    /// Gets the query and images resource
    pub fn split(self) -> (Query<'w, 's, PixelBuffers>, ResMut<'w, Assets<Image>>) {
        (self.query, self.images)
    }
}

impl<'w, 's> GetFrame for QueryPixelBuffer<'w, 's> {
    fn frame(&mut self) -> Frame<'_> {
        let image_handle = self.query.single().image_handle;
        Frame::extract(&mut self.images, image_handle)
    }
}