kitgit

tirbofish/dropbear · commit

7192219e7306a1b7f358ee10885094bcfd2142d5

fix: antialiasing hot swapping fix

Unverified

Thribhu K <4tkbytes@pm.me> · 2026-02-23 10:52

view full diff

diff --git a/crates/dropbear-engine/src/lib.rs b/crates/dropbear-engine/src/lib.rs
index 905a06d..f50f994 100644
--- a/crates/dropbear-engine/src/lib.rs
+++ b/crates/dropbear-engine/src/lib.rs
@@ -637,6 +637,23 @@ Hardware:
             );
     }
 
+    pub fn set_antialiasing(&mut self, antialiasing: AntiAliasingMode) -> bool {
+        if *self.antialiasing.read() == antialiasing {
+            return false;
+        }
+
+        *self.antialiasing.write() = antialiasing;
+
+        let config = self.config.read().clone();
+        self.depth_texture =
+            Texture::depth_texture(&config, &self.device, antialiasing, Some("depth texture"));
+        self.hdr
+            .write()
+            .resize(&self.device, config.width, config.height, Some(antialiasing));
+
+        true
+    }
+
     /// Resizes the offscreen viewport texture without touching the window surface.
     pub fn resize_viewport_texture(&mut self, width: u32, height: u32) {
         if width == 0 || height == 0 {
@@ -1443,6 +1460,13 @@ impl ApplicationHandler for App {
                 scene::SceneCommand::SetFPS(new_fps) => {
                     self.set_target_fps(new_fps);
                 }
+                scene::SceneCommand::SetAntialiasing(antialiasing) => {
+                    if let Some((state, graphics)) = self.windows.get_mut(&window_id) {
+                        if state.set_antialiasing(antialiasing) {
+                            *graphics = Arc::new(graphics::SharedGraphicsContext::from_state(state));
+                        }
+                    }
+                }
                 scene::SceneCommand::ResizeViewport((width, height)) => {
                     if let Some((state, graphics)) = self.windows.get_mut(&window_id) {
                         state.resize_viewport_texture(width, height);
diff --git a/crates/dropbear-engine/src/scene.rs b/crates/dropbear-engine/src/scene.rs
index 940e955..2529a39 100644
--- a/crates/dropbear-engine/src/scene.rs
+++ b/crates/dropbear-engine/src/scene.rs
@@ -7,6 +7,7 @@ use winit::event_loop::ActiveEventLoop;
 use winit::window::WindowId;
 
 use crate::{WindowData, graphics::SharedGraphicsContext, input};
+use crate::multisampling::AntiAliasingMode;
 use parking_lot::RwLock;
 use std::{collections::HashMap, rc::Rc, sync::Arc};
 
@@ -35,6 +36,7 @@ pub enum SceneCommand {
     RequestWindow(WindowData),
     CloseWindow(WindowId),
     SetFPS(u32),
+    SetAntialiasing(AntiAliasingMode),
     ResizeViewport((u32, u32)),
 }
 
@@ -150,6 +152,7 @@ impl Manager {
                 SceneCommand::RequestWindow(_)
                 | SceneCommand::CloseWindow(_)
                 | SceneCommand::SetFPS(_)
+                | SceneCommand::SetAntialiasing(_)
                 | SceneCommand::ResizeViewport(_) => {
                     return vec![command];
                 }
diff --git a/crates/eucalyptus-editor/src/editor/mod.rs b/crates/eucalyptus-editor/src/editor/mod.rs
index f671855..e158ee2 100644
--- a/crates/eucalyptus-editor/src/editor/mod.rs
+++ b/crates/eucalyptus-editor/src/editor/mod.rs
@@ -68,6 +68,7 @@ use tokio::sync::oneshot;
 use transform_gizmo_egui::{EnumSet, Gizmo, GizmoMode, GizmoOrientation};
 use wgpu::{Color, Extent3d};
 use winit::dpi::PhysicalSize;
+use dropbear_engine::multisampling::AntiAliasingMode;
 use winit::window::{CursorGrabMode, WindowAttributes};
 use winit::{keyboard::KeyCode, window::Window};
 
@@ -177,6 +178,7 @@ pub struct Editor {
     pub(crate) play_mode_exit_rx: Option<std::sync::mpsc::Receiver<()>>,
 
     pub(crate) asset_clipboard: Option<AssetClipboard>,
+    pub(crate) pending_aa_reload: Option<AntiAliasingMode>,
 }
 
 impl Editor {
@@ -292,6 +294,7 @@ impl Editor {
             play_mode_pid: None,
             play_mode_exit_rx: None,
             asset_clipboard: None,
+            pending_aa_reload: None,
             collider_wireframe_pipeline: None,
             instance_buffer_cache: HashMap::new(),
             animated_instance_buffer: None,
@@ -1388,6 +1391,7 @@ impl Editor {
     pub fn load_wgpu_nerdy_stuff<'a>(
         &mut self,
         graphics: std::sync::Arc<dropbear_engine::graphics::SharedGraphicsContext>,
+        skybox_texture: Option<&Vec<u8>>,
     ) {
         self.main_render_pipeline = Some(MainRenderPipeline::new(graphics.clone()));
         self.light_cube_pipeline = Some(LightCubePipeline::new(graphics.clone()));
@@ -1405,7 +1409,7 @@ impl Editor {
         let sky_texture = HdrLoader::from_equirectangular_bytes(
             &graphics.device,
             &graphics.queue,
-            DEFAULT_SKY_TEXTURE,
+            skybox_texture.map_or(DEFAULT_SKY_TEXTURE, |v| v.as_slice()),
             1080,
             Some("sky texture"),
         );
@@ -1569,7 +1573,9 @@ impl UndoableAction {
 
 /// This enum will be used to describe the type of command/signal. This is only between
 /// the editor and unlike SceneCommand, this will ping a signal everywhere in that scene
+#[derive(Default)]
 pub enum Signal {
+    #[default]
     None,
     Copy(SceneEntity),
     Paste(SceneEntity),
@@ -1588,6 +1594,9 @@ pub enum Signal {
     /// Adds a new component instance using the async init pipeline.
     AddComponent(hecs::Entity, Box<dyn SerializedComponent>),
     RequestNewWindow(WindowData),
+    ReloadWGPUData{
+        skybox_texture: Option<Vec<u8>>
+    },
     UpdateViewportSize((f32, f32)),
 }
 
diff --git a/crates/eucalyptus-editor/src/editor/scene.rs b/crates/eucalyptus-editor/src/editor/scene.rs
index f4663b4..2e7288f 100644
--- a/crates/eucalyptus-editor/src/editor/scene.rs
+++ b/crates/eucalyptus-editor/src/editor/scene.rs
@@ -149,8 +149,29 @@ impl Scene for Editor {
             log_once::debug_once!("Scene has fully loaded");
         }
 
+        {
+            let desired = EDITOR_SETTINGS.read().anti_aliasing_mode;
+            let current = *graphics.antialiasing.read();
+
+            if desired != current {
+                if self.pending_aa_reload != Some(desired)
+                    && matches!(self.scene_command, SceneCommand::None)
+                {
+                    log::debug!("Anti aliasing mode changed, requesting WGPU update");
+                    self.scene_command = SceneCommand::SetAntialiasing(desired);
+                    self.pending_aa_reload = Some(desired);
+                }
+            } else if self.pending_aa_reload.is_some() {
+                log::debug!("Anti aliasing mode applied, reloading WGPU data");
+                self.signal = Signal::ReloadWGPUData {
+                    skybox_texture: None,
+                };
+                self.pending_aa_reload = None;
+            }
+        }
+
         if !self.is_world_loaded.rendering_loaded && self.is_world_loaded.is_fully_loaded() {
-            self.load_wgpu_nerdy_stuff(graphics);
+            self.load_wgpu_nerdy_stuff(graphics, None);
             return;
         }
 
diff --git a/crates/eucalyptus-editor/src/editor/settings/editor.rs b/crates/eucalyptus-editor/src/editor/settings/editor.rs
index bd77274..54f64d6 100644
--- a/crates/eucalyptus-editor/src/editor/settings/editor.rs
+++ b/crates/eucalyptus-editor/src/editor/settings/editor.rs
@@ -226,21 +226,16 @@ impl Scene for EditorSettingsWindow {
                                 }
                             });
                             {
-                                let mut antialiasing = graphics.antialiasing.write();
                                 ui.label("Anti-aliasing mode:");
                                 ComboBox::from_id_salt("anti-aliasing-mode-combobox")
-                                    .selected_text(match *antialiasing {
+                                    .selected_text(match editor.anti_aliasing_mode {
                                         AntiAliasingMode::None => "None",
                                         AntiAliasingMode::MSAA4 => "MSAA4"
                                     })
                                     .show_ui(ui, |ui| {
-                                        ui.selectable_value(&mut *antialiasing, AntiAliasingMode::None, "None");
-                                        ui.selectable_value(&mut *antialiasing, AntiAliasingMode::MSAA4, "MSAA4");
+                                        ui.selectable_value(&mut editor.anti_aliasing_mode, AntiAliasingMode::None, "None");
+                                        ui.selectable_value(&mut editor.anti_aliasing_mode, AntiAliasingMode::MSAA4, "MSAA4");
                                     });
-
-                                if editor.anti_aliasing_mode != *antialiasing {
-                                    editor.anti_aliasing_mode = *antialiasing;
-                                }
                             }
 
                         }
diff --git a/crates/eucalyptus-editor/src/signal.rs b/crates/eucalyptus-editor/src/signal.rs
index 9b2f72d..fe8e017 100644
--- a/crates/eucalyptus-editor/src/signal.rs
+++ b/crates/eucalyptus-editor/src/signal.rs
@@ -9,7 +9,13 @@ use eucalyptus_core::{fatal, info, success, success_without_console, warn, warn_
 use std::fs;
 use std::path::PathBuf;
 use std::sync::Arc;
+use log::error;
 use winit::keyboard::KeyCode;
+use dropbear_engine::pipelines::GlobalsUniform;
+use dropbear_engine::pipelines::light_cube::LightCubePipeline;
+use dropbear_engine::pipelines::shader::MainRenderPipeline;
+use dropbear_engine::sky::{HdrLoader, SkyPipeline, DEFAULT_SKY_TEXTURE};
+use eucalyptus_core::physics::collider::shader::ColliderWireframePipeline;
 
 pub trait SignalController {
     fn run_signal(&mut self, graphics: Arc<SharedGraphicsContext>) -> anyhow::Result<()>;
@@ -20,7 +26,7 @@ impl SignalController for Editor {
         let local_signal: Option<Signal> = None;
         let show = true;
 
-        match &self.signal {
+        match std::mem::replace(&mut self.signal, Signal::None) {
             Signal::None => {
                 // returns absolutely nothing because no signal is set.
                 Ok::<(), anyhow::Error>(())
@@ -29,7 +35,7 @@ impl SignalController for Editor {
             Signal::AssetCopy { source, division } => {
                 self.asset_clipboard = Some(AssetClipboard {
                     source: source.clone(),
-                    division: *division,
+                    division: division,
                 });
                 self.signal = Signal::None;
                 Ok(())
@@ -46,7 +52,7 @@ impl SignalController for Editor {
                 }
 
                 let clipboard = clipboard.unwrap();
-                if clipboard.division != *division {
+                if clipboard.division != division {
                     warn!("Cannot paste across different asset divisions");
                     self.signal = Signal::None;
                     return Ok(());
@@ -521,7 +527,7 @@ impl SignalController for Editor {
                     loader_future.await
                 };
                 let handle = graphics.future_queue.push(init_future);
-                self.pending_components.push((*entity, handle));
+                self.pending_components.push((entity, handle));
 
                 success!("Queued component addition for entity {:?}", entity);
                 self.signal = Signal::None;
@@ -545,6 +551,21 @@ impl SignalController for Editor {
                 self.signal = Signal::None;
                 Ok(())
             }
+            Signal::ReloadWGPUData { skybox_texture } => {
+                self.main_render_pipeline = None;
+                self.light_cube_pipeline = None;
+                self.shader_globals = None;
+                self.collider_wireframe_pipeline = None;
+                self.mipmapper = None;
+                self.texture_id = None;
+                self.window = None;
+                self.sky_pipeline = None;
+                self.load_wgpu_nerdy_stuff(graphics.clone(), skybox_texture.as_ref());
+                
+                self.signal = Signal::None;
+                
+                Ok(())
+            }
         }?;
         if !show {
             self.signal = Signal::None;
diff --git a/crates/redback-runtime/src/lib.rs b/crates/redback-runtime/src/lib.rs
index 60297d6..2edcf3c 100644
--- a/crates/redback-runtime/src/lib.rs
+++ b/crates/redback-runtime/src/lib.rs
@@ -237,7 +237,18 @@ impl PlayMode {
         Ok(result)
     }
 
-    pub fn load_wgpu_nerdy_stuff<'a>(&mut self, graphics: Arc<SharedGraphicsContext>) {
+    pub fn reload_wgpu(&mut self, graphics: Arc<SharedGraphicsContext>, sky_texture: Option<&Vec<u8>>) {
+        self.light_cube_pipeline = None;
+        self.main_pipeline = None;
+        self.shader_globals = None;
+        self.collider_wireframe_pipeline = None;
+        self.kino = None;
+        self.sky_pipeline = None;
+
+        self.load_wgpu_nerdy_stuff(graphics, sky_texture);
+    }
+
+    pub fn load_wgpu_nerdy_stuff<'a>(&mut self, graphics: Arc<SharedGraphicsContext>, sky_texture: Option<&Vec<u8>>) {
         self.light_cube_pipeline = Some(LightCubePipeline::new(graphics.clone()));
         self.main_pipeline = Some(MainRenderPipeline::new(graphics.clone()));
         self.shader_globals = Some(GlobalsUniform::new(
@@ -262,7 +273,7 @@ impl PlayMode {
         let sky_texture = HdrLoader::from_equirectangular_bytes(
             &graphics.device,
             &graphics.queue,
-            DEFAULT_SKY_TEXTURE,
+            sky_texture.map_or(DEFAULT_SKY_TEXTURE, |v| v.as_slice()),
             1080,
             Some("sky texture"),
         );
@@ -511,7 +522,7 @@ impl PlayMode {
         progress.camera_received = true;
         self.scene_progress = Some(progress);
 
-        self.load_wgpu_nerdy_stuff(graphics.clone());
+        self.load_wgpu_nerdy_stuff(graphics.clone(), None);
 
         self.reload_scripts_for_current_world(graphics.clone());
 
@@ -541,7 +552,7 @@ impl PlayMode {
                 self.active_camera = Some(new_camera);
             }
 
-            self.load_wgpu_nerdy_stuff(graphics.clone());
+            self.load_wgpu_nerdy_stuff(graphics.clone(), None);
             self.reload_scripts_for_current_world(graphics.clone());
 
             self.current_scene = Some(scene_progress.requested_scene.clone());