test_components/
test_components.rs

1use cgmath::Quaternion;
2use forte_engine::{component_app::EngineComponent, create_app, egui::EguiEngine, math::{quaternion::QuaternionExt, transforms::Transform}, primitives::{cameras::Camera, mesh::Mesh, textures::Texture, transforms::TransformRaw, vertices::Vertex}, render::pipelines::Pipeline, run_app, ui::{elements::UIElement, style::{Color, PositionSetting, Sizing, Style}, UIEngine}, utils::resources::Handle};
3
4const VERTICES: &[Vertex] = &[
5    Vertex { position: [ 0.5, -0.5, -0.5], tex_coords: [0.4131759, 0.00759614], normal: [0.0, 0.0, 0.0] },
6    Vertex { position: [ 0.5, -0.5,  0.5], tex_coords: [0.0048659444, 0.43041354], normal: [0.0, 0.0, 0.0] },
7    Vertex { position: [-0.5, -0.5,  0.5], tex_coords: [0.28081453, 0.949397], normal: [0.0, 0.0, 0.0] },
8    Vertex { position: [-0.5, -0.5, -0.5], tex_coords: [0.85967, 0.84732914], normal: [0.0, 0.0, 0.0] },
9    Vertex { position: [ 0.5,  0.5, -0.5], tex_coords: [0.9414737, 0.2652641], normal: [0.0, 0.0, 0.0] },
10    Vertex { position: [ 0.5,  0.5,  0.5], tex_coords: [0.28081453, 0.949397], normal: [0.0, 0.0, 0.0] },
11    Vertex { position: [-0.5,  0.5,  0.5], tex_coords: [0.85967, 0.84732914], normal: [0.0, 0.0, 0.0] },
12    Vertex { position: [-0.5,  0.5, -0.5], tex_coords: [0.9414737, 0.2652641], normal: [0.0, 0.0, 0.0] },
13];
14
15const INDICES: &[u16] = &[
16    1, 2, 3,
17    4, 7, 6,
18    4, 5, 1,
19    1, 5, 6,
20    6, 7, 3,
21    4, 0, 3,
22    0, 1, 3,
23    5, 4, 6,
24    0, 4, 1,
25    2, 1, 6,
26    2, 6, 3,
27    7, 4, 3
28];
29
30pub struct TestComponent {
31    mesh: Handle<Mesh>, 
32    texture: Handle<Texture>, 
33    camera: Camera,
34    instances: Vec<Transform>,
35    instance_buffer: wgpu::Buffer,
36    test: String
37}
38
39impl EngineComponent<(&mut RenderEngine, &mut UIEngine, &mut EguiEngine)> for TestComponent {
40
41    fn create(engine: &mut RenderEngine) -> Self { 
42        // generate camera
43        let mut camera = Camera::new(
44            &engine, 
45            engine.config.width as f32 / engine.config.height as f32,
46            45.0, 0.1, 100.0
47        );
48        camera.position = (0.0, 0.0, 5.0).into();
49        camera.update(engine);
50
51        // create instances
52        let instances = vec![Transform {
53            position: cgmath::Vector3 { x: 0.0, y: 0.0, z: 0.0 },
54            rotation: cgmath::Quaternion::euler_deg_z(0.0),
55            scale: (1.0, 1.0, 1.0).into()
56        }];
57
58        engine.verify_pipeline_exists("forte.test", |engine| {
59            Pipeline::new(
60                "std", &engine, include_str!("rotating_cube.wgsl"),
61                &[Vertex::desc(), TransformRaw::desc()],
62                &[
63                    &engine.device.create_bind_group_layout(&Camera::BIND_LAYOUT),
64                    &engine.device.create_bind_group_layout(&Texture::BIND_LAYOUT),
65                ],
66                true
67            )
68        });
69
70        Self {
71            instance_buffer: TransformRaw::buffer_from_generic(engine, &instances),
72            mesh: engine.create_mesh("test", VERTICES, INDICES),
73            texture: engine.create_texture("test", include_bytes!("rotating_cube.png")),
74            camera, instances,
75            test: "".to_string()
76        }
77    }
78
79    fn start(&mut self, (engine, ui, _): (&mut RenderEngine, &mut UIEngine, &mut EguiEngine)) {
80        let mut a = UIElement::container(
81            &engine, 
82            Style { 
83                width: Sizing::Px(200.0), 
84                height: Sizing::Px(200.0), 
85                color: Color { red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0 },
86                top: Sizing::Px(10.0),
87                left: Sizing::Px(10.0),
88                border: Sizing::Px(5.0),
89                round: Sizing::Px(15.0),
90                ..Default::default() 
91            }
92        );
93        a.children.push(UIElement::container(
94            &engine, 
95            Style {
96                width: Sizing::Px(100.0), 
97                height: Sizing::Px(100.0), 
98                position_setting: PositionSetting::Parent,
99                top: Sizing::Px(10.0),
100                left: Sizing::Px(10.0),
101                border: Sizing::Px(5.0),
102                round: Sizing::Px(10.0),
103                color: Color { red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0 },
104                ..Default::default() 
105            }
106        ));
107        ui.elements.push(a);
108    }
109
110    fn update(&mut self, (engine, _, egui): (&mut RenderEngine, &mut UIEngine, &mut EguiEngine)) {
111        // update rotation
112        TransformRaw::update_buffer_generic(
113            engine, &self.instance_buffer, 
114            &[Transform {
115                rotation: Quaternion::euler_deg(0.0, engine.time_since_start * 45.0, engine.time_since_start * 45.0),
116                ..Default::default()
117            }]
118        );
119        
120        // test window
121        egui::Window::new("Test")
122            .show(egui.context(), |ui| { 
123                ui.label("Hi from test window!");
124                ui.text_edit_singleline(&mut self.test); 
125                if ui.button("Search").clicked() {
126                    println!("Search for {}", self.test);
127                }
128            });
129    }
130    
131    fn render<'rpass>(&'rpass mut self, engine: &'rpass RenderEngine, pass: &mut wgpu::RenderPass<'rpass>) {
132        // draw
133        self.camera.bind(pass, engine, 0);
134        engine.draw_textured_mesh(pass, &self.mesh, &self.texture, &self.instance_buffer, self.instances.len() as u32);
135    }
136
137    fn exit(&mut self, _: (&mut RenderEngine, &mut UIEngine, &mut EguiEngine)) {}
138}
139
140create_app! {
141    CLEAR_COLOR = wgpu::Color { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
142
143    APP {
144        ui_engine: UIEngine[render_engine],
145        test: TestComponent[render_engine, ui_engine, egui],
146        egui: EguiEngine[render_engine, inputs]
147    },
148
149    PASSES {
150        0: {
151            PARTS: [
152                {
153                    PIPELINE: "forte.test",
154                    PREPARE: [],
155                    RENDER: test,
156                }
157            ],
158            DEPTH: true
159        },
160        1: {
161            PARTS: [
162                {
163                    PIPELINE: "forte.ui",
164                    PREPARE: [],
165                    RENDER: ui_engine,
166                },
167                {
168                    PIPELINE: "forte.ui",
169                    PREPARE: [],
170                    RENDER: egui,
171                }
172            ],
173            DEPTH: false
174        }
175    }
176}
177
178fn main() { pollster::block_on(run_app::<App>()) }