penguin_app/
application.rs1use super::ecs::*;
2use anyhow::*;
3
4use winit::event::WindowEvent;
5use winit::event::{ElementState, Event, VirtualKeyCode};
6use winit::event_loop::{ControlFlow, EventLoop};
7
8use crate::config::AppConfig;
9
10
11pub struct App {
12 pub event_loop: Option<EventLoop<()>>,
13 world: World,
15 resources: Resources,
16 startup_schedule: Schedule,
18 run_schedule: Schedule,
19 shutdown_schedule: Schedule,
20}
21impl App {
22 pub fn builder(config: AppConfig) -> builder::AppBuilder {
23 builder::AppBuilder::builder(config)
24 }
25
26 pub fn run(mut self) -> Result<()> {
27 self.startup_schedule
28 .execute(&mut self.world, &mut self.resources);
29
30 let event_loop = self.event_loop.take().unwrap();
31 self.run_loop(event_loop)
32 }
33
34 pub fn run_loop(mut self, event_loop: EventLoop<()>) -> Result<()> {
35 event_loop.run(move |event, _, control_flow| {
36 let _ = &self;
37 *control_flow = ControlFlow::Poll;
38
39 match event {
40 Event::WindowEvent { event, .. } => match event {
42 WindowEvent::CloseRequested => {
43 log::info!("Close requested, closing...");
44 *control_flow = ControlFlow::Exit;
45 }
46 WindowEvent::KeyboardInput { input, .. } => {
47 match (input.virtual_keycode, input.state) {
48 (Some(VirtualKeyCode::Escape), ElementState::Pressed) => {
49 *control_flow = ControlFlow::Exit
50 }
51 _ => {
52 let input_events_resource =
53 self.resources.get_mut::<super::input::InputEvents>();
54 input_events_resource.unwrap().update(input);
55 }
56 }
57 }
58 _ => {}
59 },
60 Event::MainEventsCleared => {
62 self.run_schedule
63 .execute(&mut self.world, &mut self.resources);
64 }
65 Event::RedrawRequested(_window_id) => {}
66 Event::LoopDestroyed => {
67 self.shutdown_schedule
68 .execute(&mut self.world, &mut self.resources);
69 }
70 _ => (),
71 }
72 });
73 }
74}
75
76
77pub mod builder {
78 use super::*;
79 use super::super::window;
80 use super::super::input;
81 use super::super::logger;
82
83 use crate::config::AppConfig;
84
85 pub struct AppBuilder {
86 event_loop: EventLoop<()>,
87 world: World,
89 resources: Resources,
90 startup_steps: Vec<Step>,
91 run_steps: Vec<Step>,
92 shutdown_steps: Vec<Step>,
93 }
94
95 impl AppBuilder {
96 pub fn builder(config: AppConfig) -> Self {
97
98 logger::init_logger(config.logger_config.clone()).expect("Couldn't init logger");
99
100
101 let event_loop = winit::event_loop::EventLoop::new();
102
103 let mut resources = Resources::default();
104 resources.insert(window::Window::new(
105 &event_loop,
106 config.clone().window_config,
107 config.logger_config.debug_message_severity.clone()
108 ));
109 log::trace!("Window resource created");
110
111
112 let builder = Self {
113 event_loop,
114 world: World::default(),
115 resources,
116 startup_steps: Vec::new(),
117 run_steps: Vec::new(),
118 shutdown_steps: Vec::new(),
119 };
120
121 builder.add_plugin(input::InputPlugin)
122 }
123
124 pub fn add_startup_steps(mut self, steps: Vec<Step>) -> Self {
125 self.startup_steps.extend(steps.into_iter());
126 self
127 }
128
129 pub fn add_run_steps(mut self, steps: Vec<Step>) -> Self {
130 self.run_steps.extend(steps.into_iter());
131 self
132 }
133
134 pub fn add_shutdown_steps(mut self, steps: Vec<Step>) -> Self {
135 self.shutdown_steps.extend(steps.into_iter());
136 self
137 }
138
139 #[allow(unused)]
140 pub fn insert_resource<T: 'static>(mut self, resource: T) -> Self
141 {
142 self.resources.insert(resource);
143 self
144 }
145
146 pub fn add_plugin<T: Plugin>(mut self, mut plugin: T) -> Self {
147 let startup_steps = plugin.startup(&mut self.resources);
148 self = self.add_startup_steps(startup_steps);
149 self = self.add_run_steps(T::run());
150 self = self.add_shutdown_steps(T::shutdown());
151 self
152 }
153
154 pub fn run(self) -> Result<()> {
155 let startup_schedule = Schedule::from(self.startup_steps);
156 let run_schedule = Schedule::from(self.run_steps);
157 let shutdown_schedule = Schedule::from(self.shutdown_steps);
158
159 let app = super::App {
160 event_loop: Some(self.event_loop),
161 world: self.world,
162 resources: self.resources,
163
164 startup_schedule,
165 run_schedule,
166 shutdown_schedule,
167 };
168
169 app.run()
170 }
171
172 pub fn build(self) -> super::App {
173 let startup_schedule = Schedule::from(self.startup_steps);
174 let run_schedule = Schedule::from(self.run_steps);
175 let shutdown_schedule = Schedule::from(self.shutdown_steps);
176
177 super::App {
178 event_loop: Some(self.event_loop),
179 world: self.world,
180 resources: self.resources,
181
182 startup_schedule,
183 run_schedule,
184 shutdown_schedule,
185 }
186 }
187 }
188}