1use crate::scene::node::constructor::NodeConstructor;
27use crate::{
28 core::{
29 algebra::{Point3, Vector2, Vector3},
30 color::Color,
31 math::{aabb::AxisAlignedBoundingBox, Rect, TriangleDefinition},
32 pool::Handle,
33 reflect::prelude::*,
34 type_traits::prelude::*,
35 uuid::{uuid, Uuid},
36 variable::InheritableVariable,
37 visitor::prelude::*,
38 },
39 material::{self, Material, MaterialResource},
40 renderer::{self, bundle::RenderContext},
41 scene::{
42 base::{Base, BaseBuilder},
43 graph::Graph,
44 mesh::buffer::{
45 VertexAttributeDataType, VertexAttributeDescriptor, VertexAttributeUsage, VertexTrait,
46 },
47 mesh::RenderPath,
48 node::{Node, NodeTrait, RdcControlFlow},
49 },
50};
51use bytemuck::{Pod, Zeroable};
52use fyrox_core::value_as_u8_slice;
53use fyrox_graph::constructor::ConstructorProvider;
54use fyrox_graph::BaseSceneGraph;
55use std::{
56 hash::{Hash, Hasher},
57 ops::{Deref, DerefMut},
58};
59
60#[derive(Copy, Clone, Debug, Default, Pod, Zeroable)]
62#[repr(C)] pub struct RectangleVertex {
64 pub position: Vector3<f32>,
66 pub tex_coord: Vector2<f32>,
68 pub color: Color,
70}
71
72impl VertexTrait for RectangleVertex {
73 fn layout() -> &'static [VertexAttributeDescriptor] {
74 &[
75 VertexAttributeDescriptor {
76 usage: VertexAttributeUsage::Position,
77 data_type: VertexAttributeDataType::F32,
78 size: 3,
79 divisor: 0,
80 shader_location: 0,
81 normalized: false,
82 },
83 VertexAttributeDescriptor {
84 usage: VertexAttributeUsage::TexCoord0,
85 data_type: VertexAttributeDataType::F32,
86 size: 2,
87 divisor: 0,
88 shader_location: 1,
89 normalized: false,
90 },
91 VertexAttributeDescriptor {
92 usage: VertexAttributeUsage::Color,
93 data_type: VertexAttributeDataType::U8,
94 size: 4,
95 divisor: 0,
96 shader_location: 2,
97 normalized: true,
98 },
99 ]
100 }
101}
102
103impl PartialEq for RectangleVertex {
104 fn eq(&self, other: &Self) -> bool {
105 self.position == other.position
106 && self.tex_coord == other.tex_coord
107 && self.color == other.color
108 }
109}
110
111impl Hash for RectangleVertex {
115 fn hash<H: Hasher>(&self, state: &mut H) {
116 #[allow(unsafe_code)]
117 unsafe {
118 let bytes = self as *const Self as *const u8;
119 state.write(std::slice::from_raw_parts(
120 bytes,
121 std::mem::size_of::<Self>(),
122 ))
123 }
124 }
125}
126
127#[derive(Reflect, Debug, Clone, ComponentProvider)]
168pub struct Rectangle {
169 base: Base,
170
171 #[reflect(setter = "set_color")]
172 color: InheritableVariable<Color>,
173
174 #[reflect(setter = "set_uv_rect")]
175 uv_rect: InheritableVariable<Rect<f32>>,
176
177 material: InheritableVariable<MaterialResource>,
178}
179
180impl Visit for Rectangle {
181 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
182 let mut region = visitor.enter_region(name)?;
183
184 if region.is_reading() {
185 if let Some(material) =
186 material::visit_old_texture_as_material(&mut region, Material::standard_2d)
187 {
188 self.material = material.into();
189 } else {
190 self.material.visit("Material", &mut region)?;
191 }
192 } else {
193 self.material.visit("Material", &mut region)?;
194 }
195
196 self.base.visit("Base", &mut region)?;
197 self.color.visit("Color", &mut region)?;
198 let _ = self.uv_rect.visit("UvRect", &mut region);
199
200 Ok(())
201 }
202}
203
204impl Default for Rectangle {
205 fn default() -> Self {
206 Self {
207 base: Default::default(),
208 color: Default::default(),
209 uv_rect: InheritableVariable::new_modified(Rect::new(0.0, 0.0, 1.0, 1.0)),
210 material: InheritableVariable::new_modified(MaterialResource::new_ok(
211 Default::default(),
212 Material::standard_2d(),
213 )),
214 }
215 }
216}
217
218impl Deref for Rectangle {
219 type Target = Base;
220
221 fn deref(&self) -> &Self::Target {
222 &self.base
223 }
224}
225
226impl DerefMut for Rectangle {
227 fn deref_mut(&mut self) -> &mut Self::Target {
228 &mut self.base
229 }
230}
231
232impl TypeUuidProvider for Rectangle {
233 fn type_uuid() -> Uuid {
234 uuid!("bb57b5e0-367a-4490-bf30-7f547407d5b5")
235 }
236}
237
238impl Rectangle {
239 pub fn color(&self) -> Color {
241 *self.color
242 }
243
244 pub fn material(&self) -> &InheritableVariable<MaterialResource> {
246 &self.material
247 }
248
249 pub fn material_mut(&mut self) -> &mut InheritableVariable<MaterialResource> {
251 &mut self.material
252 }
253
254 pub fn set_color(&mut self, color: Color) -> Color {
256 self.color.set_value_and_mark_modified(color)
257 }
258
259 pub fn uv_rect(&self) -> Rect<f32> {
263 *self.uv_rect
264 }
265
266 pub fn set_uv_rect(&mut self, uv_rect: Rect<f32>) -> Rect<f32> {
275 self.uv_rect.set_value_and_mark_modified(uv_rect)
276 }
277}
278
279impl ConstructorProvider<Node, Graph> for Rectangle {
280 fn constructor() -> NodeConstructor {
281 NodeConstructor::new::<Self>()
282 .with_variant("Rectangle (2D Sprite)", |_| {
283 RectangleBuilder::new(BaseBuilder::new().with_name("Sprite (2D)"))
284 .build_node()
285 .into()
286 })
287 .with_group("2D")
288 }
289}
290
291impl NodeTrait for Rectangle {
292 fn local_bounding_box(&self) -> AxisAlignedBoundingBox {
293 AxisAlignedBoundingBox::unit()
294 }
295
296 fn world_bounding_box(&self) -> AxisAlignedBoundingBox {
297 self.local_bounding_box()
298 .transform(&self.global_transform())
299 }
300
301 fn id(&self) -> Uuid {
302 Self::type_uuid()
303 }
304
305 fn collect_render_data(&self, ctx: &mut RenderContext) -> RdcControlFlow {
306 if !self.should_be_rendered(ctx.frustum) {
307 return RdcControlFlow::Continue;
308 }
309
310 if renderer::is_shadow_pass(ctx.render_pass_name) {
311 return RdcControlFlow::Continue;
312 }
313
314 let global_transform = self.global_transform();
315
316 type Vertex = RectangleVertex;
317
318 let vertices = [
319 Vertex {
320 position: global_transform
321 .transform_point(&Point3::new(-0.5, 0.5, 0.0))
322 .coords,
323 tex_coord: self.uv_rect.right_top_corner(),
324 color: *self.color,
325 },
326 Vertex {
327 position: global_transform
328 .transform_point(&Point3::new(0.5, 0.5, 0.0))
329 .coords,
330 tex_coord: self.uv_rect.left_top_corner(),
331 color: *self.color,
332 },
333 Vertex {
334 position: global_transform
335 .transform_point(&Point3::new(0.5, -0.5, 0.0))
336 .coords,
337 tex_coord: self.uv_rect.left_bottom_corner(),
338 color: *self.color,
339 },
340 Vertex {
341 position: global_transform
342 .transform_point(&Point3::new(-0.5, -0.5, 0.0))
343 .coords,
344 tex_coord: self.uv_rect.right_bottom_corner(),
345 color: *self.color,
346 },
347 ];
348
349 let triangles = [TriangleDefinition([0, 1, 2]), TriangleDefinition([2, 3, 0])];
350
351 let sort_index = ctx.calculate_sorting_index(self.global_position());
352
353 ctx.storage.push_triangles(
354 Vertex::layout(),
355 &self.material,
356 RenderPath::Forward,
357 sort_index,
358 self.handle(),
359 &mut move |mut vertex_buffer, mut triangle_buffer| {
360 let start_vertex_index = vertex_buffer.vertex_count();
361
362 for vertex in vertices.iter() {
363 vertex_buffer
364 .push_vertex_raw(value_as_u8_slice(vertex))
365 .unwrap();
366 }
367
368 triangle_buffer
369 .push_triangles_iter_with_offset(start_vertex_index, triangles.into_iter());
370 },
371 );
372
373 RdcControlFlow::Continue
374 }
375}
376
377pub struct RectangleBuilder {
379 base_builder: BaseBuilder,
380 color: Color,
381 uv_rect: Rect<f32>,
382 material: MaterialResource,
383}
384
385impl RectangleBuilder {
386 pub fn new(base_builder: BaseBuilder) -> Self {
388 Self {
389 base_builder,
390 color: Color::WHITE,
391 uv_rect: Rect::new(0.0, 0.0, 1.0, 1.0),
392 material: MaterialResource::new_ok(Default::default(), Material::standard_2d()),
393 }
394 }
395
396 pub fn with_color(mut self, color: Color) -> Self {
398 self.color = color;
399 self
400 }
401
402 pub fn with_uv_rect(mut self, uv_rect: Rect<f32>) -> Self {
405 self.uv_rect = uv_rect;
406 self
407 }
408
409 pub fn with_material(mut self, material: MaterialResource) -> Self {
411 self.material = material;
412 self
413 }
414
415 pub fn build_rectangle(self) -> Rectangle {
417 Rectangle {
418 base: self.base_builder.build_base(),
419 color: self.color.into(),
420 uv_rect: self.uv_rect.into(),
421 material: self.material.into(),
422 }
423 }
424
425 pub fn build_node(self) -> Node {
427 Node::new(self.build_rectangle())
428 }
429
430 pub fn build(self, graph: &mut Graph) -> Handle<Node> {
432 graph.add_node(self.build_node())
433 }
434}