1use std::any::Any;
2use std::collections::HashMap;
3use std::sync::{Arc, Mutex};
4use std::time::{Duration, Instant};
5use egui_glium::EguiGlium;
6use winit::window::Window;
7use glium::glutin::surface::WindowSurface;
8use glium::{Display, Surface, Texture2d, uniform};
9use glium::uniforms::UniformBuffer;
10use serde::{Deserialize, Serialize};
11use uuid::Uuid;
12use winit::event::{Event, WindowEvent};
13use winit::event_loop::{ControlFlow};
14use crate::camera::{Camera, CameraSerializer};
15use crate::collision_world::MouseState;
16use crate::data::AppStateData;
17use crate::event::EventModifiers;
18use crate::geometry::BoneTransforms;
19use crate::light::{Light, LightEmissionType};
20use crate::logging::{EnigmaError, EnigmaMessage, EnigmaWarning};
21use crate::material::Material;
22use crate::object::{Object, ObjectInstance};
23use crate::postprocessing::PostProcessingEffect;
24use crate::texture::Texture;
25
26pub mod shader;
27pub mod geometry;
28pub mod debug_geo;
29pub mod texture;
30pub mod material;
31pub mod object;
32pub mod light;
33pub mod camera;
34pub mod event;
35pub mod collision_world;
36pub mod default_events;
37pub mod postprocessing;
38pub mod ui;
39pub mod resources;
40pub mod data;
41pub mod example_resources;
42pub mod animation;
43pub mod logging;
44
45pub fn init_default(app_state: &mut AppState) {
46 app_state.set_renderscale(1);
47 app_state.set_fps(60);
48 app_state.set_max_buffers(3);
49
50 if app_state.get_camera().is_none(){
51 app_state.set_camera(Camera::default());
52 }
53
54 app_state.inject_event(
55 event::EventCharacteristic::MousePress(event::MouseButton::Left),
56 Arc::new(default_events::select_object),
57 None,
58 );
59 app_state.inject_event(
60 event::EventCharacteristic::MousePress(event::MouseButton::Right),
61 Arc::new(default_events::select_object_add),
62 None,
63 );
64
65 app_state.add_state_data("camera_move_speed", Box::new(10.0f32));
69 app_state.add_state_data("camera_rotate_speed", Box::new(2.0f32));
70
71 app_state.inject_event(
72 event::EventCharacteristic::KeyPress(event::VirtualKeyCode::W),
73 Arc::new(default_events::camera_fly_forward),
74 Some(EventModifiers::new(false, false, false)),
75 );
76 app_state.inject_event(
77 event::EventCharacteristic::KeyPress(event::VirtualKeyCode::A),
78 Arc::new(default_events::camera_fly_left),
79 Some(EventModifiers::new(false, false, false)),
80 );
81 app_state.inject_event(
82 event::EventCharacteristic::KeyPress(event::VirtualKeyCode::S),
83 Arc::new(default_events::camera_fly_backward),
84 Some(EventModifiers::new(false, false, false)),
85 );
86 app_state.inject_event(
87 event::EventCharacteristic::KeyPress(event::VirtualKeyCode::D),
88 Arc::new(default_events::camera_fly_right),
89 Some(EventModifiers::new(false, false, false)),
90 );
91 app_state.inject_event(
92 event::EventCharacteristic::KeyPress(event::VirtualKeyCode::Space),
93 Arc::new(default_events::camera_up),
94 Some(EventModifiers::new(false, false, false)),
95 );
96 app_state.inject_event(
97 event::EventCharacteristic::KeyPress(event::VirtualKeyCode::Space),
98 Arc::new(default_events::camera_down),
99 Some(EventModifiers::new(true, false, false)),
100 );
101 app_state.inject_event(
102 event::EventCharacteristic::MouseDown(event::MouseButton::Right),
103 Arc::new(default_events::camera_rotate),
104 Some(EventModifiers::new(true, false, false)),
105 );
106}
107
108#[derive(Serialize, Deserialize)]
109pub struct AppStateSerializer {
110 pub camera: Option<CameraSerializer>,
111 pub light: Vec<light::LightSerializer>,
112 pub ambient_light: Option<light::LightSerializer>,
113 pub skybox: Option<object::ObjectSerializer>,
114 pub materials: Vec<material::MaterialSerializer>,
115 pub skybox_texture: Option<texture::TextureSerializer>,
116 pub objects: Vec<object::ObjectSerializer>,
117 pub object_selection: Vec<String>,
118}
119
120pub struct AppState {
121 pub fps: u64,
122 pub camera: Option<camera::Camera>,
123 pub light: Vec<light::Light>,
124 pub ambient_light: Option<light::Light>,
125 pub skybox: Option<object::Object>,
126 pub skybox_texture: Option<texture::Texture>,
127 pub objects: Vec<object::Object>,
128 pub materials: Vec<material::Material>,
129 pub object_selection: Vec<Uuid>,
130 pub event_injections: Vec<(event::EventCharacteristic, event::EventFunction, event::EventModifiers)>,
131 pub update_injections: Vec<event::EventFunction>,
132 pub gui_injections: Vec<ui::GUIDrawFunction>,
133 pub post_processes: Vec<Box<dyn PostProcessingEffect>>,
134 pub display: Option<glium::Display<WindowSurface>>,
135 pub time: f32,
136 pub delta_time: f32,
137 pub render_scale: u32,
138 pub max_buffers: usize,
139 mouse_state: MouseState,
140 last_event_time: Instant,
141 last_frame_time: Instant,
142 is_mouse_down: bool,
143 pub state_data: Vec<AppStateData>,
144}
145
146pub struct EventLoop {
147 pub event_loop: winit::event_loop::EventLoop<()>,
148 pub window: Window,
149 pub display: Display<WindowSurface>,
150 pub modifiers: EventModifiers,
151 gui_renderer: Option<EguiGlium>,
152}
153
154impl AppState {
155 pub fn new() -> Self {
156 AppState {
157 fps: 60,
158 camera: None,
159 skybox: None,
160 skybox_texture: None,
161 objects: Vec::new(),
162 materials: Vec::new(),
163 object_selection: Vec::new(),
164 light: Vec::new(),
165 ambient_light: None,
166 event_injections: Vec::new(),
167 update_injections: Vec::new(),
168 post_processes: Vec::new(),
169 display: None,
170 time: 0.0,
171 delta_time: 0.0,
172 render_scale: 1,
173 max_buffers: 3,
174 mouse_state: MouseState::new(),
175 gui_injections: Vec::new(),
176 state_data: Vec::new(),
177 last_event_time: Instant::now(),
178 last_frame_time: Instant::now(),
179 is_mouse_down: false,
180 }
181 }
182
183 fn setup_skybox_instance(&self, display: &Display<WindowSurface>, sky_box_matrix: &Option<[[f32; 4]; 4]>) -> Option<(Uuid, object::ObjectInstance)> {
184 match &self.skybox {
185 Some(skybox) => {
186 let mut instance = ObjectInstance::new(display);
187 let model_matrix = sky_box_matrix.unwrap_or_else(|| {
188 [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
189 });
190 instance.set_vertex_buffers(skybox.get_vertex_buffers(display));
191 instance.set_index_buffers(skybox.get_index_buffers(display));
192 instance.instance_matrices.push(model_matrix);
193 let data = instance.instance_matrices
194 .iter()
195 .map(|i| geometry::InstanceAttribute {
196 model_matrix: *i,
197 })
198 .collect::<Vec<_>>();
199 instance.instance_attributes = glium::vertex::VertexBuffer::dynamic(display, &data).unwrap();
200 Some((skybox.get_unique_id(), instance))
201 }
202 None => None
203 }
204 }
205
206 fn setup_instances(&mut self, display: &Display<WindowSurface>, model_matrices: &HashMap<Uuid, [[f32; 4]; 4]>) -> HashMap<Uuid, object::ObjectInstance> {
207 let mut instances = HashMap::new();
208 self.objects.sort_by(|a, b| {
210 let distance_a = (self.camera.expect("failed to retrieve camera").transform.get_position() - a.transform.get_position()).len();
211 let distance_b = (self.camera.expect("failed to retrieve camera").transform.get_position() - b.transform.get_position()).len();
212 distance_b.partial_cmp(&distance_a).unwrap()
213 });
214
215 for object in self.objects.iter() {
217 let instance_id = object.get_instance_id();
218 let model_matrix = model_matrices.get(&object.get_unique_id()).unwrap_or_else(|| {
219 &[[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
220 });
221 if !instances.contains_key(&instance_id) {
222 let mut object_instance = ObjectInstance::new(display);
223 object_instance.set_vertex_buffers(object.get_vertex_buffers(display));
224 object_instance.set_index_buffers(object.get_index_buffers(display));
225 instances.insert(instance_id, object_instance);
226 }
227 instances.get_mut(&instance_id).expect("No instance of this uuid found. which is weird, because we just added it above").add_instance(*model_matrix);
228
229
230 match instances.get_mut(&instance_id) {
232 Some(instance) => {
233 let data = instance.instance_matrices
234 .iter()
235 .map(|i| geometry::InstanceAttribute {
236 model_matrix: *i,
237 })
238 .collect::<Vec<_>>();
239 instance.instance_attributes = glium::vertex::VertexBuffer::dynamic(display, &data).unwrap();
240 }
241 None => panic!("Something went wrong, when adding the instance")
242 }
243 }
244 instances
245 }
246
247 pub fn to_serializer(&self) -> AppStateSerializer {
248 EnigmaMessage::new(Some("An AppState Serializer does not completely serialize the AppState but only scene objects like Objects, Camera, Lights. It does NOT serialize any injections like code in form of functions or GUI!"), true).log();
249 let camera = match self.camera {
250 Some(camera) => Some(camera.to_serializer()),
251 None => None,
252 };
253 let light = self.light.iter().map(|l| l.to_serializer()).collect();
254 let ambient_light = match &self.ambient_light {
255 Some(light) => Some(light.to_serializer()),
256 None => None,
257 };
258 let skybox = match &self.skybox {
259 Some(skybox) => Some(skybox.to_serializer()),
260 None => None,
261 };
262 let skybox_texture = match &self.skybox_texture {
263 Some(texture) => Some(texture.to_serializer()),
264 None => None,
265 };
266 let objects = self.objects.iter().map(|o| o.to_serializer()).collect();
267 let materials = self.materials.iter().map(|o| o.to_serializer()).collect();
268 let object_selection = self.object_selection.iter().map(|o| o.to_string()).collect();
269 AppStateSerializer {
270 camera,
271 light,
272 ambient_light,
273 skybox,
274 skybox_texture,
275 objects,
276 materials,
277 object_selection,
278 }
279 }
280
281 pub fn inject_serializer(&mut self, serializer: AppStateSerializer, display: Display<WindowSurface>, additive: bool) {
282 self.camera = match serializer.camera {
283 Some(camera) => Some(Camera::from_serializer(camera)),
284 None => None,
285 };
286 match serializer.ambient_light {
287 Some(light) => {
288 self.add_light(Light::from_serializer(light), LightEmissionType::Ambient);
289 }
290 None => {}
291 };
292 self.skybox = match serializer.skybox {
293 Some(skybox) => Some(Object::from_serializer(skybox)),
294 None => None,
295 };
296 self.skybox_texture = match serializer.skybox_texture {
297 Some(texture) => Some(Texture::from_serializer(texture, &display)),
298 None => None,
299 };
300
301 if !additive {
302 self.light.clear();
303 self.objects.clear();
304 self.object_selection.clear();
305 }
306 for l in serializer.light {
307 self.add_light(Light::from_serializer(l), LightEmissionType::Source);
308 }
309 for o in serializer.objects {
310 self.add_object(Object::from_serializer(o));
311 }
312 for m in serializer.materials {
313 self.add_material(Material::from_serializer(m, &display));
314 }
315 for o in serializer.object_selection {
316 self.object_selection.push(Uuid::parse_str(&o).unwrap());
317 }
318 }
319
320 pub fn add_state_data(&mut self, name: &str, data: Box<dyn Any>) {
321 self.state_data.push(AppStateData::new(name, data));
322 }
323
324 pub fn add_material(&mut self, material: Material) {
325 self.materials.push(material);
326 }
327
328 pub fn get_material(&self, uuid: &Uuid) -> Option<&Material> {
329 for material in &self.materials {
330 if &material.uuid == uuid {
331 return Some(&material);
332 }
333 }
334 None
335 }
336
337 pub fn get_material_by_name(&self, name: &str) -> Option<&Material> {
338 for material in &self.materials {
339 if &material.name == name {
340 return Some(&material);
341 }
342 }
343 None
344 }
345
346 pub fn get_state_data_value<T: 'static>(&self, name: &str) -> Option<&T> {
347 for data in self.state_data.iter() {
348 if data.get_name() == name {
349 if let Some(value) = data.get_value().downcast_ref::<T>() {
351 return Some(value);
352 }
353 }
354 }
355 None
356 }
357
358 pub fn get_state_data_value_mut<T: 'static>(&mut self, name: &str) -> Option<&mut T> {
359 for data in self.state_data.iter_mut() {
360 if data.get_name() == name {
361 if let Some(value) = data.get_value_mut().downcast_mut::<T>() {
363 return Some(value);
364 }
365 }
366 }
367 None
368 }
369
370 pub fn set_state_data_value(&mut self, name: &str, value: Box<dyn Any>) {
371 for data in &mut self.state_data {
372 if data.get_name() == name {
373 data.set_value(value);
374 return;
375 }
376 }
377 self.add_state_data(name, value);
379 }
380
381 pub fn inject_gui(&mut self, function: ui::GUIDrawFunction) {
382 self.gui_injections.push(function);
383 }
384
385 pub fn add_post_process(&mut self, post_process: Box<dyn PostProcessingEffect>) {
386 self.post_processes.push(post_process);
387 }
388
389 pub fn get_post_processes(&self) -> &Vec<Box<dyn PostProcessingEffect>> {
390 &self.post_processes
391 }
392
393 pub fn get_post_processes_mut(&mut self) -> &mut Vec<Box<dyn PostProcessingEffect>> {
394 &mut self.post_processes
395 }
396
397 pub fn get_mouse_state(&self) -> &MouseState {
398 &self.mouse_state
399 }
400
401 pub fn get_mouse_state_mut(&mut self) -> &mut MouseState {
402 &mut self.mouse_state
403 }
404
405 pub fn convert_to_arc_mutex(self) -> Arc<Mutex<Self>> {
406 Arc::new(Mutex::new(self))
407 }
408
409 pub fn add_object(&mut self, object: object::Object) {
410 self.objects.push(object);
411 }
412
413 pub fn get_objects(&self) -> &Vec<object::Object> {
414 &self.objects
415 }
416
417 pub fn get_object(&self, name: &str) -> Option<&object::Object> {
418 for object in self.objects.iter() {
419 if object.name == name {
420 return Some(object);
421 }
422 }
423 None
424 }
425
426 pub fn get_object_mut(&mut self, name: &str) -> Option<&mut object::Object> {
427 for object in self.objects.iter_mut() {
428 if object.name == name {
429 return Some(object);
430 }
431 }
432 None
433 }
434
435 pub fn get_object_by_uuid(&self, uuid: &Uuid) -> Option<&object::Object> {
436 for object in self.objects.iter() {
437 if &object.get_unique_id() == uuid {
438 return Some(object);
439 }
440 }
441 None
442 }
443
444 pub fn get_object_by_uuid_mut(&mut self, uuid: Uuid) -> Option<&mut object::Object> {
445 for object in self.objects.iter_mut() {
446 if object.get_unique_id() == uuid {
447 return Some(object);
448 }
449 }
450 None
451 }
452
453 pub fn get_selected_objects_mut(&mut self) -> Vec<&mut object::Object> {
454 let mut selected = Vec::new();
455 for object in self.objects.iter_mut() {
456 if self.object_selection.contains(&object.get_unique_id()) {
457 selected.push(object);
458 }
459 }
460 selected
461 }
462
463 pub fn add_light(&mut self, light: light::Light, light_type: LightEmissionType) {
464 match light_type {
465 LightEmissionType::Source => self.light.push(light),
466 LightEmissionType::Ambient => self.ambient_light = Some(light),
467 }
468 }
469
470 pub fn remove_light(&mut self, index: usize, light_type: LightEmissionType) {
471 match light_type {
472 LightEmissionType::Source => {
473 if index >= self.light.len() {
474 panic!("Index out of bounds");
475 }
476 self.light.remove(index);
477 }
478 LightEmissionType::Ambient => {
479 self.ambient_light = None;
480 }
481 };
482 }
483
484 pub fn get_lights(&self) -> &Vec<light::Light> {
485 &self.light
486 }
487
488 pub fn set_fps(&mut self, fps: u64) {
489 self.fps = fps;
490 }
491
492 pub fn get_fps(&self) -> u64 {
493 self.fps
494 }
495
496 pub fn get_objects_mut(&mut self) -> &mut Vec<object::Object> {
497 &mut self.objects
498 }
499
500 pub fn set_camera(&mut self, camera: camera::Camera) {
501 self.camera = Some(camera);
502 }
503
504 pub fn get_camera(&self) -> &Option<camera::Camera> {
505 &self.camera
506 }
507
508 pub fn get_camera_mut(&mut self) -> &mut Option<camera::Camera> {
509 &mut self.camera
510 }
511
512 pub fn set_renderscale(&mut self, scale: u32) {
513 self.render_scale = scale;
514 }
515
516 pub fn get_renderscale(&self) -> u32 {
517 self.render_scale
518 }
519
520 pub fn set_max_buffers(&mut self, max_buffers: usize) {
521 self.max_buffers = max_buffers;
522 }
523
524 pub fn get_max_buffers(&self) -> usize {
525 self.max_buffers
526 }
527
528 pub fn inject_event(&mut self, characteristic: event::EventCharacteristic, function: event::EventFunction, modifiers: Option<event::EventModifiers>) {
529 match modifiers {
530 Some(modifiers) => self.event_injections.push((characteristic, function, modifiers)),
531 None => self.event_injections.push((characteristic, function, event::EventModifiers::default())),
532 }
533 }
534 pub fn inject_update_function(&mut self, function: event::EventFunction) {
535 self.update_injections.push(function);
536 }
537
538 pub fn set_skybox(&mut self, skybox: object::Object) {
539 self.skybox = Some(skybox);
540 }
541
542 pub fn set_skybox_from_texture(&mut self, texture: Texture, event_loop: &EventLoop){
543 let mut material = crate::material::Material::unlit(event_loop.get_display_clone(), false);
544 material.set_name("INTERNAL::SkyBox");
545
546 material.set_texture(texture, crate::material::TextureType::Albedo);
547 let mut object = Object::load_from_gltf_resource(resources::skybox(), None);
549 object.add_material(material.uuid);
551 object.get_shapes_mut()[0].set_material_from_object_list(0);
552 object.name = "Skybox".to_string();
553 object.transform.set_scale([1.0, 1.0, 1.0]);
554 self.add_material(material);
555 self.set_skybox(object);
556 }
557
558 pub fn get_skybox(&self) -> &Option<object::Object> {
559 &self.skybox
560 }
561
562 pub fn get_skybox_mut(&mut self) -> &mut Option<object::Object> {
563 &mut self.skybox
564 }
565}
566
567impl EventLoop {
568 pub fn new(title: &str, width: u32, height: u32) -> Self {
569 let event_loop = winit::event_loop::EventLoopBuilder::new().build();
570 let (window, display) = glium::backend::glutin::SimpleWindowBuilder::new()
571 .with_title(title)
572 .with_inner_size(width, height)
573 .build(&event_loop);
574 EventLoop {
575 event_loop,
576 window,
577 display,
578 modifiers: EventModifiers::default(),
579 gui_renderer: None,
580 }
581 }
582 pub fn get_display_clone(&self) -> Display<WindowSurface> {
583 self.display.clone()
584 }
585
586 pub fn get_display_reference(&self) -> &Display<WindowSurface> {
587 &self.display
588 }
589
590 pub fn spawn_skybox(&mut self, app_state: &mut AppState) -> (crate::object::Object, texture::Texture) {
591 if let Some(current_skybox_object) = app_state.get_skybox().clone() {
592 if let Some(texture_uuid) = current_skybox_object.get_materials().first() {
594 if let Some(material) = app_state.get_material(texture_uuid) {
595 if let Some(texture) = &material.albedo {
596 return (
598 current_skybox_object,
599 texture.get_texture_clone(self.get_display_reference())
600 );
601 }
602 }
603 }
604
605 let mut logger = EnigmaWarning::new(None, true);
607 logger.extent("Failed to get texture from existing skybox. Creating default skybox...");
608 logger.log();
609 }
610
611 let mut material = crate::material::Material::unlit(self.display.clone(), false);
612 material.set_name("INTERNAL::SkyBox");
613
614 material.set_texture_from_resource(resources::skybox_texture(), crate::material::TextureType::Albedo);
615
616 let mut object = Object::load_from_gltf_resource(resources::skybox(), None);
618
619 object.add_material(material.uuid);
621 object.get_shapes_mut()[0].set_material_from_object_list(0);
622
623 object.name = "Skybox".to_string();
624
625 object.transform.set_scale([1.0, 1.0, 1.0]);
626
627 app_state.add_material(material);
628 let skybox_texture = texture::Texture::from_resource(&self.display, resources::skybox_texture());
630 (object, skybox_texture)
631 }
632
633 pub fn set_icon_from_path(&self, path: &str) {
634 let image = image::open(path).expect("failed to load icon").to_rgba8();
635 let image_dimensions = image.dimensions();
636 let data = image.into_raw();
637 let icon = winit::window::Icon::from_rgba(data, image_dimensions.0, image_dimensions.1).expect("failed to load icon");
638 self.window.set_window_icon(Some(icon));
639 }
640
641 pub fn set_icon_from_resource(&self, data: &[u8]) {
642 let image = image::load_from_memory(data).expect("failed to load icon").to_rgba8();
643 let image_dimensions = image.dimensions();
644 let data = image.into_raw();
645 let icon = winit::window::Icon::from_rgba(data, image_dimensions.0, image_dimensions.1).expect("failed to load icon");
646 self.window.set_window_icon(Some(icon));
647 }
648
649 pub fn run(mut self, app_state: Arc<Mutex<AppState>>) {
651 let mut temp_app_state = app_state.lock().unwrap();
652 temp_app_state.display = Some(self.display.clone());
653
654 let (skybox, skybox_texture) = self.spawn_skybox(&mut temp_app_state);
656 temp_app_state.set_skybox(skybox);
657
658
659 let mut next_frame_time = Instant::now();
661 let nanos = 1_000_000_000 / temp_app_state.fps;
662 let frame_duration = Duration::from_nanos(nanos); let mut texture = Texture2d::empty(&self.display, self.window.inner_size().width * temp_app_state.render_scale, self.window.inner_size().height * temp_app_state.render_scale).expect("Failed to create texture");
665 let mut depth_texture = glium::texture::DepthTexture2d::empty(&self.display, self.window.inner_size().width * temp_app_state.render_scale, self.window.inner_size().height * temp_app_state.render_scale).expect("Failed to create depth texture");
666
667 let mut buffer_textures: Vec<Texture2d> = Vec::new();
668 for _ in 0..temp_app_state.max_buffers {
669 buffer_textures.push(Texture2d::empty(&self.display, self.window.inner_size().width * temp_app_state.render_scale, self.window.inner_size().height * temp_app_state.render_scale).expect("Failed to create texture"));
670 }
671
672 drop(temp_app_state);
674
675 let screen_vert_rect = postprocessing::get_screen_vert_rect(&self.display);
677 let screen_indices_rect = postprocessing::get_screen_indices_rect(&self.display);
678 let screen_program = postprocessing::get_screen_program(&self.display);
679
680 match self.gui_renderer {
682 Some(_) => {}
683 None => {
684 let egui_glium = EguiGlium::new(&self.display, &self.window, &self.event_loop);
685 self.gui_renderer = Some(egui_glium);
686 }
687 }
688 self.event_loop.run(move |event, _window_target, control_flow| {
690 let mut app_state = app_state.lock().unwrap();
692 let light = app_state.light.clone();
693 let ambient_light = app_state.ambient_light.clone();
694 let camera = app_state.camera.clone();
695 let event_injections = app_state.event_injections.clone();
696 let update_injections = app_state.update_injections.clone();
697 let gui_injections = app_state.gui_injections.clone();
698
699 *control_flow = ControlFlow::WaitUntil(next_frame_time);
700 next_frame_time = Instant::now() + frame_duration;
701
702 let texture = &mut texture;
704 let depth_texture = &mut depth_texture;
705 let buffer_textures = &mut buffer_textures;
706 let mut framebuffer = glium::framebuffer::SimpleFrameBuffer::with_depth_buffer(&self.display, &*texture, &*depth_texture).expect("Failed to create framebuffer");
707
708 let skybox_texture = &skybox_texture;
710
711 match event {
712 Event::WindowEvent { event, .. } => match event {
713 WindowEvent::CloseRequested => { *control_flow = ControlFlow::Exit; }
714 WindowEvent::Resized(new_size) => {
715 let response = self.gui_renderer.as_mut().expect("Failed to retrieve gui renderer").on_event(&event);
716 if !response.consumed {
717 app_state.camera.as_mut().expect("failed to retrieve camera").set_aspect(new_size.width as f32, new_size.height as f32);
718 self.display.resize(new_size.into());
719 if let Some(app_state_display) = app_state.display.as_mut() {
720 app_state_display.resize(new_size.into());
721 }
722 }
723 }
724 WindowEvent::ModifiersChanged(modifiers) => {
725 self.modifiers.ctrl = modifiers.ctrl();
726 self.modifiers.shift = modifiers.shift();
727 self.modifiers.alt = modifiers.alt();
728 }
729 WindowEvent::CursorMoved { position, .. } => {
730 let response = self.gui_renderer.as_mut().expect("Failed to retrieve gui renderer").on_event(&event);
731 if !response.consumed {
732 app_state.get_mouse_state_mut().update_position((position.x, position.y));
733 }
734 }
735 WindowEvent::MouseInput { state, button, .. } => {
736 let mut response = self.gui_renderer.as_mut().expect("Failed to retrieve gui renderer").on_event(&event);
737 if !response.consumed {
738 for (characteristic, function, modifiers) in &event_injections {
739 if let event::EventCharacteristic::MouseDown(mouse_button) = characteristic {
740 if button == *mouse_button && modifiers == &self.modifiers {
741 if state == winit::event::ElementState::Pressed {
742 app_state.is_mouse_down = true;
743 app_state.last_event_time = Instant::now();
744 function(&mut app_state);
745 } else {
746 app_state.is_mouse_down = false;
747 }
748 }
749 } else if let event::EventCharacteristic::MousePress(_) = characteristic {
750 if modifiers == &self.modifiers {
751 function(&mut app_state);
752 response.consumed = true;
753 }
754 }
755 }
756 }
757 }
758 WindowEvent::KeyboardInput { input, .. } => {
759 let response = self.gui_renderer.as_mut().expect("Failed to retrieve gui renderer").on_event(&event);
760 if !response.consumed {
761 for (characteristic, function, modifiers) in event_injections {
762 if let event::EventCharacteristic::KeyPress(key_code) = characteristic {
763 if input.state == winit::event::ElementState::Pressed && input.virtual_keycode == Some(key_code) && modifiers == self.modifiers {
764 function(&mut app_state);
765 }
766 }
767 };
768 }
769 }
770 _ => {
771 _ = self.gui_renderer.as_mut().expect("Failed to retrieve gui renderer").on_event(&event);
772 }
773 }
774 Event::RedrawRequested(_) => {
775 let current_time = Instant::now();
776 app_state.delta_time = (current_time - app_state.last_frame_time).as_secs_f32();
777 app_state.last_frame_time = current_time;
778 app_state.time += app_state.delta_time;
779 for material in app_state.materials.iter_mut() {
781 material.update();
782 }
783 let deltatime = app_state.delta_time;
785 for object in app_state.objects.iter_mut() {
786 object.update(deltatime);
787 }
788
789 let render_target = &mut framebuffer;
790 render_target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
791 let model_matrices: std::collections::HashMap<Uuid, [[f32; 4]; 4]> = app_state.objects.iter_mut().map(|x| (x.get_unique_id(), x.transform.get_matrix())).collect();
792 let bone_uniform_buffers: std::collections::HashMap<Uuid, UniformBuffer<BoneTransforms>> = app_state.objects.iter_mut().map(|x| (x.get_unique_id(), x.get_bone_transform_buffer(&self.display))).collect();
793 let object_instances = app_state.setup_instances(&self.display, &model_matrices);
794 let opaque_rendering_parameter = glium::DrawParameters {
796 depth: glium::Depth {
797 test: glium::draw_parameters::DepthTest::IfLess,
798 write: true,
799 ..Default::default()
800 },
801 backface_culling: glium::draw_parameters::BackfaceCullingMode::CullClockwise,
802 ..Default::default()
803 };
804
805 for (instance_id, object_instance) in object_instances.iter() {
806 let object_option = app_state.get_object_by_uuid(&instance_id);
807 match object_option {
808 Some(object) => {
809 let closest_lights = object.get_closest_lights(&light);
810 let has_skeleton = object.get_skeleton().is_some();
811 let bone_transform = bone_uniform_buffers.get(&object.get_unique_id()).expect("Missing Bone Transform Uniforms for Object");
812 for ((buffer, mat_index), indices) in object_instance.vertex_buffers.iter().zip(object_instance.index_buffers.iter()) {
813 let mat_uuid: &Uuid = &object.get_materials()[*mat_index];
814 match app_state.get_material(mat_uuid) {
815 Some(material) => {
816 if material.render_transparent {
817 continue;
818 }
819 let uniforms = &material.get_uniforms(&closest_lights, ambient_light, camera, &bone_transform, has_skeleton, skybox_texture);
820 render_target.draw((buffer, object_instance.instance_attributes.per_instance().expect("Error, unwrapping per instance in opaque draw")), indices, &material.program, uniforms, &opaque_rendering_parameter).expect("Failed to draw object");
821 }
822 None => ()
823 }
824 }
825 }
826 None => EnigmaError::new(Some(smart_format!("Error, instancing the Object Instance with the instance id {}, because no Object with that Id could be found", instance_id).as_str()), true).log()
827 }
828 }
829
830 let skybox_rendering_parameter = glium::DrawParameters {
832 depth: glium::Depth {
833 test: glium::draw_parameters::DepthTest::IfLess,
834 write: false,
835 ..Default::default()
836 },
837 backface_culling: glium::draw_parameters::BackfaceCullingMode::CullClockwise,
838 ..Default::default()
839 };
840
841 let skybox_model_matrix = match app_state.get_skybox_mut() {
843 Some(obj) => Some(obj.transform.get_matrix().clone()),
844 None => None
845 };
846 let skybox_instance = app_state.setup_skybox_instance(&self.display, &skybox_model_matrix);
847
848 match skybox_instance {
849 Some((skybox_id, instance)) => {
850 let object_option = app_state.get_skybox();
851 match object_option {
852 Some(skybox) => {
853 let closest_lights = skybox.get_closest_lights(&light);
854 let skybox_bone_buffer = skybox.get_bone_transform_buffer(&self.display);
855 for ((buffer, mat_index), indices) in instance.vertex_buffers.iter().zip(instance.index_buffers.iter()) {
856 let mat_uuid: &Uuid = &skybox.get_materials()[*mat_index];
857 match app_state.get_material(mat_uuid) {
858 Some(material) => {
859 let uniforms = &material.get_uniforms(&closest_lights, ambient_light, camera, &skybox_bone_buffer, false, skybox_texture);
860 render_target.draw((buffer, instance.instance_attributes.per_instance().expect("Error, unwrapping per instance in skybox draw")), indices, &material.program, uniforms, &skybox_rendering_parameter).expect("Failed to draw object");
861 }
862 None => ()
863 }
864 }
865 }
866 None => EnigmaError::new(Some(smart_format!("Error, instancing the Skybox Instance with the instance id {}, because no Object with that Id could be found", skybox_id).as_str()), true).log()
867 }
868 }
869 None => {}
870 }
871
872 let transparent_rendering_parameter = glium::DrawParameters {
874 blend: glium::Blend::alpha_blending(),
875 ..opaque_rendering_parameter
876 };
877 for (instance_id, object_instance) in object_instances.iter() {
878 let object_option = app_state.get_object_by_uuid(&instance_id);
879 match object_option {
880 Some(object) => {
881 let closest_lights = object.get_closest_lights(&light);
882 let has_skeleton = object.get_skeleton().is_some();
883 let bone_transform = bone_uniform_buffers.get(&object.get_unique_id()).expect("Missing Bone Transform Uniforms for Object");
884 for ((buffer, mat_index), indices) in object_instance.vertex_buffers.iter().zip(object_instance.index_buffers.iter()) {
885 let mat_uuid: &Uuid = &object.get_materials()[*mat_index];
886 match app_state.get_material(mat_uuid) {
887 Some(material) => {
888 if !material.render_transparent {
889 continue;
890 }
891 let uniforms = &material.get_uniforms(&closest_lights, ambient_light, camera, &bone_transform, has_skeleton, skybox_texture);
892 render_target.draw((buffer, object_instance.instance_attributes.per_instance().expect("Error, unwrapping per instance in transparent draw")), indices, &material.program, uniforms, &transparent_rendering_parameter).expect("Failed to draw object");
893 }
894 None => ()
895 }
896 }
897 }
898 None => EnigmaError::new(Some(smart_format!("Error, instancing the Transparent Object Instance with the instance id {}, because no Object with that Id could be found", instance_id).as_str()), true).log()
899 }
900 }
901
902 for process in app_state.get_post_processes() {
904 process.render(&app_state, &screen_vert_rect, &screen_indices_rect, &mut framebuffer, &texture, &depth_texture, &buffer_textures);
905 }
906
907 let mut screen_target = self.display.draw();
909 let screen_uniforms = uniform! {
910 scene: &*texture,
911 };
912 screen_target.draw(
913 &screen_vert_rect,
914 &screen_indices_rect,
915 &screen_program,
916 &screen_uniforms,
917 &Default::default(),
918 ).expect("Failed to draw screen");
919
920 let gui_renderer = self.gui_renderer.as_mut().expect("Failed to retrieve gui renderer");
922 gui_renderer.run(&self.window, |egui_context| {
923 for function in gui_injections.iter() {
924 function(egui_context, &mut app_state);
925 }
926 });
927 gui_renderer.paint(&self.display, &mut screen_target);
928 screen_target.finish().expect("Failed to swap buffers");
929 }
930 Event::MainEventsCleared => {
931
932 if app_state.is_mouse_down && app_state.last_event_time.elapsed() >= Duration::from_millis(100) {
934 for (characteristic, function, modifiers) in &event_injections {
935 if let event::EventCharacteristic::MouseDown(_) = characteristic {
936 if modifiers == &self.modifiers {
937 function(&mut app_state);
938 app_state.last_event_time = Instant::now();
939 }
940 }
941 }
942 }
943
944 for function in update_injections {
946 function(&mut app_state);
947 }
948 self.window.request_redraw();
949 }
950 _ => (),
951 }
952 });
953 }
954}