1use anyhow::Result;
2use effect_core::{
3 id::{LayerID, TextureID},
4 primitives::vertex::Vertex,
5 raw::entityraw::Entity2DRaw,
6};
7use std::collections::{hash_map::Keys, HashMap};
8use winit::dpi::PhysicalSize;
9
10use crate::{
11 entity::entity2d::WebEntity2D,
12 texture::{texture2d::WebTexture2D, texture_atlas::WebTextureAtlas2D},
13};
14
15pub struct WebLayer2D {
18 id: LayerID,
19 textures: HashMap<TextureID, WebTexture2D>,
20 atlas: WebTextureAtlas2D,
21 vertex_buffer: wgpu::Buffer,
22 entity_count: usize,
23 entity_maximum: usize,
24 entity_buffer: Option<wgpu::Buffer>,
25 dimensions: winit::dpi::PhysicalSize<u32>,
26}
27
28impl WebLayer2D {
29 pub fn new(
30 id: LayerID,
31 dimensions: winit::dpi::PhysicalSize<u32>,
32 mut textures: Vec<WebTexture2D>,
33 device: &wgpu::Device,
34 queue: &wgpu::Queue,
35 bind_group_layout: &wgpu::BindGroupLayout,
36 texture_size: PhysicalSize<u32>,
37 pixel_art: bool,
38 ) -> Result<Self> {
39 let atlas = WebTextureAtlas2D::new(
40 &mut textures,
41 device,
42 queue,
43 bind_group_layout,
44 texture_size,
45 pixel_art,
46 )?;
47 let mut textures_layer = HashMap::new();
48 for texture in textures {
49 textures_layer.insert(texture.id().clone(), texture);
50 }
51 let entity_count = 0;
52 let entity_maximum = 0;
53 let vertex_buffer = WebLayer2DSystem::create_vertex_buffer(
54 texture_size,
55 atlas.tex_coord_size(),
56 device,
57 queue,
58 );
59 Ok(Self {
60 id,
61 textures: textures_layer,
62 atlas,
63 vertex_buffer,
64 entity_count,
65 entity_buffer: None,
66 entity_maximum,
67 dimensions,
68 })
69 }
70
71 pub fn tex_coord_size(&self) -> PhysicalSize<f32> {
72 self.atlas.tex_coord_size()
73 }
74
75 pub fn id(&self) -> LayerID {
76 self.id
77 }
78
79 pub fn contains_texture(&self, texture_id: &TextureID) -> bool {
80 self.textures.contains_key(texture_id)
81 }
82
83 pub fn texture_ids<'a>(&'a self) -> Keys<'a, TextureID, WebTexture2D> {
84 self.textures.keys()
85 }
86
87 pub fn vertex_buffer(&self) -> wgpu::BufferSlice {
88 self.vertex_buffer.slice(..)
89 }
90
91 pub fn entity_buffer(&self) -> Option<wgpu::BufferSlice> {
92 match self.entity_buffer.as_ref() {
93 Some(e_buf) => {
94 let length = self.entity_count * std::mem::size_of::<Entity2DRaw>();
95 Some(e_buf.slice(0..length as u64))
96 }
97 None => None,
98 }
99 }
100
101 pub fn index_count(&self) -> usize {
102 self.entity_count * 6
103 }
104
105 pub fn entity_count(&self) -> usize {
106 self.entity_count
107 }
108
109 pub fn entity_maximum(&self) -> usize {
110 self.entity_maximum
111 }
112
113 pub fn get_texture(&self, id: TextureID) -> Option<&WebTexture2D> {
114 self.textures.get(&id)
115 }
116
117 pub fn width(&self) -> u32 {
118 self.dimensions.width
119 }
120
121 pub fn height(&self) -> u32 {
122 self.dimensions.height
123 }
124
125 pub fn bind_group(&self) -> &wgpu::BindGroup {
126 self.atlas.bind_group()
127 }
128
129 pub fn atlas_dimensions(&self) -> PhysicalSize<u32> {
130 self.atlas.dimensions()
131 }
132}
133
134pub struct WebLayer2DSystem;
135
136impl WebLayer2DSystem {
137 fn alloc_buffer(
138 data: &[u8],
139 size: u64,
140 device: &wgpu::Device,
141 queue: &wgpu::Queue,
142 label: &str,
143 index: bool,
144 ) -> wgpu::Buffer {
145 let usage;
146 if index {
147 usage = wgpu::BufferUsages::INDEX;
148 } else {
149 usage = wgpu::BufferUsages::VERTEX;
150 }
151 let buffer = device.create_buffer(&wgpu::BufferDescriptor {
152 label: Some(label),
153 size,
154 usage: usage | wgpu::BufferUsages::COPY_DST,
155 mapped_at_creation: false,
156 });
157 queue.write_buffer(&buffer, 0, data);
158 buffer
159 }
160
161 fn create_entity_buffer(
163 entities: &[&WebEntity2D],
164 device: &wgpu::Device,
165 queue: &wgpu::Queue,
166 ) -> wgpu::Buffer {
167 let ents = entities.iter().map(|e| e.to_raw()).collect::<Vec<_>>();
168 let data: &[u8] = bytemuck::cast_slice(ents.as_slice());
169 let size = std::mem::size_of_val(data) as u64;
170 WebLayer2DSystem::alloc_buffer(data, size * 2, device, queue, "Entity Buffer", false)
171 }
172
173 fn _create_index_buffer(device: &wgpu::Device, queue: &wgpu::Queue) -> wgpu::Buffer {
174 let mut indices: Vec<u16> = Vec::new();
175 indices.extend_from_slice(&[0, 1, 2, 0, 2, 3]);
176 let data: &[u8] = bytemuck::cast_slice(&indices);
177 let size = (std::mem::size_of::<u16>() * 6) as u64;
178 WebLayer2DSystem::alloc_buffer(data, size, device, queue, "Index Buffer", true)
179 }
180
181 fn create_vertex_buffer(
182 _texture_size: PhysicalSize<u32>,
183 tex_coord_size: PhysicalSize<f32>,
184 device: &wgpu::Device,
185 queue: &wgpu::Queue,
186 ) -> wgpu::Buffer {
187 let width = 0.5;
189 let height = 0.5;
190 let verts = vec![
191 Vertex {
192 position: [width, height, 0.0],
193 tex_coords: [tex_coord_size.width, 0.0],
194 },
195 Vertex {
196 position: [-width, height, 0.0],
197 tex_coords: [0.0, 0.0],
198 },
199 Vertex {
200 position: [-width, -height, 0.0],
201 tex_coords: [0.0, tex_coord_size.height],
202 },
203 Vertex {
204 position: [width, -height, 0.0],
205 tex_coords: [tex_coord_size.width, tex_coord_size.height],
206 },
207 ];
208 let data: &[u8] = bytemuck::cast_slice(verts.as_slice());
209 let size = (std::mem::size_of::<Vertex>() * verts.len()) as u64;
210 WebLayer2DSystem::alloc_buffer(data, size, device, queue, "Vertex Buffer", false)
211 }
212
213 pub fn set_entities(
216 layer: &mut WebLayer2D,
217 entities: &[&WebEntity2D],
218 device: &wgpu::Device,
219 queue: &wgpu::Queue,
220 ) {
221 layer.entity_count = entities.len();
224
225 if layer.entity_count() > layer.entity_maximum() || layer.entity_buffer().is_none() {
226 layer.entity_buffer = Some(WebLayer2DSystem::create_entity_buffer(
228 &entities, device, queue,
229 ));
230 layer.entity_maximum = layer.entity_count * 2;
231 } else {
232 let ents = entities.iter().map(|e| e.to_raw()).collect::<Vec<_>>();
234 let entity_data: &[u8] = bytemuck::cast_slice(ents.as_slice());
235 queue.write_buffer(&layer.entity_buffer.as_ref().unwrap(), 0, entity_data);
236 }
237 }
238}