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