ltrender/draw_object_builder/
mod.rs1use std::time::Instant;
2
3use crate::{
4 DrawObject, DrawObjectKey, ScreenKey,
5 drawable_register::ObjectLifetime,
6 error::{AppError, DrawObjectBuilderError},
7 rendering::{render_handle::RenderHandle, renderer::RenderModeBehavior},
8 terminal_buffer::{Drawable, buffer_and_celldrawer::Shader},
9};
10pub mod sprite_drawable_builder;
11pub use sprite_drawable_builder::SpriteDrawableBuilder;
12pub mod circle_drawable_builder;
13pub use circle_drawable_builder::CircleDrawableBuilder;
14pub mod line_drawable_builder;
15pub use line_drawable_builder::LineDrawableBuilder;
16pub mod polygon_drawable_builder;
17pub use polygon_drawable_builder::PolygonDrawableBuilder;
18pub mod rect_drawable_builder;
19pub use rect_drawable_builder::RectDrawableBuilder;
20pub mod videostream_drawable_builder;
21pub use videostream_drawable_builder::VideoStreamDrawableBuilder;
22
23macro_rules! allow_drawable_building {
24 ($builder_name:ident, $fn_name:ident) => {
25 pub fn $fn_name<F>(mut self, build_fn: F) -> Result<Self, DrawObjectBuilderError>
26 where
27 F: FnOnce($builder_name) -> $builder_name,
28 {
29 let builder = build_fn($builder_name::new());
30 let drawable = builder.build()?;
31 self.drawable = Some(drawable);
32 Ok(self)
33 }
34 };
35}
36
37#[macro_export]
38macro_rules! handle_field {
39 ($fn_name:ident, $field_name:ident, $type:ty) => {
40 pub fn $fn_name(mut self, $field_name: $type) -> Self {
41 self.$field_name = Some($field_name);
42 self
43 }
44 };
45}
46
47#[macro_export]
48macro_rules! handle_pointed_field {
49 ($fn_name:ident, $field_name:ident) => {
50 pub fn $fn_name(mut self, $field_name: impl Into<Point<i32>>) -> Self {
51 let point = $field_name.into();
52 self.$field_name = Some(point);
53 self
54 }
55 };
56}
57
58#[macro_export]
59macro_rules! handle_char_field {
60 ($fn_name:ident, $field_name:ident) => {
61 pub fn $fn_name(mut self, $field_name: impl Into<TerminalChar>) -> Self {
62 let point = $field_name.into();
63 self.$field_name = Some(point);
64 self
65 }
66 };
67}
68
69#[derive(Default)]
70pub struct DrawObjectBuilder {
71 layer: Option<usize>,
72 shaders: Vec<Box<dyn Shader>>,
73 drawable: Option<Box<dyn Drawable>>,
74 screen_id: Option<ScreenKey>,
75 lt: Option<ObjectLifetime>,
76}
77
78impl DrawObjectBuilder {
79 handle_field!(layer, layer, usize);
80 handle_field!(screen, screen_id, usize);
81 handle_field!(add_lifetime, lt, ObjectLifetime);
82 pub fn shader<T>(mut self, shader: T) -> Self
83 where
84 T: Shader + 'static,
85 {
86 self.shaders.push(Box::new(shader));
87 self
88 }
89
90 pub fn drawable(mut self, drawable: Box<dyn Drawable>) -> Self {
91 self.drawable = Some(drawable);
92 self
93 }
94
95 allow_drawable_building!(SpriteDrawableBuilder, sprite_drawable);
96 allow_drawable_building!(CircleDrawableBuilder, circle_drawable);
97 allow_drawable_building!(LineDrawableBuilder, line_drawable);
98 allow_drawable_building!(PolygonDrawableBuilder, polygon_drawable);
99 allow_drawable_building!(RectDrawableBuilder, rect_drawable);
100 allow_drawable_building!(VideoStreamDrawableBuilder, videostream_drawable);
101
102 pub fn build<M>(
103 &mut self,
104 render_handle: &mut RenderHandle<M>,
105 ) -> Result<DrawObjectKey, AppError>
106 where
107 M: RenderModeBehavior,
108 {
109 let layer = self.layer.ok_or(DrawObjectBuilderError::NoLayerAdded())?;
110 let screen_id = self
111 .screen_id
112 .ok_or(DrawObjectBuilderError::NoScreenAdded())?;
113
114 let drawable = self
115 .drawable
116 .take()
117 .ok_or(DrawObjectBuilderError::NoDrawableAdded())?;
118
119 let lifetime = self.lt.ok_or(DrawObjectBuilderError::NoLifetimeAdded())?;
120
121 render_handle.register_drawable(
122 screen_id,
123 DrawObject {
124 lifetime,
125 layer,
126 drawable,
127 shaders: self.shaders.clone(),
128 creation_time: Instant::now(),
129 },
130 )
131 }
132}