kitgit

tirbofish/dropbear · commit

bfddeece3ffab9ecdc7c08f0e204de228aaa0289

Merge pull request #46 features: optimised model loading, added world loading status, changed from WASM to boa_engine jarvis, run github actions. i think this commit deserves a nightly action (not public enough yet lol)

Unverified

tk <4tkbytes@pm.me> · 2025-09-18 08:58

view full diff

diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml
deleted file mode 100644
index 9b23cc7..0000000
--- a/.github/workflows/docs.yaml
+++ /dev/null
@@ -1,42 +0,0 @@
-name: Generate and Publish TypeScript Docs
-
-on:
-  push:
-    branches: [ main ]
-  workflow_dispatch:
-
-permissions:
-  contents: read
-  pages: write
-
-jobs:
-  build-and-deploy:
-    runs-on: ubuntu-latest
-
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v4
-
-      - name: Setup Node.js
-        uses: actions/setup-node@v4
-        with:
-          node-version: 18
-
-      - name: Cache npm
-        uses: actions/cache@v4
-        with:
-          path: ~/.npm
-          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
-          restore-keys: |
-            ${{ runner.os }}-node-
-
-      - name: Generate TypeScript docs
-        run: |
-          chmod +x scripts/gen_docs.sh
-          ./scripts/gen_docs.sh
-
-      - name: Deploy to GitHub Pages
-        uses: peaceiris/actions-gh-pages@v3
-        with:
-          github_token: ${{ secrets.PAGES_PAT }}
-          publish_dir: ./docs
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index b28240e..5061850 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,8 +22,8 @@ colored = "3.0"
 dropbear-engine = { path = "dropbear-engine" }
 egui = "0.32"
 egui-toast-fork = "0.18"
-egui_wgpu_backend = { version = "0.35", git = "https://github.com/hasenbanck/egui_wgpu_backend"}
-egui_winit_platform = { version = "0.27", git = "https://github.com/hasenbanck/egui_winit_platform" }
+egui-wgpu = { version = "0.32" }
+egui-winit = { version = "0.32" }
 egui_dnd = "0.13"
 egui_dock-fork = { version = "0.17", features = ["serde"] }
 egui_extras = { version = "0.32", features = ["all_loaders"] }
@@ -42,22 +42,26 @@ open = "5"
 parking_lot = {version = "0.12", features = ["deadlock_detection"] }
 rfd = "0.15.4"
 ron = "0.11"
-russimp-ng = { version = "3.2", features = ["static-link"] }
-rustyscript = { version = "0.12" }
+# russimp-ng = { version = "3.2", features = ["static-link"] }
+# rustyscript = { version = "0.12" }
 serde = { version = "1.0.219", features = ["derive"] }
 spin_sleep = "1.3"
 transform-gizmo-egui = { git = "https://github.com/4tkbytes/transform-gizmo"}
 tokio = { version = "1", features = ["full"] }
-wgpu = "26"
+wgpu = "25"
 winit = { version = "0.30", features = [] }
 zip = "5.1"
 walkdir = "2.3"
-wasmer = { version = "6.1.0-rc.3" }
+# wasmer = { version = "6.1.0-rc.3" }
 rayon = "1.11"
 flate2 = "1.1"
 reqwest = { version = "0.11", features = ["stream"] }
 tar = "0.4"
 async-trait = "0.1"
+futures-util = "0.3"
+boa_engine = "0.20"
+backtrace = "0.3"
+
 
 gltf = "1"
 thiserror = "2.0"
@@ -76,11 +80,11 @@ lto = false
 # it takes way too long to exit out
 panic = "abort"
 
-[profile.release]
-opt-level = 3
-lto = true 
-codegen-units = 1
-strip = true
-panic = "abort"
-debug = false
-incremental = false
+# [profile.release]
+# opt-level = 3
+# lto = true 
+# codegen-units = 1
+# strip = true
+# panic = "abort"
+# debug = false
+# incremental = false
diff --git a/dropbear-engine/Cargo.toml b/dropbear-engine/Cargo.toml
index bdc755b..6cf629b 100644
--- a/dropbear-engine/Cargo.toml
+++ b/dropbear-engine/Cargo.toml
@@ -14,8 +14,8 @@ app_dirs2.workspace = true
 bytemuck.workspace = true
 chrono.workspace = true
 colored.workspace = true
-egui_wgpu_backend.workspace = true
-egui_winit_platform.workspace = true
+egui-wgpu.workspace = true
+egui-winit.workspace = true
 egui.workspace = true
 env_logger.workspace = true
 futures.workspace = true
@@ -36,6 +36,8 @@ gltf.workspace = true
 rayon.workspace = true
 tokio.workspace = true
 async-trait.workspace = true
+backtrace.workspace = true
+os_info = "*"
 
 [target.'cfg(not(target_os = "android"))'.dependencies]
 rfd.workspace = true
diff --git a/dropbear-engine/src/camera.rs b/dropbear-engine/src/camera.rs
index 73fefa8..a4060ab 100644
--- a/dropbear-engine/src/camera.rs
+++ b/dropbear-engine/src/camera.rs
@@ -161,7 +161,11 @@ impl Camera {
         result
     }
 
-    pub fn create_bind_group_layout(&mut self, graphics: Arc<SharedGraphicsContext>, camera_buffer: Buffer) {
+    pub fn create_bind_group_layout(
+        &mut self,
+        graphics: Arc<SharedGraphicsContext>,
+        camera_buffer: Buffer,
+    ) {
         let camera_bind_group_layout =
             graphics
                 .device
@@ -179,16 +183,14 @@ impl Camera {
                     label: Some("camera_bind_group_layout"),
                 });
 
-        let camera_bind_group = graphics
-            .device
-            .create_bind_group(&BindGroupDescriptor {
-                layout: &camera_bind_group_layout,
-                entries: &[BindGroupEntry {
-                    binding: 0,
-                    resource: camera_buffer.as_entire_binding(),
-                }],
-                label: Some("camera_bind_group"),
-            });
+        let camera_bind_group = graphics.device.create_bind_group(&BindGroupDescriptor {
+            layout: &camera_bind_group_layout,
+            entries: &[BindGroupEntry {
+                binding: 0,
+                resource: camera_buffer.as_entire_binding(),
+            }],
+            label: Some("camera_bind_group"),
+        });
         self.layout = Some(camera_bind_group_layout);
         self.bind_group = Some(camera_bind_group);
     }
diff --git a/dropbear-engine/src/egui_renderer.rs b/dropbear-engine/src/egui_renderer.rs
index df7b8b3..f0bc2a1 100644
--- a/dropbear-engine/src/egui_renderer.rs
+++ b/dropbear-engine/src/egui_renderer.rs
@@ -1,60 +1,68 @@
-use egui::{Context, FontDefinitions};
-use egui_wgpu_backend::{RenderPass, ScreenDescriptor, wgpu};
-use egui_winit_platform::{Platform, PlatformDescriptor};
-use wgpu::{CommandEncoder, Device, Queue, TextureFormat, TextureView};
+use egui::Context;
+use egui_wgpu::wgpu::{CommandEncoder, Device, Queue, StoreOp, TextureFormat, TextureView};
+use egui_wgpu::{Renderer, ScreenDescriptor, wgpu};
+use egui_winit::State;
 use winit::event::WindowEvent;
 use winit::window::Window;
 
 pub struct EguiRenderer {
-    state: Platform,
-    renderer: RenderPass,
+    state: State,
+    renderer: Renderer,
     frame_started: bool,
 }
 
 impl EguiRenderer {
-    pub fn context(&mut self) -> Context {
-        self.state.context()
+    pub fn context(&self) -> &Context {
+        self.state.egui_ctx()
     }
 
-    pub fn renderer(&mut self) -> &mut RenderPass {
+    pub fn renderer(&mut self) -> &mut Renderer {
         &mut self.renderer
     }
 
     pub fn new(
         device: &Device,
         output_color_format: TextureFormat,
+        output_depth_format: Option<TextureFormat>,
         msaa_samples: u32,
         window: &Window,
     ) -> EguiRenderer {
-        let size = window.inner_size();
-
-        let platform = Platform::new(PlatformDescriptor {
-            physical_width: size.width as u32,
-            physical_height: size.height as u32,
-            scale_factor: window.scale_factor(),
-            font_definitions: FontDefinitions::default(),
-            style: Default::default(),
-        });
-
-        let egui_renderer = RenderPass::new(device, output_color_format, msaa_samples);
+        let egui_context = Context::default();
+
+        let egui_state = egui_winit::State::new(
+            egui_context,
+            egui::viewport::ViewportId::ROOT,
+            &window,
+            Some(window.scale_factor() as f32),
+            None,
+            Some(2 * 1024), // default dimension is 2048
+        );
+        let egui_renderer = Renderer::new(
+            device,
+            output_color_format,
+            output_depth_format,
+            msaa_samples,
+            true,
+        );
 
         EguiRenderer {
-            state: platform,
+            state: egui_state,
             renderer: egui_renderer,
             frame_started: false,
         }
     }
 
-    pub fn handle_input(&mut self, event: &WindowEvent) {
-        let _ = self.state.handle_event(event);
+    pub fn handle_input(&mut self, window: &Window, event: &WindowEvent) {
+        let _ = self.state.on_window_event(window, event);
     }
 
     pub fn ppp(&mut self, v: f32) {
         self.context().set_pixels_per_point(v);
     }
 
-    pub fn begin_frame(&mut self) {
-        self.state.begin_pass();
+    pub fn begin_frame(&mut self, window: &Window) {
+        let raw_input = self.state.take_egui_input(window);
+        self.state.egui_ctx().begin_pass(raw_input);
         self.frame_started = true;
     }
 
@@ -68,37 +76,46 @@ impl EguiRenderer {
         screen_descriptor: ScreenDescriptor,
     ) {
         if !self.frame_started {
-            return;
+            panic!("begin_frame must be called before end_frame_and_draw can be called!");
         }
 
-        let full_output = self.state.end_pass(Some(window));
-        let paint_jobs = self
-            .state
-            .context()
-            .tessellate(full_output.shapes, self.state.context().pixels_per_point());
-        let textures_delta: egui::TexturesDelta = full_output.textures_delta;
+        self.ppp(screen_descriptor.pixels_per_point);
 
-        self.renderer
-            .add_textures(device, queue, &textures_delta)
-            .expect("add texture ok");
-        self.renderer
-            .update_buffers(device, queue, &paint_jobs, &screen_descriptor);
+        let full_output = self.state.egui_ctx().end_pass();
 
-        self.renderer
-            .execute(
-                encoder,
-                window_surface_view,
-                &paint_jobs,
-                &screen_descriptor,
-                Some(wgpu::Color::BLACK),
-            )
-            .expect("egui execute ok");
+        self.state
+            .handle_platform_output(window, full_output.platform_output);
 
-        // self.ppp(window.scale_factor() as f32);
+        let tris = self
+            .state
+            .egui_ctx()
+            .tessellate(full_output.shapes, self.state.egui_ctx().pixels_per_point());
+        for (id, image_delta) in &full_output.textures_delta.set {
+            self.renderer
+                .update_texture(device, queue, *id, image_delta);
+        }
+        self.renderer
+            .update_buffers(device, queue, encoder, &tris, &screen_descriptor);
+        let rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
+            color_attachments: &[Some(wgpu::RenderPassColorAttachment {
+                view: window_surface_view,
+                resolve_target: None,
+                ops: egui_wgpu::wgpu::Operations {
+                    load: egui_wgpu::wgpu::LoadOp::Load,
+                    store: StoreOp::Store,
+                },
+            })],
+            depth_stencil_attachment: None,
+            timestamp_writes: None,
+            label: Some("egui main render pass"),
+            occlusion_query_set: None,
+        });
 
         self.renderer
-            .remove_textures(textures_delta)
-            .expect("remove texture ok");
+            .render(&mut rpass.forget_lifetime(), &tris, &screen_descriptor);
+        for x in &full_output.textures_delta.free {
+            self.renderer.free_texture(x)
+        }
 
         self.frame_started = false;
     }
diff --git a/dropbear-engine/src/entity.rs b/dropbear-engine/src/entity.rs
index 171bef6..6865cc9 100644
--- a/dropbear-engine/src/entity.rs
+++ b/dropbear-engine/src/entity.rs
@@ -1,11 +1,11 @@
 use futures::executor::block_on;
 use glam::{DMat4, DQuat, DVec3, Mat4};
 use serde::{Deserialize, Serialize};
-use std::{path::PathBuf, sync::Arc};
+use std::{path::{Path, PathBuf}, sync::Arc};
 use wgpu::{Buffer, util::DeviceExt};
 
 use crate::{
-    graphics::{SharedGraphicsContext, Instance},
+    graphics::{Instance, SharedGraphicsContext},
     model::{LazyModel, LazyType, Model},
 };
 
@@ -68,7 +68,7 @@ pub struct LazyAdoptedEntity {
 impl LazyAdoptedEntity {
     /// Create a LazyAdoptedEntity from a file path (can be run on background thread)
     pub async fn from_file(path: &PathBuf, label: Option<&str>) -> anyhow::Result<Self> {
-        let buffer = std::fs::read(path)?;
+        let buffer = tokio::fs::read(path).await?;
         Self::from_memory(buffer, label).await
     }
 
@@ -79,7 +79,7 @@ impl LazyAdoptedEntity {
     ) -> anyhow::Result<Self> {
         let lazy_model = Model::lazy_load(buffer, label).await?;
         let label_str = label.unwrap_or("LazyAdoptedEntity").to_string();
-        
+
         Ok(Self {
             lazy_model,
             label: label_str,
@@ -105,7 +105,7 @@ impl LazyType for LazyAdoptedEntity {
     }
 }
 
-#[derive(Default)]
+#[derive(Default, Clone)]
 pub struct AdoptedEntity {
     pub model: Option<Model>,
     pub previous_matrix: DMat4,
@@ -114,8 +114,13 @@ pub struct AdoptedEntity {
 }
 
 impl AdoptedEntity {
-    pub async fn new(graphics: Arc<SharedGraphicsContext>, path: &PathBuf, label: Option<&str>) -> anyhow::Result<Self> {
-        let model = Model::load(graphics.clone(), path, label.clone()).await?;
+    pub async fn new(
+        graphics: Arc<SharedGraphicsContext>,
+        path: impl AsRef<Path>,
+        label: Option<&str>,
+    ) -> anyhow::Result<Self> {
+        let path = path.as_ref().to_path_buf();
+        let model = Model::load(graphics.clone(), &path, label.clone()).await?;
         Ok(Self::adopt(graphics, model).await)
     }
 
diff --git a/dropbear-engine/src/graphics.rs b/dropbear-engine/src/graphics.rs
index 60197a2..8ce5515 100644
--- a/dropbear-engine/src/graphics.rs
+++ b/dropbear-engine/src/graphics.rs
@@ -6,12 +6,19 @@ use image::GenericImageView;
 use parking_lot::Mutex;
 // use nalgebra::{Matrix4, UnitQuaternion, Vector3};
 use wgpu::{
-    util::{BufferInitDescriptor, DeviceExt}, BindGroup, BindGroupLayout, Buffer, BufferAddress, BufferUsages, Color, CommandEncoder, CompareFunction, DepthBiasState, Device, Extent3d, LoadOp, Operations, Queue, RenderPass, RenderPassDepthStencilAttachment, RenderPipeline, Sampler, ShaderModule, StencilState, SurfaceConfiguration, TextureDescriptor, TextureFormat, TextureUsages, TextureView, TextureViewDescriptor, VertexBufferLayout
+    BindGroup, BindGroupLayout, Buffer, BufferAddress, BufferUsages, Color, CommandEncoder,
+    CompareFunction, DepthBiasState, Device, Extent3d, LoadOp, Operations, Queue, RenderPass,
+    RenderPassDepthStencilAttachment, RenderPipeline, Sampler, ShaderModule, StencilState,
+    SurfaceConfiguration, TextureDescriptor, TextureFormat, TextureUsages, TextureView,
+    TextureViewDescriptor, VertexBufferLayout,
+    util::{BufferInitDescriptor, DeviceExt},
 };
 use winit::window::Window;
 
 use crate::{
-    egui_renderer::EguiRenderer, model::{self, Vertex}, State
+    State,
+    egui_renderer::EguiRenderer,
+    model::{self, Vertex},
 };
 
 pub const NO_TEXTURE: &'static [u8] = include_bytes!("../../resources/no-texture.png");
@@ -44,7 +51,7 @@ pub struct FrameGraphicsContext<'a> {
 
 impl SharedGraphicsContext {
     pub fn get_egui_context(&self) -> Context {
-        self.egui_renderer.lock().context()
+        self.egui_renderer.lock().context().clone()
     }
 
     pub fn create_uniform<T>(&self, uniform: T, label: Option<&str>) -> Buffer
@@ -83,17 +90,15 @@ impl<'a> RenderContext<'a> {
         encoder: &'a mut CommandEncoder,
     ) -> Self {
         let screen_size = (state.config.width as f32, state.config.height as f32);
-        let diffuse_sampler = Arc::new(state
-            .device
-            .create_sampler(&wgpu::SamplerDescriptor {
-                address_mode_u: wgpu::AddressMode::ClampToEdge,
-                address_mode_v: wgpu::AddressMode::ClampToEdge,
-                address_mode_w: wgpu::AddressMode::ClampToEdge,
-                mag_filter: wgpu::FilterMode::Linear,
-                min_filter: wgpu::FilterMode::Nearest,
-                mipmap_filter: wgpu::FilterMode::Nearest,
-                ..Default::default()
-            }));
+        let diffuse_sampler = Arc::new(state.device.create_sampler(&wgpu::SamplerDescriptor {
+            address_mode_u: wgpu::AddressMode::ClampToEdge,
+            address_mode_v: wgpu::AddressMode::ClampToEdge,
+            address_mode_w: wgpu::AddressMode::ClampToEdge,
+            mag_filter: wgpu::FilterMode::Linear,
+            min_filter: wgpu::FilterMode::Nearest,
+            mipmap_filter: wgpu::FilterMode::Nearest,
+            ..Default::default()
+        }));
         Self {
             shared: Arc::new(SharedGraphicsContext {
                 device: state.device.clone(),
@@ -123,7 +128,8 @@ impl<'a> RenderContext<'a> {
         label: Option<&str>,
     ) -> RenderPipeline {
         let render_pipeline_layout =
-            self.shared.device
+            self.shared
+                .device
                 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
                     label: Some(label.unwrap_or("Render Pipeline Descriptor")),
                     bind_group_layouts: bind_group_layouts.as_slice(),
@@ -131,7 +137,8 @@ impl<'a> RenderContext<'a> {
                 });
 
         let render_pipeline =
-            self.shared.device
+            self.shared
+                .device
                 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
                     label: Some(label.unwrap_or("Render Pipeline")),
                     layout: Some(&render_pipeline_layout),
@@ -181,7 +188,8 @@ impl<'a> RenderContext<'a> {
     }
 
     pub fn clear_colour(&mut self, color: Color) -> RenderPass<'static> {
-        self.frame.encoder
+        self.frame
+            .encoder
             .begin_render_pass(&wgpu::RenderPassDescriptor {
                 label: Some("Render Pass"),
                 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
@@ -191,7 +199,6 @@ impl<'a> RenderContext<'a> {
                         load: wgpu::LoadOp::Clear(color),
                         store: wgpu::StoreOp::Store,
                     },
-                    depth_slice: None,
                 })],
                 depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
                     view: &self.frame.depth_texture.view,
@@ -208,14 +215,18 @@ impl<'a> RenderContext<'a> {
     }
 }
 
-// A nice little struct that stored basic information about a WGPU shader. 
+// A nice little struct that stored basic information about a WGPU shader.
 pub struct Shader {
     pub label: String,
     pub module: ShaderModule,
 }
 
 impl Shader {
-    pub fn new(graphics: Arc<SharedGraphicsContext>, shader_file_contents: &str, label: Option<&str>) -> Self {
+    pub fn new(
+        graphics: Arc<SharedGraphicsContext>,
+        shader_file_contents: &str,
+        label: Option<&str>,
+    ) -> Self {
         let module = graphics
             .device
             .create_shader_module(wgpu::ShaderModuleDescriptor {
@@ -236,7 +247,7 @@ impl Shader {
 }
 
 #[derive(Clone)]
-/// Describes a texture, like an image of some sort. Can be a normal texture on a model or a viewport or depth texture. 
+/// Describes a texture, like an image of some sort. Can be a normal texture on a model or a viewport or depth texture.
 pub struct Texture {
     pub texture: wgpu::Texture,
     pub sampler: Sampler,
@@ -250,10 +261,10 @@ impl Texture {
     /// Describes the depth format for all Texture related functions in WGPU to use. Makes life easier
     pub const DEPTH_FORMAT: TextureFormat = TextureFormat::Depth32Float;
 
-    /// Creates a new Texture from the bytes of an image. This function is blocking, and takes roughly 4 seconds to 
-    /// convert from the image to RGBA, which can cause issues. There are better options, such as doing it yourself. 
-    /// 
-    /// Once async is implemented, this will be a better use. 
+    /// Creates a new Texture from the bytes of an image. This function is blocking, and takes roughly 4 seconds to
+    /// convert from the image to RGBA, which can cause issues. There are better options, such as doing it yourself.
+    ///
+    /// Once async is implemented, this will be a better use.
     pub fn new(graphics: Arc<SharedGraphicsContext>, diffuse_bytes: &[u8]) -> Self {
         let start = Instant::now();
         let diffuse_image = image::load_from_memory(diffuse_bytes).unwrap();
@@ -261,7 +272,10 @@ impl Texture {
 
         let start = Instant::now();
         let diffuse_rgba = diffuse_image.to_rgba8();
-        println!("Converting diffuse image to rgba8 took {:?}", start.elapsed());
+        println!(
+            "Converting diffuse image to rgba8 took {:?}",
+            start.elapsed()
+        );
 
         let dimensions = diffuse_image.dimensions();
         let texture_size = wgpu::Extent3d {
@@ -271,18 +285,16 @@ impl Texture {
         };
 
         let start = Instant::now();
-        let diffuse_texture = graphics
-            .device
-            .create_texture(&wgpu::TextureDescriptor {
-                label: Some("diffuse_texture"),
-                size: texture_size,
-                mip_level_count: 1,
-                sample_count: 1,
-                dimension: wgpu::TextureDimension::D2,
-                format: wgpu::TextureFormat::Rgba8Unorm,
-                usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
-                view_formats: &[],
-            });
+        let diffuse_texture = graphics.device.create_texture(&wgpu::TextureDescriptor {
+            label: Some("diffuse_texture"),
+            size: texture_size,
+            mip_level_count: 1,
+            sample_count: 1,
+            dimension: wgpu::TextureDimension::D2,
+            format: wgpu::TextureFormat::Rgba8Unorm,
+            usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
+            view_formats: &[],
+        });
         println!("Creating new diffuse texture took {:?}", start.elapsed());
 
         let start = Instant::now();
@@ -301,41 +313,41 @@ impl Texture {
             },
             texture_size,
         );
-        println!("Writing texture to graphics queue took {:?}", start.elapsed());
+        println!(
+            "Writing texture to graphics queue took {:?}",
+            start.elapsed()
+        );
 
         let start = Instant::now();
         let diffuse_texture_view = diffuse_texture.create_view(&TextureViewDescriptor::default());
-        let diffuse_sampler = graphics
-            .device
-            .create_sampler(&wgpu::SamplerDescriptor {
-                address_mode_u: wgpu::AddressMode::ClampToEdge,
-                address_mode_v: wgpu::AddressMode::ClampToEdge,
-                address_mode_w: wgpu::AddressMode::ClampToEdge,
-                mag_filter: wgpu::FilterMode::Linear,
-                min_filter: wgpu::FilterMode::Nearest,
-                mipmap_filter: wgpu::FilterMode::Nearest,
-                ..Default::default()
-            });
+        let diffuse_sampler = graphics.device.create_sampler(&wgpu::SamplerDescriptor {
+            address_mode_u: wgpu::AddressMode::ClampToEdge,
+            address_mode_v: wgpu::AddressMode::ClampToEdge,
+            address_mode_w: wgpu::AddressMode::ClampToEdge,
+            mag_filter: wgpu::FilterMode::Linear,
+            min_filter: wgpu::FilterMode::Nearest,
+            mipmap_filter: wgpu::FilterMode::Nearest,
+            ..Default::default()
+        });
         println!("Creating sampler took {:?}", start.elapsed());
 
         let start = Instant::now();
-        let diffuse_bind_group =
-            graphics
-                .device
-                .create_bind_group(&wgpu::BindGroupDescriptor {
-                    layout: &graphics.texture_bind_layout,
-                    entries: &[
-                        wgpu::BindGroupEntry {
-                            binding: 0,
-                            resource: wgpu::BindingResource::TextureView(&diffuse_texture_view),
-                        },
-                        wgpu::BindGroupEntry {
-                            binding: 1,
-                            resource: wgpu::BindingResource::Sampler(&diffuse_sampler),
-                        },
-                    ],
-                    label: Some("texture_bind_group"),
-                });
+        let diffuse_bind_group = graphics
+            .device
+            .create_bind_group(&wgpu::BindGroupDescriptor {
+                layout: &graphics.texture_bind_layout,
+                entries: &[
+                    wgpu::BindGroupEntry {
+                        binding: 0,
+                        resource: wgpu::BindingResource::TextureView(&diffuse_texture_view),
+                    },
+                    wgpu::BindGroupEntry {
+                        binding: 1,
+                        resource: wgpu::BindingResource::Sampler(&diffuse_sampler),
+                    },
+                ],
+                label: Some("texture_bind_group"),
+            });
         println!("Creating diffuse bind group took {:?}", start.elapsed());
         println!("Done creating texture");
         Self {
@@ -348,7 +360,7 @@ impl Texture {
         }
     }
 
-    /// Creates a new depth texture. This is an internal function. 
+    /// Creates a new depth texture. This is an internal function.
     pub fn create_depth_texture(
         config: &SurfaceConfiguration,
         device: &Device,
@@ -443,8 +455,8 @@ impl Texture {
         self.bind_group.as_ref().unwrap()
     }
 
-    /// Alternative to [`Texture::new()`], which uses an existing rgba data buffer compared to new which synchronously 
-    /// converts the image to RGBA form. 
+    /// Alternative to [`Texture::new()`], which uses an existing rgba data buffer compared to new which synchronously
+    /// converts the image to RGBA form.
     pub(crate) fn from_rgba_buffer(
         graphics: Arc<SharedGraphicsContext>,
         rgba_data: &[u8],
@@ -467,7 +479,10 @@ impl Texture {
             usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
             view_formats: &[],
         });
-        println!("Creating new diffuse texture took {:?}", create_start.elapsed());
+        println!(
+            "Creating new diffuse texture took {:?}",
+            create_start.elapsed()
+        );
 
         let write_start = Instant::now();
         graphics.queue.write_texture(
@@ -485,7 +500,10 @@ impl Texture {
             },
             texture_size,
         );
-        println!("Writing texture to graphics queue took {:?}", write_start.elapsed());
+        println!(
+            "Writing texture to graphics queue took {:?}",
+            write_start.elapsed()
+        );
 
         let sampler_start = Instant::now();
         let diffuse_sampler = graphics.device.create_sampler(&wgpu::SamplerDescriptor {
@@ -502,21 +520,26 @@ impl Texture {
         let view = diffuse_texture.create_view(&wgpu::TextureViewDescriptor::default());
 
         let bind_group_start = Instant::now();
-        let diffuse_bind_group = graphics.device.create_bind_group(&wgpu::BindGroupDescriptor {
-            layout: &graphics.texture_bind_layout,
-            entries: &[
-                wgpu::BindGroupEntry {
-                    binding: 0,
-                    resource: wgpu::BindingResource::TextureView(&view),
-                },
-                wgpu::BindGroupEntry {
-                    binding: 1,
-                    resource: wgpu::BindingResource::Sampler(&diffuse_sampler),
-                },
-            ],
-            label: Some("texture_bind_group"),
-        });
-        println!("Creating diffuse bind group took {:?}", bind_group_start.elapsed());
+        let diffuse_bind_group = graphics
+            .device
+            .create_bind_group(&wgpu::BindGroupDescriptor {
+                layout: &graphics.texture_bind_layout,
+                entries: &[
+                    wgpu::BindGroupEntry {
+                        binding: 0,
+                        resource: wgpu::BindingResource::TextureView(&view),
+                    },
+                    wgpu::BindGroupEntry {
+                        binding: 1,
+                        resource: wgpu::BindingResource::Sampler(&diffuse_sampler),
+                    },
+                ],
+                label: Some("texture_bind_group"),
+            });
+        println!(
+            "Creating diffuse bind group took {:?}",
+            bind_group_start.elapsed()
+        );
 
         println!("Done creating texture");
 
@@ -530,7 +553,7 @@ impl Texture {
         }
     }
 
-    /// Creates a new [`Texture`] with a specified sampler (wgpu) and already converted RGBA byte buffer. 
+    /// Creates a new [`Texture`] with a specified sampler (wgpu) and already converted RGBA byte buffer.
     pub fn new_with_sampler_with_rgba_buffer(
         graphics: Arc<SharedGraphicsContext>,
         rgba_data: &[u8],
@@ -554,7 +577,10 @@ impl Texture {
             usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
             view_formats: &[],
         });
-        println!("Creating new diffuse texture took {:?}", create_start.elapsed());
+        println!(
+            "Creating new diffuse texture took {:?}",
+            create_start.elapsed()
+        );
 
         let write_start = Instant::now();
         graphics.queue.write_texture(
@@ -572,40 +598,46 @@ impl Texture {
             },
             texture_size,
         );
-        println!("Writing texture to graphics queue took {:?}", write_start.elapsed());
+        println!(
+            "Writing texture to graphics queue took {:?}",
+            write_start.elapsed()
+        );
 
         let sampler_start = Instant::now();
-        let diffuse_sampler = graphics
-            .device
-            .create_sampler(&wgpu::SamplerDescriptor {
-                address_mode_u: address_mode,
-                address_mode_v: address_mode,
-                address_mode_w: address_mode,
-                mag_filter: wgpu::FilterMode::Linear,
-                min_filter: wgpu::FilterMode::Nearest,
-                mipmap_filter: wgpu::FilterMode::Nearest,
-                ..Default::default()
-            });      
+        let diffuse_sampler = graphics.device.create_sampler(&wgpu::SamplerDescriptor {
+            address_mode_u: address_mode,
+            address_mode_v: address_mode,
+            address_mode_w: address_mode,
+            mag_filter: wgpu::FilterMode::Linear,
+            min_filter: wgpu::FilterMode::Nearest,
+            mipmap_filter: wgpu::FilterMode::Nearest,
+            ..Default::default()
+        });
         println!("Creating sampler took {:?}", sampler_start.elapsed());
 
         let view = diffuse_texture.create_view(&wgpu::TextureViewDescriptor::default());
 
         let bind_group_start = Instant::now();
-        let diffuse_bind_group = graphics.device.create_bind_group(&wgpu::BindGroupDescriptor {
-            layout: &graphics.texture_bind_layout,
-            entries: &[
-                wgpu::BindGroupEntry {
-                    binding: 0,
-                    resource: wgpu::BindingResource::TextureView(&view),
-                },
-                wgpu::BindGroupEntry {
-                    binding: 1,
-                    resource: wgpu::BindingResource::Sampler(&diffuse_sampler),
-                },
-            ],
-            label: Some("texture_bind_group"),
-        });
-        println!("Creating diffuse bind group took {:?}", bind_group_start.elapsed());
+        let diffuse_bind_group = graphics
+            .device
+            .create_bind_group(&wgpu::BindGroupDescriptor {
+                layout: &graphics.texture_bind_layout,
+                entries: &[
+                    wgpu::BindGroupEntry {
+                        binding: 0,
+                        resource: wgpu::BindingResource::TextureView(&view),
+                    },
+                    wgpu::BindGroupEntry {
+                        binding: 1,
+                        resource: wgpu::BindingResource::Sampler(&diffuse_sampler),
+                    },
+                ],
+                label: Some("texture_bind_group"),
+            });
+        println!(
+            "Creating diffuse bind group took {:?}",
+            bind_group_start.elapsed()
+        );
 
         println!("Done creating texture");
 
@@ -620,9 +652,9 @@ impl Texture {
     }
 
     /// Creates a new [`Texture`] with a specified sampler (wgpu).
-    /// 
-    /// This function decodes the image to RGBA, which can take a long time. This function is not 
-    /// recommended to be used until you have async working. 
+    ///
+    /// This function decodes the image to RGBA, which can take a long time. This function is not
+    /// recommended to be used until you have async working.
     pub fn new_with_sampler(
         graphics: Arc<SharedGraphicsContext>,
         diffuse_bytes: &[u8],
@@ -638,18 +670,16 @@ impl Texture {
             depth_or_array_layers: 1,
         };
 
-        let diffuse_texture = graphics
-            .device
-            .create_texture(&wgpu::TextureDescriptor {
-                label: Some("diffuse_texture"),
-                size: texture_size,
-                mip_level_count: 1,
-                sample_count: 1,
-                dimension: wgpu::TextureDimension::D2,
-                format: wgpu::TextureFormat::Rgba8Unorm,
-                usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
-                view_formats: &[],
-            });
+        let diffuse_texture = graphics.device.create_texture(&wgpu::TextureDescriptor {
+            label: Some("diffuse_texture"),
+            size: texture_size,
+            mip_level_count: 1,
+            sample_count: 1,
+            dimension: wgpu::TextureDimension::D2,
+            format: wgpu::TextureFormat::Rgba8Unorm,
+            usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
+            view_formats: &[],
+        });
 
         graphics.queue.write_texture(
             wgpu::TexelCopyTextureInfo {
@@ -668,36 +698,33 @@ impl Texture {
         );
 
         let diffuse_texture_view = diffuse_texture.create_view(&TextureViewDescriptor::default());
-        let diffuse_sampler = graphics
+        let diffuse_sampler = graphics.device.create_sampler(&wgpu::SamplerDescriptor {
+            address_mode_u: address_mode,
+            address_mode_v: address_mode,
+            address_mode_w: address_mode,
+            mag_filter: wgpu::FilterMode::Linear,
+            min_filter: wgpu::FilterMode::Nearest,
+            mipmap_filter: wgpu::FilterMode::Nearest,
+            ..Default::default()
+        });
+
+        let diffuse_bind_group = graphics
             .device
-            .create_sampler(&wgpu::SamplerDescriptor {
-                address_mode_u: address_mode,
-                address_mode_v: address_mode,
-                address_mode_w: address_mode,
-                mag_filter: wgpu::FilterMode::Linear,
-                min_filter: wgpu::FilterMode::Nearest,
-                mipmap_filter: wgpu::FilterMode::Nearest,
-                ..Default::default()
+            .create_bind_group(&wgpu::BindGroupDescriptor {
+                layout: &graphics.texture_bind_layout,
+                entries: &[
+                    wgpu::BindGroupEntry {
+                        binding: 0,
+                        resource: wgpu::BindingResource::TextureView(&diffuse_texture_view),
+                    },
+                    wgpu::BindGroupEntry {
+                        binding: 1,
+                        resource: wgpu::BindingResource::Sampler(&diffuse_sampler),
+                    },
+                ],
+                label: Some("texture_bind_group"),
             });
 
-        let diffuse_bind_group =
-            graphics
-                .device
-                .create_bind_group(&wgpu::BindGroupDescriptor {
-                    layout: &graphics.texture_bind_layout,
-                    entries: &[
-                        wgpu::BindGroupEntry {
-                            binding: 0,
-                            resource: wgpu::BindingResource::TextureView(&diffuse_texture_view),
-                        },
-                        wgpu::BindGroupEntry {
-                            binding: 1,
-                            resource: wgpu::BindingResource::Sampler(&diffuse_sampler),
-                        },
-                    ],
-                    label: Some("texture_bind_group"),
-                });
-
         Self {
             texture: diffuse_texture,
             sampler: diffuse_sampler,
@@ -708,14 +735,17 @@ impl Texture {
         }
     }
 
-    /// A helper function that loads the texture from a path. Still returns the same [`Texture`]. 
-    pub async fn load_texture(graphics: Arc<SharedGraphicsContext>, path: &PathBuf) -> anyhow::Result<Texture> {
+    /// A helper function that loads the texture from a path. Still returns the same [`Texture`].
+    pub async fn load_texture(
+        graphics: Arc<SharedGraphicsContext>,
+        path: &PathBuf,
+    ) -> anyhow::Result<Texture> {
         let data = fs::read(path)?;
         Ok(Self::new(graphics.clone(), &data))
     }
 }
 
-#[derive(Default)]
+#[derive(Default, Clone)]
 pub struct Instance {
     pub position: DVec3,
     pub rotation: DQuat,
diff --git a/dropbear-engine/src/lib.rs b/dropbear-engine/src/lib.rs
index 542a1d3..ba51e94 100644
--- a/dropbear-engine/src/lib.rs
+++ b/dropbear-engine/src/lib.rs
@@ -17,7 +17,7 @@ use app_dirs2::{AppDataType, AppInfo};
 use chrono::Local;
 use colored::Colorize;
 use egui::TextureId;
-use egui_wgpu_backend::ScreenDescriptor;
+use egui_wgpu::ScreenDescriptor;
 use env_logger::Builder;
 use futures::executor::block_on;
 use gilrs::{Gilrs, GilrsBuilder};
@@ -44,10 +44,7 @@ use winit::{
     window::Window,
 };
 
-use crate::{
-    egui_renderer::EguiRenderer,
-    graphics::Texture,
-};
+use crate::{egui_renderer::EguiRenderer, graphics::Texture};
 
 pub use gilrs;
 use log::LevelFilter;
@@ -104,10 +101,21 @@ impl State {
             .await?;
 
         let info = adapter.get_info();
+        let os_info = os_info::get();
         log::info!(
             "\n==================== BACKEND INFO ====================
 Backend: {}
 
+Software:
+    Architecture: {:?}
+    Bitness: {:?}
+    Codename: {:?}
+    Edition: {:?}
+    Os Type: {:?}
+    Version: {:?}
+    TLDR: {}
+
+
 Hardware:
     Adapter Name: {}
     Vendor: {}
@@ -118,6 +126,13 @@ Hardware:
 =======================================================
 ",
             info.backend.to_string(),
+            os_info.architecture(),
+            os_info.bitness(),
+            os_info.codename(),
+            os_info.edition(),
+            os_info.os_type(),
+            os_info.version(),
+            os_info,
             info.name,
             info.vendor,
             info.device,
@@ -173,13 +188,19 @@ Hardware:
                 label: Some("texture_bind_group_layout"),
             });
 
-        let mut egui_renderer = Arc::new(Mutex::new(EguiRenderer::new(&device, config.format, 1, &window)));
-
-        let texture_id = Arc::get_mut(&mut egui_renderer).unwrap().lock().renderer().egui_texture_from_wgpu_texture(
+        let mut egui_renderer = Arc::new(Mutex::new(EguiRenderer::new(
             &device,
-            &viewport_texture.view,
-            wgpu::FilterMode::Linear,
-        );
+            config.format,
+            None,
+            1,
+            &window,
+        )));
+
+        let texture_id = Arc::get_mut(&mut egui_renderer)
+            .unwrap()
+            .lock()
+            .renderer()
+            .register_native_texture(&device, &viewport_texture.view, wgpu::FilterMode::Linear);
 
         let result = Self {
             surface,
@@ -212,15 +233,15 @@ Hardware:
             Texture::create_depth_texture(&self.config, &self.device, Some("depth texture"));
         self.viewport_texture =
             Texture::create_viewport_texture(&self.config, &self.device, Some("viewport texture"));
-        self.texture_id = Arc::get_mut(&mut self
-            .egui_renderer).unwrap().lock()
+        self.egui_renderer
+            .lock()
             .renderer()
-            .egui_texture_from_wgpu_texture(
+            .update_egui_texture_from_wgpu_texture(
                 &self.device,
                 &self.viewport_texture.view,
                 wgpu::FilterMode::Linear,
-            )
-            .into();
+                *self.texture_id,
+            );
     }
 
     /// Asynchronously renders the scene and the egui renderer. I don't know what else to say.
@@ -261,12 +282,9 @@ Hardware:
             },
         };
 
-        let size = self.window.inner_size();
-
         let screen_descriptor = ScreenDescriptor {
-            physical_width: size.width,
-            physical_height: size.height,
-            scale_factor: self.window.scale_factor() as f32,
+            size_in_pixels: [self.config.width, self.config.height],
+            pixels_per_point: self.window.scale_factor() as f32,
         };
 
         let view = output
@@ -280,10 +298,10 @@ Hardware:
 
         let viewport_view = { &self.viewport_texture.view.clone() };
 
-        self.egui_renderer.lock().begin_frame();
+        self.egui_renderer.lock().begin_frame(&self.window);
 
         let mut graphics = graphics::RenderContext::from_state(self, viewport_view, &mut encoder);
-        
+
         scene_manager
             .update(previous_dt, &mut graphics, event_loop)
             .await;
@@ -407,14 +425,16 @@ impl App {
     /// - setup: A closure that can initialise the first scenes, such as a menu or the game itself.
     /// It takes an input of a scene manager and an input manager, and expects you to return back the changed
     /// managers.
-    pub fn run<F>(config: WindowConfiguration, app_name: &str, setup: F) -> anyhow::Result<()>
+    pub async fn run<F>(config: WindowConfiguration, app_name: &str, setup: F) -> anyhow::Result<()>
     where
         F: FnOnce(scene::Manager, input::Manager) -> (scene::Manager, input::Manager),
     {
         let log_dir = app_dirs2::app_root(AppDataType::UserData, &config.app_info)
             .expect("Failed to get app data directory")
             .join("logs");
-        std::fs::create_dir_all(&log_dir).expect("Failed to create log dir");
+        tokio::fs::create_dir_all(&log_dir)
+            .await
+            .expect("Failed to create log dir");
 
         let datetime_str = Local::now().format("%Y-%m-%d_%H-%M-%S");
         let log_filename = format!("{}.{}.log", app_name, datetime_str);
@@ -562,7 +582,10 @@ impl ApplicationHandler for App {
             None => return,
         };
 
-        state.egui_renderer.lock().handle_input(&event);
+        state
+            .egui_renderer
+            .lock()
+            .handle_input(&state.window, &event);
 
         match event {
             WindowEvent::CloseRequested => {
diff --git a/dropbear-engine/src/lighting.rs b/dropbear-engine/src/lighting.rs
index ff2a3e5..b11659c 100644
--- a/dropbear-engine/src/lighting.rs
+++ b/dropbear-engine/src/lighting.rs
@@ -212,13 +212,16 @@ impl LazyType for LazyLight {
 
     fn poke(self, graphics: Arc<SharedGraphicsContext>) -> anyhow::Result<Self::T> {
         let label_str = self.label.clone().unwrap_or_else(|| "Light".to_string());
-        
+
         let forward = DVec3::new(0.0, 0.0, -1.0);
         let direction = self.transform.rotation * forward;
 
         let uniform = LightUniform {
             position: dvec3_to_uniform_array(self.transform.position),
-            direction: dvec3_direction_to_uniform_array(direction, self.light_component.outer_cutoff_angle),
+            direction: dvec3_direction_to_uniform_array(
+                direction,
+                self.light_component.outer_cutoff_angle,
+            ),
             colour: dvec3_colour_to_uniform_array(
                 self.light_component.colour * self.light_component.intensity as f64,
                 self.light_component.light_type,
@@ -232,33 +235,39 @@ impl LazyType for LazyLight {
         let cube_model = if let Some(lazy_model) = self.cube_lazy_model {
             lazy_model.poke(graphics.clone())?
         } else {
-            anyhow::bail!("The light cube LazyModel has not been initialised yet. Use Light::new(/** params */).preload_cube_model() to preload it (which is required)");
+            anyhow::bail!(
+                "The light cube LazyModel has not been initialised yet. Use Light::new(/** params */).preload_cube_model() to preload it (which is required)"
+            );
         };
 
         let buffer = graphics.create_uniform(uniform, self.label.as_deref());
 
-        let layout = graphics.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
-            entries: &[wgpu::BindGroupLayoutEntry {
-                binding: 0,
-                visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
-                ty: wgpu::BindingType::Buffer {
-                    ty: wgpu::BufferBindingType::Uniform,
-                    has_dynamic_offset: false,
-                    min_binding_size: None,
-                },
-                count: None,
-            }],
-            label: self.label.as_deref(),
-        });
-
-        let bind_group = graphics.device.create_bind_group(&wgpu::BindGroupDescriptor {
-            layout: &layout,
-            entries: &[wgpu::BindGroupEntry {
-                binding: 0,
-                resource: buffer.as_entire_binding(),
-            }],
-            label: self.label.as_deref(),
-        });
+        let layout = graphics
+            .device
+            .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
+                entries: &[wgpu::BindGroupLayoutEntry {
+                    binding: 0,
+                    visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
+                    ty: wgpu::BindingType::Buffer {
+                        ty: wgpu::BufferBindingType::Uniform,
+                        has_dynamic_offset: false,
+                        min_binding_size: None,
+                    },
+                    count: None,
+                }],
+                label: self.label.as_deref(),
+            });
+
+        let bind_group = graphics
+            .device
+            .create_bind_group(&wgpu::BindGroupDescriptor {
+                layout: &layout,
+                entries: &[wgpu::BindGroupEntry {
+                    binding: 0,
+                    resource: buffer.as_entire_binding(),
+                }],
+                label: self.label.as_deref(),
+            });
 
         let instance = Instance::new(
             self.transform.position,
@@ -266,11 +275,14 @@ impl LazyType for LazyLight {
             DVec3::new(0.25, 0.25, 0.25),
         );
 
-        let instance_buffer = graphics.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
-            label: self.label.as_deref().or(Some("instance buffer")),
-            contents: bytemuck::cast_slice(&[instance.to_raw()]),
-            usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
-        });
+        let instance_buffer =
+            graphics
+                .device
+                .create_buffer_init(&wgpu::util::BufferInitDescriptor {
+                    label: self.label.as_deref().or(Some("instance buffer")),
+                    contents: bytemuck::cast_slice(&[instance.to_raw()]),
+                    usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
+                });
 
         log::debug!("Created new light [{}]", label_str);
 
@@ -286,6 +298,7 @@ impl LazyType for LazyLight {
     }
 }
 
+#[derive(Clone)]
 pub struct Light {
     pub uniform: LightUniform,
     cube_model: Model,
@@ -312,7 +325,8 @@ impl Light {
             let lazy_model = Model::lazy_load(
                 include_bytes!("../../resources/cube.glb").to_vec(),
                 result.label.as_deref(),
-            ).await?;
+            )
+            .await?;
             result.cube_lazy_model = Some(lazy_model);
         }
         Ok(result)
@@ -352,22 +366,21 @@ impl Light {
 
         let buffer = graphics.create_uniform(uniform, label.clone());
 
-        let layout =
-            graphics
-                .device
-                .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
-                    entries: &[wgpu::BindGroupLayoutEntry {
-                        binding: 0,
-                        visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
-                        ty: wgpu::BindingType::Buffer {
-                            ty: wgpu::BufferBindingType::Uniform,
-                            has_dynamic_offset: false,
-                            min_binding_size: None,
-                        },
-                        count: None,
-                    }],
-                    label: label.clone(),
-                });
+        let layout = graphics
+            .device
+            .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
+                entries: &[wgpu::BindGroupLayoutEntry {
+                    binding: 0,
+                    visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
+                    ty: wgpu::BindingType::Buffer {
+                        ty: wgpu::BufferBindingType::Uniform,
+                        has_dynamic_offset: false,
+                        min_binding_size: None,
+                    },
+                    count: None,
+                }],
+                label: label.clone(),
+            });
 
         let bind_group = graphics
             .device
@@ -453,6 +466,7 @@ impl Light {
     }
 }
 
+#[derive(Clone)]
 pub struct LightManager {
     pub pipeline: Option<RenderPipeline>,
     light_array_buffer: Option<Buffer>,
@@ -472,22 +486,21 @@ impl LightManager {
     }
 
     pub fn create_light_array_resources(&mut self, graphics: Arc<SharedGraphicsContext>) {
-        let layout =
-            graphics
-                .device
-                .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
-                    entries: &[wgpu::BindGroupLayoutEntry {
-                        binding: 0,
-                        visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
-                        ty: wgpu::BindingType::Buffer {
-                            ty: wgpu::BufferBindingType::Uniform,
-                            has_dynamic_offset: false,
-                            min_binding_size: None,
-                        },
-                        count: None,
-                    }],
-                    label: Some("Light Array Layout"),
-                });
+        let layout = graphics
+            .device
+            .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
+                entries: &[wgpu::BindGroupLayoutEntry {
+                    binding: 0,
+                    visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
+                    ty: wgpu::BindingType::Buffer {
+                        ty: wgpu::BufferBindingType::Uniform,
+                        has_dynamic_offset: false,
+                        min_binding_size: None,
+                    },
+                    count: None,
+                }],
+                label: Some("Light Array Layout"),
+            });
 
         let buffer = graphics.create_uniform(LightArrayUniform::default(), Some("Light Array"));
 
@@ -505,6 +518,7 @@ impl LightManager {
         self.light_array_layout = Some(layout);
         self.light_array_buffer = Some(buffer);
         self.light_array_bind_group = Some(bind_group);
+        log::debug!("Created light array resources")
     }
 
     pub fn update(&mut self, graphics: Arc<SharedGraphicsContext>, world: &hecs::World) {
diff --git a/dropbear-engine/src/model.rs b/dropbear-engine/src/model.rs
index fccda56..87ef2fe 100644
--- a/dropbear-engine/src/model.rs
+++ b/dropbear-engine/src/model.rs
@@ -8,12 +8,12 @@ use parking_lot::Mutex;
 //     material::{DataContent, TextureType},
 //     scene::{PostProcess, Scene},
 // };
+use rayon::prelude::*;
 use std::collections::HashMap;
 use std::sync::Arc;
 use std::time::Instant;
 use std::{mem, ops::Range, path::PathBuf};
 use wgpu::{BufferAddress, VertexAttribute, VertexBufferLayout, util::DeviceExt};
-use rayon::prelude::*;
 
 pub const GREY_TEXTURE_BYTES: &'static [u8] = include_bytes!("../../resources/grey.png");
 
@@ -86,56 +86,66 @@ impl LazyType for LazyModel {
 
     fn poke(self, graphics: Arc<SharedGraphicsContext>) -> anyhow::Result<Self::T> {
         let start = Instant::now();
-        
+
         let cache_key = self.parsed_data.label.clone();
         if let Some(cached_model) = MEMORY_MODEL_CACHE.lock().get(&cache_key) {
             log::debug!("Model loaded from cache during poke: {:?}", cache_key);
             return Ok(cached_model.clone());
         }
 
-        log::debug!("Creating GPU resources for model: {:?}", self.parsed_data.label);
+        log::debug!(
+            "Creating GPU resources for model: {:?}",
+            self.parsed_data.label
+        );
 
         let mut materials = Vec::new();
         for material_data in &self.parsed_data.material_data {
             let texture_start = Instant::now();
-            
+
             let diffuse_texture = Texture::from_rgba_buffer(
-                graphics.clone(), 
-                &material_data.rgba_data, 
-                material_data.dimensions
+                graphics.clone(),
+                &material_data.rgba_data,
+                material_data.dimensions,
             );
-            
+
             let bind_group = diffuse_texture.bind_group().to_owned();
-            
+
             materials.push(Material {
                 name: material_data.name.clone(),
                 diffuse_texture,
                 bind_group,
             });
-            
-            log::debug!("Created GPU texture for material '{}' in {:?}", 
-                        material_data.name, texture_start.elapsed());
+
+            log::debug!(
+                "Created GPU texture for material '{}' in {:?}",
+                material_data.name,
+                texture_start.elapsed()
+            );
         }
 
         let mut meshes = Vec::new();
         for mesh_data in &self.parsed_data.mesh_data {
             let buffer_start = Instant::now();
 
-            let vertex_buffer = graphics.clone()
-                .device
-                .create_buffer_init(&wgpu::util::BufferInitDescriptor {
-                    label: Some(&format!("{} Vertex Buffer", mesh_data.name)),
-                    contents: bytemuck::cast_slice(&mesh_data.vertices),
-                    usage: wgpu::BufferUsages::VERTEX,
-                });
+            let vertex_buffer =
+                graphics
+                    .clone()
+                    .device
+                    .create_buffer_init(&wgpu::util::BufferInitDescriptor {
+                        label: Some(&format!("{} Vertex Buffer", mesh_data.name)),
+                        contents: bytemuck::cast_slice(&mesh_data.vertices),
+                        usage: wgpu::BufferUsages::VERTEX,
+                    });
 
-            let index_buffer = graphics.clone()
-                .device
-                .create_buffer_init(&wgpu::util::BufferInitDescriptor {
-                    label: Some(&format!("{} Index Buffer", mesh_data.name)),
-                    contents: bytemuck::cast_slice(&mesh_data.indices),
-                    usage: wgpu::BufferUsages::INDEX,
-                });
+            let index_buffer =
+                graphics
+                    .clone()
+                    .device
+                    .create_buffer_init(&wgpu::util::BufferInitDescriptor {
+                        label: Some(&format!("{} Index Buffer", mesh_data.name)),
+                        contents: bytemuck::cast_slice(&mesh_data.indices),
+                        usage: wgpu::BufferUsages::INDEX,
+                    });
 
             meshes.push(Mesh {
                 name: mesh_data.name.clone(),
@@ -145,8 +155,11 @@ impl LazyType for LazyModel {
                 material: mesh_data.material_index,
             });
 
-            log::debug!("Created GPU buffers for mesh '{}' in {:?}", 
-                        mesh_data.name, buffer_start.elapsed());
+            log::debug!(
+                "Created GPU buffers for mesh '{}' in {:?}",
+                mesh_data.name,
+                buffer_start.elapsed()
+            );
         }
 
         let model = Model {
@@ -157,25 +170,26 @@ impl LazyType for LazyModel {
         };
 
         MEMORY_MODEL_CACHE.lock().insert(cache_key, model.clone());
-        log::debug!("Model GPU resource creation completed in {:?}", start.elapsed());
-        
+        log::debug!(
+            "Model GPU resource creation completed in {:?}",
+            start.elapsed()
+        );
+
         Ok(model)
     }
 }
 
-
 impl Model {
-
-    /// Creates a [`LazyModel`]. 
+    /// Creates a [`LazyModel`].
     pub async fn lazy_load(
         buffer: impl AsRef<[u8]>,
         label: Option<&str>,
     ) -> anyhow::Result<LazyModel> {
         let start = Instant::now();
         let label_str = label.unwrap_or("default");
-        
+
         log::debug!("Starting lazy load for model: {:?}", label_str);
-        
+
         let res_ref = ResourceReference::from_bytes(buffer.as_ref());
         let (gltf, buffers, _images) = gltf::import_slice(buffer.as_ref())?;
 
@@ -183,26 +197,27 @@ impl Model {
         for material in gltf.materials() {
             log::debug!("Processing material: {:?}", material.name());
             let material_name = material.name().unwrap_or("Unnamed Material").to_string();
-            
-            let image_data = if let Some(pbr) = material.pbr_metallic_roughness().base_color_texture() {
-                let texture_info = pbr.texture();
-                let image = texture_info.source();
-                match image.source() {
-                    gltf::image::Source::View { view, mime_type: _ } => {
-                        let buffer_data = &buffers[view.buffer().index()];
-                        let start = view.offset();
-                        let end = start + view.length();
-                        buffer_data[start..end].to_vec()
-                    }
-                    gltf::image::Source::Uri { uri, mime_type: _ } => {
-                        log::warn!("External URI textures not supported: {}", uri);
-                        GREY_TEXTURE_BYTES.to_vec()
+
+            let image_data =
+                if let Some(pbr) = material.pbr_metallic_roughness().base_color_texture() {
+                    let texture_info = pbr.texture();
+                    let image = texture_info.source();
+                    match image.source() {
+                        gltf::image::Source::View { view, mime_type: _ } => {
+                            let buffer_data = &buffers[view.buffer().index()];
+                            let start = view.offset();
+                            let end = start + view.length();
+                            buffer_data[start..end].to_vec()
+                        }
+                        gltf::image::Source::Uri { uri, mime_type: _ } => {
+                            log::warn!("External URI textures not supported: {}", uri);
+                            GREY_TEXTURE_BYTES.to_vec()
+                        }
                     }
-                }
-            } else {
-                GREY_TEXTURE_BYTES.to_vec()
-            };
-            
+                } else {
+                    GREY_TEXTURE_BYTES.to_vec()
+                };
+
             texture_data.push((material_name, image_data));
         }
 
@@ -215,14 +230,18 @@ impl Model {
             .into_par_iter()
             .map(|(material_name, image_data)| {
                 let material_start = Instant::now();
-                
-                let diffuse_image = image::load_from_memory(&image_data)
-                    .expect("Failed to load image from memory");
+
+                let diffuse_image =
+                    image::load_from_memory(&image_data).expect("Failed to load image from memory");
                 let diffuse_rgba = diffuse_image.to_rgba8();
                 let dimensions = diffuse_image.dimensions();
-                
-                log::debug!("Processed material '{}' in {:?}", material_name, material_start.elapsed());
-                
+
+                log::debug!(
+                    "Processed material '{}' in {:?}",
+                    material_name,
+                    material_start.elapsed()
+                );
+
                 ParsedMaterialData {
                     name: material_name,
                     rgba_data: diffuse_rgba.into_raw(),
@@ -231,14 +250,17 @@ impl Model {
             })
             .collect();
 
-        log::debug!("Parallel material processing took: {:?}", parallel_start.elapsed());
+        log::debug!(
+            "Parallel material processing took: {:?}",
+            parallel_start.elapsed()
+        );
 
         let mut mesh_data = Vec::new();
         for mesh in gltf.meshes() {
             log::debug!("Processing mesh: {:?}", mesh.name());
             for primitive in mesh.primitives() {
                 let reader = primitive.reader(|buffer| Some(&buffers[buffer.index()]));
-                
+
                 let positions: Vec<[f32; 3]> = reader
                     .read_positions()
                     .ok_or_else(|| anyhow::anyhow!("Mesh missing positions"))?
@@ -289,17 +311,20 @@ impl Model {
             material_data: processed_materials,
         };
 
-        log::debug!("Lazy load completed for model: {:?} in {:?}", label_str, start.elapsed());
-        
+        log::debug!(
+            "Lazy load completed for model: {:?} in {:?}",
+            label_str,
+            start.elapsed()
+        );
+
         Ok(LazyModel { parsed_data })
     }
 
     pub async fn load_from_memory(
         graphics: Arc<SharedGraphicsContext>,
         buffer: impl AsRef<[u8]>,
-        label: Option<&str>
+        label: Option<&str>,
     ) -> anyhow::Result<Model> {
-        println!("========== Benchmarking speed of loading {:?} ==========", label);
         let start = Instant::now();
         let cache_key = label.unwrap_or("default").to_string();
 
@@ -308,6 +333,10 @@ impl Model {
             return Ok(cached_model.clone());
         }
 
+        println!(
+            "========== Benchmarking speed of loading {:?} ==========",
+            label
+        );
         log::debug!("Loading from memory");
         let res_ref = ResourceReference::from_bytes(buffer.as_ref());
 
@@ -318,26 +347,27 @@ impl Model {
         for material in gltf.materials() {
             log::debug!("Processing material: {:?}", material.name());
             let material_name = material.name().unwrap_or("Unnamed Material").to_string();
-            
-            let image_data = if let Some(pbr) = material.pbr_metallic_roughness().base_color_texture() {
-                let texture_info = pbr.texture();
-                let image = texture_info.source();
-                match image.source() {
-                    gltf::image::Source::View { view, mime_type: _ } => {
-                        let buffer_data = &buffers[view.buffer().index()];
-                        let start = view.offset();
-                        let end = start + view.length();
-                        buffer_data[start..end].to_vec()
-                    }
-                    gltf::image::Source::Uri { uri, mime_type: _ } => {
-                        log::warn!("External URI textures not supported: {}", uri);
-                        GREY_TEXTURE_BYTES.to_vec()
+
+            let image_data =
+                if let Some(pbr) = material.pbr_metallic_roughness().base_color_texture() {
+                    let texture_info = pbr.texture();
+                    let image = texture_info.source();
+                    match image.source() {
+                        gltf::image::Source::View { view, mime_type: _ } => {
+                            let buffer_data = &buffers[view.buffer().index()];
+                            let start = view.offset();
+                            let end = start + view.length();
+                            buffer_data[start..end].to_vec()
+                        }
+                        gltf::image::Source::Uri { uri, mime_type: _ } => {
+                            log::warn!("External URI textures not supported: {}", uri);
+                            GREY_TEXTURE_BYTES.to_vec()
+                        }
                     }
-                }
-            } else {
-                GREY_TEXTURE_BYTES.to_vec()
-            };
-            
+                } else {
+                    GREY_TEXTURE_BYTES.to_vec()
+                };
+
             texture_data.push((material_name, image_data));
         }
 
@@ -350,38 +380,49 @@ impl Model {
             .into_par_iter()
             .map(|(material_name, image_data)| {
                 let material_start = Instant::now();
-                
+
                 let load_start = Instant::now();
                 let diffuse_image = image::load_from_memory(&image_data).unwrap();
                 println!("Loading image to memory: {:?}", load_start.elapsed());
-                
+
                 let rgba_start = Instant::now();
                 let diffuse_rgba = diffuse_image.to_rgba8();
-                println!("Converting diffuse image to rgba8 took {:?}", rgba_start.elapsed());
-                
+                println!(
+                    "Converting diffuse image to rgba8 took {:?}",
+                    rgba_start.elapsed()
+                );
+
                 let dimensions = diffuse_image.dimensions();
-                
-                println!("Parallel processing of material '{}' took: {:?}", material_name, material_start.elapsed());
-                
+
+                println!(
+                    "Parallel processing of material '{}' took: {:?}",
+                    material_name,
+                    material_start.elapsed()
+                );
+
                 (material_name, diffuse_rgba.into_raw(), dimensions)
             })
             .collect();
 
-        println!("Total parallel image processing took: {:?}", parallel_start.elapsed());
+        println!(
+            "Total parallel image processing took: {:?}",
+            parallel_start.elapsed()
+        );
 
         let mut materials = Vec::new();
         for (material_name, rgba_data, dimensions) in processed_textures {
             let start = Instant::now();
-            
-            let diffuse_texture = Texture::from_rgba_buffer(graphics.clone(), &rgba_data, dimensions);
+
+            let diffuse_texture =
+                Texture::from_rgba_buffer(graphics.clone(), &rgba_data, dimensions);
             let bind_group = diffuse_texture.bind_group().to_owned();
-            
+
             materials.push(Material {
                 name: material_name,
                 diffuse_texture,
                 bind_group,
             });
-            
+
             println!("Time to create GPU texture: {:?}", start.elapsed());
         }
 
@@ -389,7 +430,7 @@ impl Model {
             log::debug!("Processing mesh: {:?}", mesh.name());
             for primitive in mesh.primitives() {
                 let reader = primitive.reader(|buffer| Some(&buffers[buffer.index()]));
-                
+
                 let positions: Vec<[f32; 3]> = reader
                     .read_positions()
                     .ok_or_else(|| anyhow::anyhow!("Mesh missing positions"))?
@@ -422,21 +463,23 @@ impl Model {
                     .into_u32()
                     .collect();
 
-                let vertex_buffer = graphics
-                    .device
-                    .create_buffer_init(&wgpu::util::BufferInitDescriptor {
-                        label: Some(&format!("{:?} Vertex Buffer", label)),
-                        contents: bytemuck::cast_slice(&vertices),
-                        usage: wgpu::BufferUsages::VERTEX,
-                    });
-
-                let index_buffer = graphics
-                    .device
-                    .create_buffer_init(&wgpu::util::BufferInitDescriptor {
-                        label: Some(&format!("{:?} Index Buffer", label)),
-                        contents: bytemuck::cast_slice(&indices),
-                        usage: wgpu::BufferUsages::INDEX,
-                    });
+                let vertex_buffer =
+                    graphics
+                        .device
+                        .create_buffer_init(&wgpu::util::BufferInitDescriptor {
+                            label: Some(&format!("{:?} Vertex Buffer", label)),
+                            contents: bytemuck::cast_slice(&vertices),
+                            usage: wgpu::BufferUsages::VERTEX,
+                        });
+
+                let index_buffer =
+                    graphics
+                        .device
+                        .create_buffer_init(&wgpu::util::BufferInitDescriptor {
+                            label: Some(&format!("{:?} Index Buffer", label)),
+                            contents: bytemuck::cast_slice(&indices),
+                            usage: wgpu::BufferUsages::INDEX,
+                        });
 
                 let material_index = primitive.material().index().unwrap_or(0);
 
@@ -481,7 +524,7 @@ impl Model {
             return Ok(cached_model.clone());
         }
 
-        let buffer = std::fs::read(path)?;
+        let buffer = tokio::fs::read(path).await?;
         let model = Self::load_from_memory(graphics, buffer, label).await?;
 
         MODEL_CACHE.lock().insert(path_str, model.clone());
diff --git a/dropbear-engine/src/panic.rs b/dropbear-engine/src/panic.rs
index 8d2dfdf..4b68d35 100644
--- a/dropbear-engine/src/panic.rs
+++ b/dropbear-engine/src/panic.rs
@@ -44,5 +44,10 @@ pub fn set_hook() {
                 .set_level(MessageLevel::Error)
                 .show();
         }
+
+        log::error!(
+            "Additional crash info (backtrace): \n{:#?}",
+            backtrace::Backtrace::new()
+        );
     }));
 }
diff --git a/dropbear-engine/src/scene.rs b/dropbear-engine/src/scene.rs
index 5c40286..17bd9fd 100644
--- a/dropbear-engine/src/scene.rs
+++ b/dropbear-engine/src/scene.rs
@@ -74,7 +74,7 @@ impl Manager {
     pub async fn update<'a>(
         &mut self,
         dt: f32,
-        graphics: &mut crate::graphics::RenderContext<'a>,    
+        graphics: &mut crate::graphics::RenderContext<'a>,
         event_loop: &ActiveEventLoop,
     ) {
         // transition scene
diff --git a/dropbear-engine/src/starter/plane.rs b/dropbear-engine/src/starter/plane.rs
index 09b80e3..b759a1c 100644
--- a/dropbear-engine/src/starter/plane.rs
+++ b/dropbear-engine/src/starter/plane.rs
@@ -1,14 +1,14 @@
-/// A straight plane (and some components). Thats it.
-///
-/// Inspiration taken from `https://github.com/4tkbytes/RedLight/blob/main/src/RedLight/Entities/Plane.cs`,
-/// my old game engine made in C sharp, where this is the plane "algorithm".
-use std::sync::Arc;
 use crate::entity::AdoptedEntity;
 use crate::graphics::{SharedGraphicsContext, Texture};
 use crate::model::{Material, Mesh, Model, ModelVertex};
 use crate::utils::{ResourceReference, ResourceReferenceType};
 use futures::executor::block_on;
 use image::GenericImageView;
+/// A straight plane (and some components). Thats it.
+///
+/// Inspiration taken from `https://github.com/4tkbytes/RedLight/blob/main/src/RedLight/Entities/Plane.cs`,
+/// my old game engine made in C sharp, where this is the plane "algorithm".
+use std::sync::Arc;
 use wgpu::{AddressMode, util::DeviceExt};
 
 /// Lazily creates a new Plane. This can only be accessed through the Default trait (which you shouldn't use),
@@ -51,22 +51,20 @@ impl LazyPlaneBuilder {
 
         indices.extend_from_slice(&[0, 2, 1, 1, 2, 3]);
 
-        let vertex_buffer =
-            graphics
-                .device
-                .create_buffer_init(&wgpu::util::BufferInitDescriptor {
-                    label: Some(&format!("{:?} Vertex Buffer", self.label.as_deref())),
-                    contents: bytemuck::cast_slice(&vertices),
-                    usage: wgpu::BufferUsages::VERTEX,
-                });
-        let index_buffer =
-            graphics
-                .device
-                .create_buffer_init(&wgpu::util::BufferInitDescriptor {
-                    label: Some(&format!("{:?} Index Buffer", self.label.as_deref())),
-                    contents: bytemuck::cast_slice(&indices),
-                    usage: wgpu::BufferUsages::INDEX,
-                });
+        let vertex_buffer = graphics
+            .device
+            .create_buffer_init(&wgpu::util::BufferInitDescriptor {
+                label: Some(&format!("{:?} Vertex Buffer", self.label.as_deref())),
+                contents: bytemuck::cast_slice(&vertices),
+                usage: wgpu::BufferUsages::VERTEX,
+            });
+        let index_buffer = graphics
+            .device
+            .create_buffer_init(&wgpu::util::BufferInitDescriptor {
+                label: Some(&format!("{:?} Index Buffer", self.label.as_deref())),
+                contents: bytemuck::cast_slice(&indices),
+                usage: wgpu::BufferUsages::INDEX,
+            });
 
         let mesh = Mesh {
             name: "plane".to_string(),
@@ -80,7 +78,7 @@ impl LazyPlaneBuilder {
             graphics.clone(),
             &self.rgba_data,
             self.dimensions,
-            AddressMode::Repeat
+            AddressMode::Repeat,
         );
         let bind_group = diffuse_texture.bind_group().clone();
         let material = Material {
@@ -100,7 +98,7 @@ impl LazyPlaneBuilder {
     }
 }
 
-/// Creates a plane in the form of an AdoptedEntity. 
+/// Creates a plane in the form of an AdoptedEntity.
 pub struct PlaneBuilder {
     width: f32,
     height: f32,
@@ -190,22 +188,20 @@ impl PlaneBuilder {
 
         indices.extend_from_slice(&[0, 2, 1, 1, 2, 3]);
 
-        let vertex_buffer =
-            graphics
-                .device
-                .create_buffer_init(&wgpu::util::BufferInitDescriptor {
-                    label: Some(&format!("{:?} Vertex Buffer", label)),
-                    contents: bytemuck::cast_slice(&vertices),
-                    usage: wgpu::BufferUsages::VERTEX,
-                });
-        let index_buffer =
-            graphics
-                .device
-                .create_buffer_init(&wgpu::util::BufferInitDescriptor {
-                    label: Some(&format!("{:?} Index Buffer", label)),
-                    contents: bytemuck::cast_slice(&indices),
-                    usage: wgpu::BufferUsages::INDEX,
-                });
+        let vertex_buffer = graphics
+            .device
+            .create_buffer_init(&wgpu::util::BufferInitDescriptor {
+                label: Some(&format!("{:?} Vertex Buffer", label)),
+                contents: bytemuck::cast_slice(&vertices),
+                usage: wgpu::BufferUsages::VERTEX,
+            });
+        let index_buffer = graphics
+            .device
+            .create_buffer_init(&wgpu::util::BufferInitDescriptor {
+                label: Some(&format!("{:?} Index Buffer", label)),
+                contents: bytemuck::cast_slice(&indices),
+                usage: wgpu::BufferUsages::INDEX,
+            });
 
         let mesh = Mesh {
             name: "plane".to_string(),
diff --git a/dropbear-engine/src/utils.rs b/dropbear-engine/src/utils.rs
index dd2693a..05b44b1 100644
--- a/dropbear-engine/src/utils.rs
+++ b/dropbear-engine/src/utils.rs
@@ -76,7 +76,7 @@ impl ResourceReference {
     }
 
     /// Creates a new `ResourceReference` from bytes
-    pub fn from_bytes(bytes: impl AsRef<[u8]>,) -> Self {
+    pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
         Self {
             ref_type: ResourceReferenceType::Bytes(bytes.as_ref().to_vec()),
         }
diff --git a/eucalyptus-core/Cargo.toml b/eucalyptus-core/Cargo.toml
index 08affcd..1abdd68 100644
--- a/eucalyptus-core/Cargo.toml
+++ b/eucalyptus-core/Cargo.toml
@@ -8,7 +8,6 @@ readme = "README.md"
 
 [dependencies]
 anyhow.workspace = true
-app_dirs2.workspace = true
 bincode.workspace = true
 chrono.workspace = true
 dropbear-engine.workspace = true
@@ -24,14 +23,10 @@ parking_lot.workspace = true
 ron.workspace = true
 serde.workspace = true
 winit.workspace = true
-wasmer.workspace = true
-lazy_static.workspace = true
-rayon.workspace = true
-reqwest.workspace = true
-flate2.workspace = true
-tar.workspace = true
 zip.workspace = true
 tokio.workspace = true
+boa_engine.workspace = true
+rayon.workspace = true
 
 [dev-dependencies]
 pollster = "*"
diff --git a/eucalyptus-core/src/dropbear.rs b/eucalyptus-core/src/dropbear.rs
new file mode 100644
index 0000000..fc4cdaa
--- /dev/null
+++ b/eucalyptus-core/src/dropbear.rs
@@ -0,0 +1 @@
+//! A module used for exposing functions
diff --git a/eucalyptus-core/src/input.rs b/eucalyptus-core/src/input.rs
index 52aa21b..3ffac0c 100644
--- a/eucalyptus-core/src/input.rs
+++ b/eucalyptus-core/src/input.rs
@@ -3,10 +3,7 @@ use std::{
     time::{Duration, Instant},
 };
 
-use wasmer::{Function, FunctionEnvMut};
-use winit::{event::MouseButton, keyboard::KeyCode, platform::scancode::PhysicalKeyExtScancode};
-
-use crate::scripting::{DropbearScriptingAPIContext, ScriptableModuleWithEnv};
+use winit::{event::MouseButton, keyboard::KeyCode};
 
 #[derive(Clone)]
 pub struct InputState {
@@ -50,41 +47,3 @@ impl InputState {
         self.pressed_keys.contains(&key)
     }
 }
-
-impl ScriptableModuleWithEnv for InputState {
-    type T = DropbearScriptingAPIContext;
-
-    fn register(env: &wasmer::FunctionEnv<Self::T>, imports: &mut wasmer::Imports, store: &mut wasmer::Store) -> anyhow::Result<()> {
-        fn is_key_pressed_impl(env: FunctionEnvMut<DropbearScriptingAPIContext>, key_code: u32) -> u32 {
-            if let Some(input) = env.data().get_input() {
-                match KeyCode::from_scancode(key_code) {
-                    winit::keyboard::PhysicalKey::Code(key_code) => {
-                        if input.is_key_pressed(key_code) { 1 } else { 0 }
-                    },
-                    winit::keyboard::PhysicalKey::Unidentified(_) => 0,
-                }
-            } else {
-                0
-            }
-        }
-        let is_key_pressed = Function::new_typed_with_env(store, &env, is_key_pressed_impl);
-
-        fn get_mouse_position_impl(env: FunctionEnvMut<DropbearScriptingAPIContext>) -> (f64, f64) {
-            if let Some(input) = env.data().get_input() {
-                input.mouse_pos
-            } else {
-                (0.0, 0.0)
-            }
-        }
-        let get_mouse_position = Function::new_typed_with_env(store, &env, get_mouse_position_impl);
-
-        imports.define(Self::module_name(), "getMousePosition", get_mouse_position);
-        imports.define(Self::module_name(), "isKeyPressed", is_key_pressed);
-
-        Ok(())
-    }
-
-    fn module_name() -> &'static str {
-        "dropbear_input"
-    }
-}
diff --git a/eucalyptus-core/src/lib.rs b/eucalyptus-core/src/lib.rs
index d0382f7..0235c5e 100644
--- a/eucalyptus-core/src/lib.rs
+++ b/eucalyptus-core/src/lib.rs
@@ -1,4 +1,5 @@
 pub mod camera;
+pub mod dropbear;
 pub mod input;
 pub mod logging;
 pub mod scripting;
diff --git a/eucalyptus-core/src/scripting.rs b/eucalyptus-core/src/scripting.rs
index 18005c1..7978e4f 100644
--- a/eucalyptus-core/src/scripting.rs
+++ b/eucalyptus-core/src/scripting.rs
@@ -1,33 +1,15 @@
-pub mod dropbear;
-pub mod build;
-
 use crate::input::InputState;
-use crate::scripting::dropbear::DropbearAPI;
 use crate::states::{EntityNode, PROJECT, SOURCE, ScriptComponent, Value};
+use boa_engine::property::PropertyKey;
+use boa_engine::{Context, JsString, JsValue, Source};
 use dropbear_engine::entity::{AdoptedEntity, Transform};
 use hecs::{Entity, World};
-use wasmer::{FunctionEnv, Imports, Instance, Module, Store, imports};
+use parking_lot::RwLock;
 use std::path::PathBuf;
+use std::str::FromStr;
 use std::sync::Arc;
 use std::{collections::HashMap, fs};
 
-/// A trait that describes a module that can be registered.
-pub trait ScriptableModule {
-    type Data;
-
-    fn register(data: &Self::Data, imports: &mut Imports, store: &mut Store) -> anyhow::Result<()>;
-
-    fn module_name() -> &'static str;
-}
-
-pub trait ScriptableModuleWithEnv {
-    type T;
-
-    fn register(env: &FunctionEnv<Self::T>, imports: &mut Imports, store: &mut Store) -> anyhow::Result<()>;
-
-    fn module_name() -> &'static str;
-}
-
 pub const TEMPLATE_SCRIPT: &'static str = include_str!("../../resources/template.ts");
 
 pub enum ScriptAction {
@@ -46,7 +28,7 @@ pub enum ScriptAction {
 #[derive(Clone)]
 pub struct DropbearScriptingAPIContext {
     pub current_entity: Option<Entity>,
-    current_world: Option<Arc<World>>,
+    current_world: Option<Arc<RwLock<World>>>,
     pub current_input: Option<InputState>,
     pub persistent_data: HashMap<String, Value>,
     pub frame_data: HashMap<String, Value>,
@@ -63,7 +45,7 @@ impl DropbearScriptingAPIContext {
         }
     }
 
-    pub fn set_context(&mut self, entity: Entity, world: Arc<World>, input: &InputState) {
+    pub fn set_context(&mut self, entity: Entity, world: Arc<RwLock<World>>, input: &InputState) {
         self.current_entity = Some(entity);
         self.current_world = Some(world);
         self.current_input = Some(input.clone());
@@ -102,25 +84,20 @@ impl DropbearScriptingAPIContext {
 
     pub fn cleanup_entity_data(&mut self, entity: Entity) {
         let entity_prefix = format!("entity_{:?}_", entity);
-        self.persistent_data.retain(|k, _| !k.starts_with(&entity_prefix));
+        self.persistent_data
+            .retain(|k, _| !k.starts_with(&entity_prefix));
     }
 }
 
 pub struct ScriptManager {
-    pub store: Store,
-    compiled_scripts: HashMap<String, Module>,
-    entity_script_data: HashMap<hecs::Entity, u32>,
+    compiled_scripts: HashMap<String, String>,
     script_context: DropbearScriptingAPIContext,
 }
 
 impl ScriptManager {
     pub fn new() -> anyhow::Result<Self> {
-        let store = Store::default();
-        
         let result = Self {
-            store,
             compiled_scripts: HashMap::new(),
-            entity_script_data: HashMap::new(),
             script_context: DropbearScriptingAPIContext::new(),
         };
 
@@ -128,9 +105,13 @@ impl ScriptManager {
         Ok(result)
     }
 
-    pub fn load_script(&mut self, script_name: &String, script_content: impl AsRef<[u8]>) -> anyhow::Result<String> {
-        let module = Module::new(self.store.engine(), script_content)?;
-        self.compiled_scripts.insert(script_name.clone(), module);
+    pub fn load_script(
+        &mut self,
+        script_name: &String,
+        script_content: String,
+    ) -> anyhow::Result<String> {
+        self.compiled_scripts
+            .insert(script_name.clone(), script_content);
         log::debug!("Loaded script [{}]", script_name);
         Ok(script_name.clone())
     }
@@ -139,36 +120,44 @@ impl ScriptManager {
         &mut self,
         entity_id: hecs::Entity,
         script_name: &str,
-        world: &mut Arc<World>,
-        input_state: &InputState
+        world: Arc<RwLock<World>>,
+        input_state: &InputState,
     ) -> anyhow::Result<()> {
         log_once::debug_once!("init_entity_script: {} for {:?}", script_name, entity_id);
 
-        if let Some(module) = self.compiled_scripts.get(script_name).cloned() {
-            self.script_context.set_context(entity_id, world.clone(), input_state);
-
-            let import_obj = self.create_imports()?;
-            let instance = Instance::new(&mut self.store, &module, &import_obj)?;
-
-            if let Ok(alloc_func) = instance.exports.get_function("__alloc") {
-                let size = std::mem::size_of::<Transform>() as i32;
-                let result = alloc_func.call(&mut self.store, &[size.into()])?;
-                if let Some(wasmer::Value::I32(ptr)) = result.get(0) {
-                    self.entity_script_data.insert(entity_id, *ptr as u32);
-                }
-            }
-
-            self.sync_entity_to_memory(entity_id, world, &instance)?;
-
-            if let Ok(init_func) = instance.exports.get_function("init") {
-                init_func.call(&mut self.store, &[])?;
+        if let Some(script_source) = self.compiled_scripts.get(script_name) {
+            self.script_context
+                .set_context(entity_id, world, input_state);
+
+            let mut context = Context::default();
+            self.expose(&mut context);
+
+            context
+                .eval(Source::from_bytes(script_source.clone().as_bytes()))
+                .map_err(|e| anyhow::anyhow!("{}", e))?;
+
+            let load = context
+                .global_object()
+                .get(
+                    PropertyKey::String(JsString::from_str("load")?),
+                    &mut context,
+                )
+                .map_err(|e| anyhow::anyhow!("{}", e))?;
+
+            if load.is_callable() {
+                let _ = load
+                    .as_callable()
+                    .unwrap()
+                    .call(&JsValue::undefined(), &[], &mut context);
+            } else {
+                log::warn!(
+                    "Unable to call load in script {}: Load is not a callable function",
+                    script_name
+                )
             }
 
-            self.sync_memory_to_entity(entity_id, world, &instance)?;
-
             self.script_context.clear_context();
-
-            Ok(())
+            return Ok(());
         } else {
             Err(anyhow::anyhow!("Script '{}' not found", script_name))
         }
@@ -178,89 +167,58 @@ impl ScriptManager {
         &mut self,
         entity_id: hecs::Entity,
         script_name: &str,
-        world: &mut Arc<World>,
+        world: Arc<RwLock<World>>,
         input_state: &InputState,
         dt: f32,
     ) -> anyhow::Result<()> {
         log_once::debug_once!("Update entity script name: {}", script_name);
 
         if let Some(module) = self.compiled_scripts.get(script_name).cloned() {
-            self.script_context.set_context(entity_id, world.clone(), input_state);
-            
-            let import_object = self.create_imports()?;
-            let instance = Instance::new(&mut self.store, &module, &import_object)?;
-            
-            self.sync_entity_to_memory(entity_id, world, &instance)?;
-            
-            if let Ok(update_func) = instance.exports.get_function("update") {
-                let dt_value = wasmer::Value::F32(dt);
-                update_func.call(&mut self.store, &[dt_value])?;
+            self.script_context
+                .set_context(entity_id, world.clone(), input_state);
+
+            let mut context = Context::default();
+            self.expose(&mut context);
+
+            context
+                .eval(Source::from_bytes(module.as_bytes()))
+                .map_err(|e| anyhow::anyhow!("{}", e))?;
+
+            let update = context
+                .global_object()
+                .get(
+                    PropertyKey::String(JsString::from_str("update")?),
+                    &mut context,
+                )
+                .map_err(|e| anyhow::anyhow!("{}", e))?;
+
+            if update.is_callable() {
+                let dt_val = JsValue::from(dt);
+                let _ = update.as_callable().unwrap().call(
+                    &JsValue::undefined(),
+                    &[dt_val],
+                    &mut context,
+                );
+            } else {
+                log::warn!(
+                    "Unable to call update in script {}: Update is not a callable function",
+                    script_name
+                )
             }
-            
-            self.sync_memory_to_entity(entity_id, world, &instance)?;
-            
+
             self.script_context.clear_context();
-            
+            return Ok(());
         } else {
-            log_once::error_once!("Unable to fetch compiled scripts for entity {:?}. Script Name: {}", entity_id, script_name);
+            log_once::error_once!(
+                "Unable to fetch compiled scripts for entity {:?}. Script Name: {}",
+                entity_id,
+                script_name
+            );
         }
         Ok(())
     }
 
-    pub fn remove_entity_script(&mut self, entity_id: hecs::Entity) {
-        self.entity_script_data.remove(&entity_id);
-    }
-
-    fn sync_entity_to_memory(&self, entity_id: hecs::Entity, world: &mut Arc<World>, instance: &Instance) -> anyhow::Result<()> {
-        if let Some(&memory_offset) = self.entity_script_data.get(&entity_id) {
-            let memory = instance.exports.get_memory("memory")?;
-            let memory_view = memory.view(&self.store);
-
-            if let Ok(transform) = Arc::get_mut(world).unwrap().query_one_mut::<&Transform>(entity_id) {
-                let transform_bytes = unsafe { std::slice::from_raw_parts(
-                    transform as *const Transform as *const u8, 
-                    std::mem::size_of::<Transform>()
-                )};
-                
-                for (i, &byte) in transform_bytes.iter().enumerate() {
-                    memory_view.write_u8((memory_offset + i as u32).into(), byte)?;
-                }
-            }
-        }
-        Ok(())
-    }
-
-    fn sync_memory_to_entity(&self, entity_id: hecs::Entity, world: &mut Arc<World>, instance: &Instance) -> anyhow::Result<()> {
-        if let Some(&memory_offset) = self.entity_script_data.get(&entity_id) {
-            let memory = instance.exports.get_memory("memory")?;
-            let memory_view = memory.view(&self.store);
-
-            Self::update::<Transform>(memory_offset, &memory_view, world, &entity_id)?;
-        }
-        Ok(())
-    }
-
-    fn update<T: Send + Sync + 'static>(memory_offset: u32, memory_view: &wasmer::MemoryView<'_>, world: &mut Arc<World>, entity_id: &hecs::Entity) -> anyhow::Result<()> {
-        let mut obj_bytes = vec![0u8; std::mem::size_of::<T>()];
-        for (i, byte) in obj_bytes.iter_mut().enumerate() {
-            *byte = memory_view.read_u8((memory_offset + i as u32).into())?;
-        }
-
-        let obj = unsafe {
-            std::ptr::read(obj_bytes.as_ptr() as *const T)
-        };
-
-        Arc::get_mut(world).unwrap().insert_one(*entity_id, obj)?;
-        Ok(())
-    }
-
-    fn create_imports(&mut self) -> anyhow::Result<Imports> {
-        let mut imports = imports! {};
-
-        DropbearAPI::register(&self.script_context, &mut imports, &mut self.store)?;
-
-        Ok(imports)
-    }
+    pub fn expose(&self, _context: &mut Context) {}
 }
 
 pub fn move_script_to_src(script_path: &PathBuf) -> anyhow::Result<PathBuf> {
@@ -342,14 +300,14 @@ pub fn move_script_to_src(script_path: &PathBuf) -> anyhow::Result<PathBuf> {
 }
 
 pub fn convert_entity_to_group(
-    world: &World,
+    world: Arc<RwLock<World>>,
     entity_id: hecs::Entity,
 ) -> anyhow::Result<EntityNode> {
-    if let Ok(mut query) = world.query_one::<(&AdoptedEntity, &Transform)>(entity_id) {
+    if let Ok(mut query) = world.read().query_one::<(&AdoptedEntity, &Transform)>(entity_id) {
         if let Some((adopted, _transform)) = query.get() {
             let entity_name = adopted.model().label.clone();
 
-            let script_node = if let Ok(script) = world.get::<&ScriptComponent>(entity_id) {
+            let script_node = if let Ok(script) = world.read().get::<&ScriptComponent>(entity_id) {
                 Some(EntityNode::Script {
                     name: script.name.clone(),
                     path: script.path.clone(),
@@ -381,12 +339,14 @@ pub fn convert_entity_to_group(
 }
 
 pub fn attach_script_to_entity(
-    world: &mut World,
+    world: Arc<RwLock<World>>,
     entity_id: hecs::Entity,
     script_component: ScriptComponent,
 ) -> anyhow::Result<()> {
-    if let Err(e) = world.insert_one(entity_id, script_component) {
-        return Err(anyhow::anyhow!("Failed to attach script to entity: {}", e));
+    {
+        if let Err(e) = world.write().insert_one(entity_id, script_component) {
+            return Err(anyhow::anyhow!("Failed to attach script to entity: {}", e));
+        }
     }
 
     log::info!("Successfully attached script to entity {:?}", entity_id);
diff --git a/eucalyptus-core/src/scripting/build.rs b/eucalyptus-core/src/scripting/build.rs
deleted file mode 100644
index a11eae5..0000000
--- a/eucalyptus-core/src/scripting/build.rs
+++ /dev/null
@@ -1,406 +0,0 @@
-use std::path::PathBuf;
-use std::process::Command;
-use app_dirs2::{AppInfo, AppDataType, app_dir};
-use tokio::fs;
-use tokio::io::AsyncWriteExt;
-
-const GLEAM_VERSION: &'static str = "1.12.0";
-const BUN_VERSION: &'static str = "1.2.22";
-const JAVY_VERSION: &'static str = "6.0.0";
-
-pub const APP_INFO: AppInfo = AppInfo {
-    name: "Eucalyptus",
-    author: "4tkbytes",
-};
-
-/// Compiles a gleam project into WASM through a pipeline. 
-pub struct GleamScriptCompiler {
-    #[allow(dead_code)]
-    project_location: PathBuf,
-}
-
-impl GleamScriptCompiler {
-    pub fn new(project_location: &PathBuf) -> Self {
-        GleamScriptCompiler {
-            project_location: project_location.clone(),
-        }
-    }
-
-    pub async fn build(self) -> anyhow::Result<()> {
-        Self::ensure_dependencies().await?;
-        Ok(())
-    }
-
-    pub async fn ensure_dependencies() -> anyhow::Result<()> {
-        println!("Checking dependencies...");
-        
-        let gleam_available = Self::check_tool_in_path("gleam").await;
-        if gleam_available {
-            println!("Gleam already exists in path");
-        }
-        let bun_available = Self::check_tool_in_path("bun").await;
-        if bun_available {
-            println!("Bun already exists in path");
-        }
-        let javy_available = Self::check_tool_in_path("javy").await;
-        if javy_available {
-            println!("Javy already exists in path");
-        }
-
-        if gleam_available && bun_available && javy_available {
-            println!("All dependencies found in PATH");
-            return Ok(());
-        }
-
-        if !(cfg!(target_os = "windows") || cfg!(target_os = "linux") || cfg!(target_os = "macos")) {
-            anyhow::bail!("The operating system is not supported for building the Gleam project")
-        }
-
-        let app_dir = app_dir(AppDataType::UserData, &APP_INFO, "")
-            .map_err(|e| anyhow::anyhow!("Failed to get app directory: {}", e))?;
-
-        if !gleam_available {
-            Self::download_gleam(&app_dir).await?;
-        }
-
-        if !bun_available {
-            Self::download_bun(&app_dir).await?;
-        }
-
-        if !javy_available {
-            Self::download_javy(&app_dir).await?;
-        }
-
-        Ok(())
-    }
-
-    async fn check_tool_in_path(tool: &str) -> bool {
-        let cmd = if cfg!(target_os = "windows") {
-            Command::new("where").arg(tool).output()
-        } else {
-            Command::new("which").arg(tool).output()
-        };
-
-        match cmd {
-            Ok(output) => output.status.success(),
-            Err(_) => false,
-        }
-    }
-
-    pub async fn download_gleam(app_dir: &PathBuf) -> anyhow::Result<()> {
-        let gleam_dir = app_dir.join("dependencies").join("gleam").join(GLEAM_VERSION);
-        
-        if gleam_dir.exists() {
-            println!("Gleam v{} already cached at {}", GLEAM_VERSION, app_dir.display());
-            return Ok(());
-        }
-
-        println!("Downloading Gleam v{}...", GLEAM_VERSION);
-        
-        let gleam_link = Self::get_gleam_download_url()?;
-        Self::download_and_extract(&gleam_link, &gleam_dir, "gleam").await?;
-        
-        println!("Gleam v{} downloaded successfully", GLEAM_VERSION);
-        Ok(())
-    }
-
-    pub async fn download_bun(app_dir: &PathBuf) -> anyhow::Result<()> {
-        let bun_dir = app_dir.join("dependencies").join("bun").join(BUN_VERSION);
-        
-        if bun_dir.exists() {
-            println!("Bun v{} already cached at {}", BUN_VERSION, app_dir.display());
-            return Ok(());
-        }
-
-        println!("Downloading Bun v{}...", BUN_VERSION);
-        
-        let bun_link = Self::get_bun_download_url()?;
-        Self::download_and_extract(&bun_link, &bun_dir, "bun").await?;
-        
-        println!("Bun v{} downloaded successfully", BUN_VERSION);
-        Ok(())
-    }
-
-    pub async fn download_javy(app_dir: &PathBuf) -> anyhow::Result<()> {
-        let javy_dir = app_dir.join("dependencies").join("javy").join(JAVY_VERSION);
-        
-        if javy_dir.exists() {
-            println!("Javy v{} already cached at {}", JAVY_VERSION, app_dir.display());
-            return Ok(());
-        }
-
-        println!("Downloading Javy v{}...", JAVY_VERSION);
-        
-        let javy_link = Self::get_javy_download_url()?;
-        Self::download_and_extract(&javy_link, &javy_dir, "javy").await?;
-        
-        println!("Javy v{} downloaded successfully", JAVY_VERSION);
-        Ok(())
-    }
-
-    async fn download_and_extract(url: &str, target_dir: &PathBuf, tool_name: &str) -> anyhow::Result<()> {
-        fs::create_dir_all(target_dir).await?;
-        
-        let response = reqwest::get(url).await?;
-        let bytes = response.bytes().await?;
-        
-        let temp_file = target_dir.join(format!("{}_download", tool_name));
-        let mut file = fs::File::create(&temp_file).await?;
-        file.write_all(&bytes).await?;
-        file.sync_all().await?;
-        drop(file);
-
-        if url.ends_with(".zip") {
-            Self::extract_zip(&temp_file, target_dir).await?;
-        } else if url.ends_with(".tar.gz") {
-            Self::extract_tar_gz(&temp_file, target_dir).await?;
-        } else if url.ends_with(".gz") {
-            Self::extract_gz(&temp_file, target_dir, tool_name).await?;
-        }
-
-        fs::remove_file(&temp_file).await?;
-        Ok(())
-    }
-
-    async fn extract_zip(archive: &PathBuf, target_dir: &PathBuf) -> anyhow::Result<()> {
-        let file = std::fs::File::open(archive)?;
-        let mut archive = zip::ZipArchive::new(file)?;
-        
-        for i in 0..archive.len() {
-            let mut file = archive.by_index(i)?;
-            let outpath = target_dir.join(file.name());
-            
-            if file.is_dir() {
-                fs::create_dir_all(&outpath).await?;
-            } else {
-                if let Some(p) = outpath.parent() {
-                    fs::create_dir_all(p).await?;
-                }
-                let mut outfile = fs::File::create(&outpath).await?;
-                let mut buffer = Vec::new();
-                std::io::Read::read_to_end(&mut file, &mut buffer)?;
-                outfile.write_all(&buffer).await?;
-            }
-        }
-        Ok(())
-    }
-
-    async fn extract_tar_gz(archive: &PathBuf, target_dir: &PathBuf) -> anyhow::Result<()> {
-        let file = std::fs::File::open(archive)?;
-        let tar = flate2::read::GzDecoder::new(file);
-        let mut archive = tar::Archive::new(tar);
-        
-        for entry in archive.entries()? {
-            let mut entry = entry?;
-            let path = target_dir.join(entry.path()?);
-            entry.unpack(path)?;
-        }
-        Ok(())
-    }
-
-    async fn extract_gz(archive: &PathBuf, target_dir: &PathBuf, tool_name: &str) -> anyhow::Result<()> {
-        let file = std::fs::File::open(archive)?;
-        let mut decoder = flate2::read::GzDecoder::new(file);
-        let mut buffer = Vec::new();
-        std::io::Read::read_to_end(&mut decoder, &mut buffer)?;
-        
-        let exe_name = if cfg!(target_os = "windows") {
-            format!("{}.exe", tool_name)
-        } else {
-            tool_name.to_string()
-        };
-        
-        let output_path = target_dir.join(exe_name);
-        let mut output_file = fs::File::create(&output_path).await?;
-        output_file.write_all(&buffer).await?;
-        
-        #[cfg(unix)]
-        {
-            use std::os::unix::fs::PermissionsExt;
-            let mut perms = output_file.metadata().await?.permissions();
-            perms.set_mode(0o755);
-            fs::set_permissions(&output_path, perms).await?;
-        }
-        
-        Ok(())
-    }
-
-    fn get_gleam_download_url() -> anyhow::Result<String> {
-        let gleam_link = {
-            #[cfg(target_os = "windows")]
-            {
-                let arch = {
-                    if cfg!(target_arch = "aarch64") {
-                        "aarch64"
-                    } else if cfg!(target_arch = "x86_64") {
-                        "x86_64"
-                    } else {
-                        anyhow::bail!("This architecture is not supported for building the gleam project");
-                    }
-                };
-                format!("https://github.com/gleam-lang/gleam/releases/download/v{}/gleam-v{}-{}-pc-windows-msvc.zip",
-                    GLEAM_VERSION,
-                    GLEAM_VERSION,
-                    arch,
-                )
-            }
-
-            #[cfg(target_os = "linux")]
-            {
-                let arch = {
-                    if cfg!(target_arch = "aarch64") {
-                        "aarch64"
-                    } else if cfg!(target_arch = "x86_64") {
-                        "x86_64"
-                    } else {
-                        anyhow::bail!("This architecture is not supported for building the gleam project");
-                    }
-                };
-                format!("https://github.com/gleam-lang/gleam/releases/download/v{}/gleam-v{}-{}-unknown-linux-musl.tar.gz",
-                    GLEAM_VERSION,
-                    GLEAM_VERSION,
-                    arch,
-                )
-            }
-
-            #[cfg(target_os = "macos")] 
-            {
-                let arch = {
-                    if cfg!(target_arch = "aarch64") {
-                        "aarch64"
-                    } else if cfg!(target_arch = "x86_64") {
-                        "x86_64"
-                    } else {
-                        anyhow::bail!("This architecture is not supported for building the gleam project");
-                    }
-                };
-                format!("https://github.com/gleam-lang/gleam/releases/download/v{}/gleam-v{}-{}-apple-darwin.tar.gz",
-                    GLEAM_VERSION,
-                    GLEAM_VERSION,
-                    arch,
-                )
-            }
-        };
-        Ok(gleam_link)
-    }
-
-    fn get_bun_download_url() -> anyhow::Result<String> {
-        let bun_link = {
-            #[cfg(target_os = "windows")]
-            {
-                let arch = {
-                    if cfg!(target_arch = "aarch64") {
-                        "aarch64"
-                    } else if cfg!(target_arch = "x86_64") {
-                        "x64"
-                    } else {
-                        anyhow::bail!("This architecture is not supported for building the gleam project");
-                    }
-                };
-                format!("https://github.com/oven-sh/bun/releases/download/bun-v{}/bun-windows-{}.zip",
-                    BUN_VERSION,
-                    arch,
-                )
-            }
-
-            #[cfg(target_os = "linux")]
-            {
-                let arch = {
-                    if cfg!(target_arch = "aarch64") {
-                        "aarch64"
-                    } else if cfg!(target_arch = "x86_64") {
-                        "x64"
-                    } else {
-                        anyhow::bail!("This architecture is not supported for building the gleam project");
-                    }
-                };
-                format!("https://github.com/oven-sh/bun/releases/download/bun-v{}/bun-linux-{}.zip",
-                    BUN_VERSION,
-                    arch,
-                )
-            }
-
-            #[cfg(target_os = "macos")] 
-            {
-                let arch = {
-                    if cfg!(target_arch = "aarch64") {
-                        "aarch64"
-                    } else if cfg!(target_arch = "x86_64") {
-                        "x64"
-                    } else {
-                        anyhow::bail!("This architecture is not supported for building the gleam project");
-                    }
-                };
-                format!("https://github.com/oven-sh/bun/releases/download/bun-v{}/bun-darwin-{}.zip",
-                    BUN_VERSION,
-                    arch,
-                )
-            }
-        };
-        Ok(bun_link)
-    }
-
-    fn get_javy_download_url() -> anyhow::Result<String> {
-        let javy_link = {
-            #[cfg(target_os = "windows")]
-            {
-                let arch = {
-                    if cfg!(target_arch = "aarch64") {
-                        anyhow::bail!("This arch is not available for prebuilt download. Please build this from source");
-                    } else if cfg!(target_arch = "x86_64") {
-                        "x86_64"
-                    } else {
-                        anyhow::bail!("This architecture is not supported for building the gleam project");
-                    }
-                };
-                format!("https://github.com/bytecodealliance/javy/releases/download/v{}/javy-{}-windows-v{}.gz",
-                    JAVY_VERSION,
-                    arch,
-                    JAVY_VERSION
-                )
-            }
-
-            #[cfg(target_os = "linux")]
-            {
-                let arch = {
-                    if cfg!(target_arch = "aarch64") {
-                        "arm"
-                    } else if cfg!(target_arch = "x86_64") {
-                        "x86_64"
-                    } else {
-                        anyhow::bail!("This architecture is not supported for building the gleam project");
-                    }
-                };
-                format!("https://github.com/bytecodealliance/javy/releases/download/v{}/javy-{}-linux-v{}.gz",
-                    JAVY_VERSION,
-                    arch,
-                    JAVY_VERSION
-                )
-            }
-
-            #[cfg(target_os = "macos")] 
-            {
-                let arch = {
-                    if cfg!(target_arch = "aarch64") {
-                        "arm"
-                    } else if cfg!(target_arch = "x86_64") {
-                        "x86_64"
-                    } else {
-                        anyhow::bail!("This architecture is not supported for building the gleam project");
-                    }
-                };
-                format!("https://github.com/bytecodealliance/javy/releases/download/v{}/javy-{}-macos-v{}.gz",
-                    JAVY_VERSION,
-                    arch,
-                    JAVY_VERSION
-                )
-            }
-        };
-        Ok(javy_link)
-    }
-}
-
-#[tokio::test]
-async fn check_if_dependencies_install() {
-    GleamScriptCompiler::ensure_dependencies().await.unwrap();
-}
\ No newline at end of file
diff --git a/eucalyptus-core/src/scripting/dropbear.rs b/eucalyptus-core/src/scripting/dropbear.rs
deleted file mode 100644
index c226442..0000000
--- a/eucalyptus-core/src/scripting/dropbear.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-
-use wasmer::FunctionEnv;
-
-use crate::{input::InputState, scripting::{DropbearScriptingAPIContext, ScriptableModule, ScriptableModuleWithEnv}};
-
-pub struct DropbearAPI;
-
-impl ScriptableModule for DropbearAPI {
-    type Data = DropbearScriptingAPIContext;
-
-    fn register(data: &Self::Data, imports: &mut wasmer::Imports, store: &mut wasmer::Store) -> anyhow::Result<()> {
-        let env = FunctionEnv::new(store, data.clone());
-
-        InputState::register(&env, imports, store)?;
-
-        Ok(())
-    }
-
-    fn module_name() -> &'static str {
-        "dropbear"
-    }
-}
\ No newline at end of file
diff --git a/eucalyptus-core/src/states.rs b/eucalyptus-core/src/states.rs
index 1f12220..ad9ca23 100644
--- a/eucalyptus-core/src/states.rs
+++ b/eucalyptus-core/src/states.rs
@@ -15,11 +15,13 @@ use once_cell::sync::Lazy;
 use parking_lot::RwLock;
 use ron::ser::PrettyConfig;
 use serde::{Deserialize, Serialize};
+use tokio::sync::mpsc::UnboundedSender;
 use std::collections::HashMap;
 use std::fmt::{Display, Formatter};
 use std::path::PathBuf;
 use std::sync::Arc;
 use std::{fmt, fs};
+use rayon::prelude::*;
 
 pub static PROJECT: Lazy<RwLock<ProjectConfig>> =
     Lazy::new(|| RwLock::new(ProjectConfig::default()));
@@ -716,15 +718,21 @@ impl SceneConfig {
 
     pub async fn load_into_world(
         &self,
-        world: &mut hecs::World,
+        world: Arc<RwLock<hecs::World>>,
         graphics: Arc<SharedGraphicsContext>,
+        progress_sender: Option<UnboundedSender<WorldLoadingStatus>>
     ) -> anyhow::Result<hecs::Entity> {
+
+        if let Some(ref s) = progress_sender {
+            let _ = s.send(WorldLoadingStatus::Idle);
+        }
+
         log::info!(
             "Loading scene [{}], clearing world with {} entities",
             self.scene_name,
-            world.len()
+            world.read().len()
         );
-        world.clear();
+        { world.write().clear(); }
 
         #[allow(unused_variables)]
         let project_config = if cfg!(feature = "editor") {
@@ -735,281 +743,202 @@ impl SceneConfig {
             PathBuf::new()
         };
 
-        log::info!("World cleared, now has {} entities", world.len());
+        log::info!("World cleared, now has {} entities", world.read().len());
 
-        for (_entity_index, entity_config) in self.entities.iter().enumerate() {
+        for (_i, entity_config) in self.entities.iter().cloned().enumerate() {
             log::debug!("Loading entity: {}", entity_config.label);
 
-            let result = match &entity_config.model_path.ref_type {
-                ResourceReferenceType::File(reference) => {
-                    let path: PathBuf = {
-                        if cfg!(feature = "editor") {
-                            log::debug!("Using feature editor");
-                            entity_config
-                                .model_path
-                                .to_project_path(project_config.clone())
-                                .ok_or_else(|| {
-                                    anyhow::anyhow!(
-                                        "Unable to convert resource reference [{}] to project path",
-                                        reference
-                                    )
-                                })?
+            let entity_configs: Vec<(usize, SceneEntity)> = {
+                let cloned = self.entities.clone();
+                cloned.into_par_iter().enumerate().map(|(i, e)| (i, e)).collect()
+            };
+
+            let total = entity_configs.len();
+
+            for (index, entity_config) in entity_configs {
+                log::debug!("Loading entity: {}", entity_config.label);
+                if let Some(ref s) = progress_sender {
+                    let _ = s.send(WorldLoadingStatus::LoadingEntity { index, name: entity_config.label.clone(), total });
+                }
+
+                let result = match &entity_config.model_path.ref_type {
+                    ResourceReferenceType::File(reference) => {
+                        let path: PathBuf = {
+                            if cfg!(feature = "editor") {
+                                log::debug!("Using feature editor");
+                                entity_config
+                                    .model_path
+                                    .to_project_path(project_config.clone())
+                                    .ok_or_else(|| {
+                                        anyhow::anyhow!(
+                                            "Unable to convert resource reference [{}] to project path",
+                                            reference
+                                        )
+                                    })?
+                            } else {
+                                log::debug!("Using feature data-only");
+                                entity_config.model_path.to_executable_path()?
+                            }
+                        };
+                        log::debug!(
+                            "Path for entity {} is {} from reference {}",
+                            entity_config.label,
+                            path.display(),
+                            reference
+                        );
+
+                        let adopted =
+                            AdoptedEntity::new(graphics.clone(), &path, Some(&entity_config.label))
+                                .await;
+                        let transform = entity_config.transform;
+
+                        if let Some(script_config) = &entity_config.script {
+                            let script = ScriptComponent {
+                                name: script_config.name.clone(),
+                                path: script_config.path.clone(),
+                            };
+                            { world.write().spawn((adopted, transform, script, entity_config.properties.clone())); }
                         } else {
-                            log::debug!("Using feature data-only");
-                            entity_config.model_path.to_executable_path()?
+                            { world.write().spawn((adopted, transform, entity_config.properties.clone())); }
                         }
-                    };
-                    log::debug!(
-                        "Path for entity {} is {} from reference {}",
-                        entity_config.label,
-                        path.display(),
-                        reference
-                    );
-
-                    let adopted = AdoptedEntity::new(graphics.clone(), &path, Some(&entity_config.label)).await;
-
-                    // let adopted = {
-                    //     let path_clone = path.clone();
-                    //     let label_clone = entity_config.label.clone();
-                        
-                    //     let (tx, mut rx) = tokio::sync::oneshot::channel();
-                        
-                    //     tokio::task::spawn_local(async move {
-                    //         let entity = LazyAdoptedEntity::from_file(&path_clone, Some(&label_clone)).await;
-                    //         let _ = tx.send(entity);
-                    //     });
-                        
-                    //     loop {
-                    //         match rx.try_recv() {
-                    //             Ok(result) => {
-                    //                 break result?.poke(graphics)?;
-                    //             },
-                    //             Err(tokio::sync::oneshot::error::TryRecvError::Empty) => {
-                    //                 std::thread::yield_now();
-                    //                 continue;
-                    //             }
-                    //             Err(tokio::sync::oneshot::error::TryRecvError::Closed) => {
-                    //                 return Err(anyhow::anyhow!("Loading task was cancelled"));
-                    //             }
-                    //         }
-                    //     }
-                    // };
-                    let transform = entity_config.transform;
-
-                    if let Some(script_config) = &entity_config.script {
-                        let script = ScriptComponent {
-                            name: script_config.name.clone(),
-                            path: script_config.path.clone(),
-                        };
-                        world.spawn((adopted, transform, script, entity_config.properties.clone()));
-                    } else {
-                        world.spawn((adopted, transform, entity_config.properties.clone()));
+
+                        Ok(())
                     }
-                    
-                    Ok(())
-                }
-                ResourceReferenceType::Bytes(bytes) => {
-                    log::info!("Loading entity from bytes [Len: {}]", bytes.len());
-                    let bytes = bytes.to_owned();
-
-                    let model = Model::load_from_memory(graphics.clone(), bytes, Some(&entity_config.label)).await?;
-                    let adopted = AdoptedEntity::adopt(graphics.clone(), model).await;
-
-                    // let adopted = {
-                    //     let bytes_clone = bytes.clone();
-                    //     let label_clone = entity_config.label.clone();
-                        
-                    //     let (tx, mut rx) = tokio::sync::oneshot::channel();
-                        
-                    //     tokio::task::spawn_local(async move {
-                    //         let entity = LazyAdoptedEntity::from_memory(bytes_clone, Some(label_clone.as_str())).await;
-                    //         let _ = tx.send(entity);
-                    //     }); 
-                        
-                    //     loop {
-                    //         match rx.try_recv() {
-                    //             Ok(result) => {
-                    //                 break result?.poke(graphics)?;
-                    //             },
-                    //             Err(tokio::sync::oneshot::error::TryRecvError::Empty) => {
-                    //                 std::thread::yield_now();
-                    //                 continue;
-                    //             }
-                    //             Err(tokio::sync::oneshot::error::TryRecvError::Closed) => {
-                    //                 return Err(anyhow::anyhow!("Loading task was cancelled"));
-                    //             }
-                    //         }
-                    //     }
-                    // };
-                    let transform = entity_config.transform;
-
-                    if let Some(script_config) = &entity_config.script {
-                        let script = ScriptComponent {
-                            name: script_config.name.clone(),
-                            path: script_config.path.clone(),
-                        };
-                        world.spawn((adopted, transform, script, entity_config.properties.clone()));
-                    } else {
-                        world.spawn((adopted, transform, entity_config.properties.clone()));
+                    ResourceReferenceType::Bytes(bytes) => {
+                        log::info!("Loading entity from bytes [Len: {}]", bytes.len());
+                        let bytes = bytes.to_owned();
+
+                        let model = Model::load_from_memory(
+                            graphics.clone(),
+                            bytes,
+                            Some(&entity_config.label),
+                        )
+                        .await?;
+                        let adopted = AdoptedEntity::adopt(graphics.clone(), model).await;
+
+                        let transform = entity_config.transform;
+
+                        if let Some(script_config) = &entity_config.script {
+                            let script = ScriptComponent {
+                                name: script_config.name.clone(),
+                                path: script_config.path.clone(),
+                            };
+                            { world.write().spawn((adopted, transform, script, entity_config.properties.clone())); }
+                        } else {
+                            { world.write().spawn((adopted, transform, entity_config.properties.clone())); }
+                        }
+
+                        Ok(())
                     }
-                    
-                    Ok(())
-                }
-                ResourceReferenceType::Plane => {
-                    let width = entity_config
-                        .properties
-                        .custom_properties
-                        .get("width")
-                        .ok_or_else(|| anyhow::anyhow!("Entity has no width property"))?;
-                    let width = match width {
-                        Value::Float(width) => width,
-                        _ => panic!("Entity has a width property that is not a float"),
-                    };
-                    let height = entity_config
-                        .properties
-                        .custom_properties
-                        .get("height")
-                        .ok_or_else(|| anyhow::anyhow!("Entity has no height property"))?;
-                    let height = match height {
-                        Value::Float(height) => height,
-                        _ => panic!("Entity has a height property that is not a float"),
-                    };
-                    let tiles_x = entity_config
-                        .properties
-                        .custom_properties
-                        .get("tiles_x")
-                        .ok_or_else(|| anyhow::anyhow!("Entity has no tiles_x property"))?;
-                    let tiles_x = match tiles_x {
-                        Value::Int(tiles_x) => tiles_x,
-                        _ => panic!("Entity has a tiles_x property that is not an int"),
-                    };
-                    let tiles_z = entity_config
-                        .properties
-                        .custom_properties
-                        .get("tiles_z")
-                        .ok_or_else(|| anyhow::anyhow!("Entity has no tiles_z property"))?;
-                    let tiles_z = match tiles_z {
-                        Value::Int(tiles_z) => tiles_z,
-                        _ => panic!("Entity has a tiles_z property that is not an int"),
-                    };
-
-                    let label_clone = entity_config.label.clone();
-                    let width_val = *width as f32;
-                    let height_val = *height as f32;
-                    let tiles_x_val = *tiles_x as u32;
-                    let tiles_z_val = *tiles_z as u32;
-
-                    let plane = PlaneBuilder::new()
-                        .with_size(width_val, height_val)
-                        .with_tiles(tiles_x_val, tiles_z_val)
-                        .build(graphics.clone(), PROTO_TEXTURE, Some(&label_clone)).await?;
-
-                    // let plane = {
-                    //     let label_clone = entity_config.label.clone();
-                    //     let width_val = *width as f32;
-                    //     let height_val = *height as f32;
-                    //     let tiles_x_val = *tiles_x as u32;
-                    //     let tiles_z_val = *tiles_z as u32;
-                        
-                    //     let (tx, mut rx) = tokio::sync::oneshot::channel();
-                        
-                    //     tokio::task::spawn_local(async move {
-                    //         let result = PlaneBuilder::new()
-                    //             .with_size(width_val, height_val)
-                    //             .with_tiles(tiles_x_val, tiles_z_val)
-                    //             .lazy_build(PROTO_TEXTURE, Some(&label_clone)).await;
-                    //         let _ = tx.send(result);
-                    //     });
-                        
-                    //     loop {
-                    //         match rx.try_recv() {
-                    //             Ok(result) => break result?.poke(graphics)?,
-                    //             Err(tokio::sync::oneshot::error::TryRecvError::Empty) => {
-                    //                 std::thread::yield_now();
-                    //                 continue;
-                    //             }
-                    //             Err(tokio::sync::oneshot::error::TryRecvError::Closed) => {
-                    //                 return Err(anyhow::anyhow!("Loading task was cancelled"));
-                    //             }
-                    //         }
-                    //     }
-                    // };
-                    let transform = entity_config.transform;
-
-                    if let Some(script_config) = &entity_config.script {
-                        let script = ScriptComponent {
-                            name: script_config.name.clone(),
-                            path: script_config.path.clone(),
+                    ResourceReferenceType::Plane => {
+                        let width = entity_config
+                            .properties
+                            .custom_properties
+                            .get("width")
+                            .ok_or_else(|| anyhow::anyhow!("Entity has no width property"))?;
+                        let width = match width {
+                            Value::Float(width) => width,
+                            _ => panic!("Entity has a width property that is not a float"),
+                        };
+                        let height = entity_config
+                            .properties
+                            .custom_properties
+                            .get("height")
+                            .ok_or_else(|| anyhow::anyhow!("Entity has no height property"))?;
+                        let height = match height {
+                            Value::Float(height) => height,
+                            _ => panic!("Entity has a height property that is not a float"),
+                        };
+                        let tiles_x = entity_config
+                            .properties
+                            .custom_properties
+                            .get("tiles_x")
+                            .ok_or_else(|| anyhow::anyhow!("Entity has no tiles_x property"))?;
+                        let tiles_x = match tiles_x {
+                            Value::Int(tiles_x) => tiles_x,
+                            _ => panic!("Entity has a tiles_x property that is not an int"),
+                        };
+                        let tiles_z = entity_config
+                            .properties
+                            .custom_properties
+                            .get("tiles_z")
+                            .ok_or_else(|| anyhow::anyhow!("Entity has no tiles_z property"))?;
+                        let tiles_z = match tiles_z {
+                            Value::Int(tiles_z) => tiles_z,
+                            _ => panic!("Entity has a tiles_z property that is not an int"),
                         };
-                        world.spawn((plane, transform, script, entity_config.properties.clone()));
-                    } else {
-                        world.spawn((plane, transform, entity_config.properties.clone()));
-                    }
 
-                    Ok(())
-                }
-                ResourceReferenceType::None => {
-                    Err(anyhow::anyhow!(
+                        let label_clone = entity_config.label.clone();
+                        let width_val = *width as f32;
+                        let height_val = *height as f32;
+                        let tiles_x_val = *tiles_x as u32;
+                        let tiles_z_val = *tiles_z as u32;
+
+                        let plane = PlaneBuilder::new()
+                            .with_size(width_val, height_val)
+                            .with_tiles(tiles_x_val, tiles_z_val)
+                            .build(graphics.clone(), PROTO_TEXTURE, Some(&label_clone))
+                            .await?;
+
+                        let transform = entity_config.transform;
+
+                        if let Some(script_config) = &entity_config.script {
+                            let script = ScriptComponent {
+                                name: script_config.name.clone(),
+                                path: script_config.path.clone(),
+                            };
+                            { world.write().spawn((plane, transform, script, entity_config.properties.clone())); }
+                        } else {
+                            { world.write().spawn((plane, transform, entity_config.properties.clone())); }
+                        }
+
+                        Ok(())
+                    }
+                    ResourceReferenceType::None => Err(anyhow::anyhow!(
                         "Entity has a resource reference of None, which cannot be loaded or referenced"
-                    ))
-                }
-            };
+                    )),
+                };
 
-            result?;
-            // processed_items += 1;
-            log::debug!("Loaded!");
+                result?;
+                log::debug!("Loaded!");
+            }
         }
 
-        for light_config in &self.lights {
+        let total = self.lights.len();
+        
+        for (index, light_config) in self.lights.iter().enumerate() {
             log::debug!("Loading light: {}", light_config.label);
+            if let Some(ref s) = progress_sender {
+                let _ = s.send(WorldLoadingStatus::LoadingLight { index, name: light_config.label.clone(), total });
+            }
 
-            let light = Light::new(graphics.clone(), &light_config.light_component, &light_config.transform, Some(&light_config.label)).await;
-
-            // let light = {
-            //     let light_comp_clone = light_config.light_component.clone();
-            //     let light_trans_clone = light_config.transform.clone();
-            //     let label_clone = light_config.label.clone();
-            //     let (tx, mut rx) = tokio::sync::oneshot::channel();
-                
-            //     tokio::task::spawn_local(async move {
-            //         let result = Light::lazy_new(
-            //             light_comp_clone,
-            //             light_trans_clone,
-            //             Some(&label_clone),
-            //         );
-            //         let _ = tx.send(result);
-            //     });
-                
-            //     loop {
-            //         match rx.try_recv() {
-            //             Ok(result) => break result.poke(graphics)?,
-            //             Err(tokio::sync::oneshot::error::TryRecvError::Empty) => {
-            //                 std::thread::yield_now();
-            //                 continue;
-            //             }
-            //             Err(tokio::sync::oneshot::error::TryRecvError::Closed) => {
-            //                 return Err(anyhow::anyhow!("Loading task was cancelled"));
-            //             }
-            //         }
-            //     }
-            // };
-
-            world.spawn((
-                light_config.light_component.clone(),
-                light_config.transform,
-                light,
-                ModelProperties::default(),
-            ));
-
-            // processed_items += 1;
+            let light = Light::new(
+                graphics.clone(),
+                &light_config.light_component,
+                &light_config.transform,
+                Some(&light_config.label),
+            )
+            .await;
+            {
+                world.write().spawn((
+                    light_config.light_component.clone(),
+                    light_config.transform,
+                    light,
+                    ModelProperties::default(),
+                ));
+            }
         }
 
-        for camera_config in &self.cameras {
+        let total = self.cameras.len();
+        for (index, camera_config) in self.cameras.iter().enumerate() {
             log::debug!(
                 "Loading camera {} of type {:?}",
                 camera_config.label,
                 camera_config.camera_type
             );
+            if let Some(ref s) = progress_sender {
+                let _ = s.send(WorldLoadingStatus::LoadingCamera { index, name: camera_config.label.clone(), total });
+            }
 
             let camera = Camera::new(
                 graphics.clone(),
@@ -1040,64 +969,30 @@ impl SceneConfig {
                     follow_target: target_label.clone(),
                     offset: DVec3::from_array(*offset),
                 };
-                world.spawn((camera, component, follow_target));
+                { world.write().spawn((camera, component, follow_target)); }
             } else {
-                world.spawn((camera, component));
+                { world.write().spawn((camera, component)); }
             }
-
-            // processed_items += 1;
         }
 
-        if world
+        if world.read()
             .query::<(&LightComponent, &Light)>()
             .iter()
             .next()
             .is_none()
         {
             log::info!("No lights in scene, spawning default light");
+            if let Some(ref s) = progress_sender {
+                let _ = s.send(WorldLoadingStatus::LoadingLight { index: 0, name: String::from("Default Light"), total: 1 });
+            }
             let comp = LightComponent::directional(glam::DVec3::ONE, 1.0);
             let trans = Transform {
-                    position: glam::DVec3::new(2.0, 4.0, 2.0),
-                    ..Default::default()
-                };
+                position: glam::DVec3::new(2.0, 4.0, 2.0),
+                ..Default::default()
+            };
             let light = Light::new(graphics.clone(), &comp, &trans, Some("Default Light")).await;
-            // let light = {
-            //     let light_comp_clone = LightComponent::directional(glam::DVec3::ONE, 1.0);
-            //     let default_transform = Transform {
-            //         position: glam::DVec3::new(2.0, 4.0, 2.0),
-            //         ..Default::default()
-            //     };
-            //     let (tx, mut rx) = tokio::sync::oneshot::channel();
-                
-            //     tokio::task::spawn_local(async move {
-            //         let result = Light::lazy_new(
-            //             light_comp_clone,
-            //             default_transform,
-            //             Some("Default Light"),
-            //         );
-            //         let _ = tx.send(result);
-            //     });
-                
-            //     loop {
-            //         match rx.try_recv() {
-            //             Ok(result) => break result.poke(graphics)?,
-            //             Err(tokio::sync::oneshot::error::TryRecvError::Empty) => {
-            //                 std::thread::yield_now();
-            //                 continue;
-            //             }
-            //             Err(tokio::sync::oneshot::error::TryRecvError::Closed) => {
-            //                 return Err(anyhow::anyhow!("Loading task was cancelled"));
-            //             }
-            //         }
-            //     }
-            // };
-
-            world.spawn((
-                comp,
-                trans,
-                light,
-                ModelProperties::default(),
-            ));
+
+            world.write().spawn((comp, trans, light, ModelProperties::default()));
         }
 
         log::info!(
@@ -1109,7 +1004,7 @@ impl SceneConfig {
         #[cfg(feature = "editor")]
         {
             // Editor mode - look for debug camera, create one if none exists
-            let debug_camera = world
+            let debug_camera = world.read()
                 .query::<(&Camera, &CameraComponent)>()
                 .iter()
                 .find_map(|(entity, (_, component))| {
@@ -1125,9 +1020,12 @@ impl SceneConfig {
                 Ok(camera_entity)
             } else {
                 log::info!("No debug camera found, creating viewport camera for editor");
+                if let Some(ref s) = progress_sender {
+                    let _ = s.send(WorldLoadingStatus::LoadingCamera { index: 0, name: String::from("Viewport Camera"), total: 1 });
+                }
                 let camera = Camera::predetermined(graphics.clone(), Some("Viewport Camera"));
                 let component = DebugCamera::new();
-                let camera_entity = world.spawn((camera, component));
+                let camera_entity = { world.write().spawn((camera, component)) };
                 Ok(camera_entity)
             }
         }
@@ -1135,7 +1033,7 @@ impl SceneConfig {
         #[cfg(not(feature = "editor"))]
         {
             // Runtime mode - look for player camera, panic if none exists
-            let player_camera = world
+            let player_camera = world.read()
                 .query::<(&Camera, &CameraComponent)>()
                 .iter()
                 .find_map(|(entity, (_, component))| {
@@ -1203,3 +1101,27 @@ pub enum EditorTab {
     ModelEntityList,   // right side,
     Viewport,          // middle,
 }
+
+/// An enum that describes the status of loading the world.
+///
+/// This is enum is used by [`SceneConfig::load_into_world`] heavily. This enum
+/// is recommended to be used with an [`UnboundedSender`]
+pub enum WorldLoadingStatus {
+    Idle,
+    LoadingEntity {
+        index: usize,
+        name: String,
+        total: usize,
+    },
+    LoadingLight {
+        index: usize,
+        name: String,
+        total: usize,
+    },
+    LoadingCamera {
+        index: usize,
+        name: String,
+        total: usize,
+    },
+    Completed,
+}
\ No newline at end of file
diff --git a/eucalyptus-core/src/utils.rs b/eucalyptus-core/src/utils.rs
index 1e20de6..75a76f0 100644
--- a/eucalyptus-core/src/utils.rs
+++ b/eucalyptus-core/src/utils.rs
@@ -33,6 +33,7 @@ pub enum ProjectProgress {
     Done,
 }
 
+#[derive(Clone)]
 pub enum ViewportMode {
     None,
     CameraMove,
diff --git a/eucalyptus-editor/Cargo.toml b/eucalyptus-editor/Cargo.toml
index f841b05..f70338c 100644
--- a/eucalyptus-editor/Cargo.toml
+++ b/eucalyptus-editor/Cargo.toml
@@ -36,6 +36,10 @@ walkdir.workspace = true
 zip.workspace = true
 tokio.workspace = true
 async-trait.workspace = true
+reqwest.workspace = true
+flate2.workspace = true
+tar.workspace = true
+futures-util.workspace = true
 
 [target.'cfg(not(target_os = "android"))'.dependencies]
 rfd.workspace = true
diff --git a/eucalyptus-editor/src/build/gleam.rs b/eucalyptus-editor/src/build/gleam.rs
new file mode 100644
index 0000000..f718f4a
--- /dev/null
+++ b/eucalyptus-editor/src/build/gleam.rs
@@ -0,0 +1,604 @@
+use app_dirs2::{AppDataType, AppInfo, app_dir};
+use futures_util::StreamExt;
+use std::path::PathBuf;
+use std::process::Command;
+use tokio::fs;
+use tokio::io::AsyncWriteExt;
+use tokio::sync::mpsc::UnboundedSender;
+
+const GLEAM_VERSION: &'static str = "1.12.0";
+const BUN_VERSION: &'static str = "1.2.22";
+const JAVY_VERSION: &'static str = "6.0.0";
+
+pub const APP_INFO: AppInfo = AppInfo {
+    name: "Eucalyptus",
+    author: "4tkbytes",
+};
+
+#[derive(Clone)]
+pub enum InstallStatus {
+    NotStarted,
+    InProgress {
+        tool: String,
+        step: String,
+        progress: f32,
+    },
+    Success,
+    Failed(String),
+}
+
+/// Compiles a gleam project into WASM through a pipeline.
+pub struct GleamScriptCompiler {
+    #[allow(dead_code)]
+    project_location: PathBuf,
+}
+
+#[allow(dead_code)]
+impl GleamScriptCompiler {
+    #[allow(dead_code)]
+    pub fn new(project_location: &PathBuf) -> Self {
+        GleamScriptCompiler {
+            project_location: project_location.clone(),
+        }
+    }
+
+    pub async fn evaluate(&self) -> anyhow::Result<()> {
+        Ok(())
+    }
+
+    pub async fn build(
+        &self,
+        sender: Option<UnboundedSender<InstallStatus>>,
+    ) -> anyhow::Result<()> {
+        Self::ensure_dependencies(sender).await?;
+        Ok(())
+    }
+
+    pub async fn ensure_dependencies(
+        sender: Option<UnboundedSender<InstallStatus>>,
+    ) -> anyhow::Result<()> {
+        if let Some(ref s) = sender {
+            let _ = s.send(InstallStatus::NotStarted);
+        }
+
+        println!("Checking dependencies...");
+
+        if let Some(ref s) = sender {
+            let _ = s.send(InstallStatus::InProgress {
+                tool: "None".to_string(),
+                step: "Checking existing tools...".to_string(),
+                progress: 0.05,
+            });
+        }
+
+        let gleam_available = Self::check_tool_in_path("gleam").await;
+        let bun_available = Self::check_tool_in_path("bun").await;
+        let javy_available = Self::check_tool_in_path("javy").await;
+
+        if gleam_available && bun_available && javy_available {
+            println!("All dependencies found in PATH");
+            if let Some(ref s) = sender {
+                let _ = s.send(InstallStatus::Success);
+            }
+            return Ok(());
+        }
+
+        if !(cfg!(target_os = "windows") || cfg!(target_os = "linux") || cfg!(target_os = "macos"))
+        {
+            anyhow::bail!("The operating system is not supported for building the Gleam project")
+        }
+
+        let app_dir = app_dir(AppDataType::UserData, &APP_INFO, "")
+            .map_err(|e| anyhow::anyhow!("Failed to get app directory: {}", e))?;
+
+        let tools_to_install: Vec<(&str, bool)> = vec![
+            ("Gleam", gleam_available),
+            ("Bun", bun_available),
+            ("Javy", javy_available),
+        ];
+        let total_to_install = tools_to_install.iter().filter(|(_, avail)| !avail).count();
+        let mut installed_count = 0;
+
+        if !gleam_available {
+            if let Some(ref s) = sender.clone() {
+                let _ = s.send(InstallStatus::InProgress {
+                    tool: "Gleam".to_string(),
+                    step: "Downloading Gleam...".to_string(),
+                    progress: 0.2 + (installed_count as f32 / total_to_install as f32) * 0.6,
+                });
+            }
+            Self::download_gleam(&app_dir, sender.clone()).await?;
+            installed_count += 1;
+        } else {
+            if let Some(ref s) = sender.clone() {
+                let _ = s.send(InstallStatus::InProgress {
+                    tool: "Gleam".to_string(),
+                    step: "Done!".to_string(),
+                    progress: 1.0,
+                });
+            }
+            installed_count += 1;
+        }
+
+        if !bun_available {
+            if let Some(ref s) = sender.clone() {
+                let _ = s.send(InstallStatus::InProgress {
+                    tool: "Bun".to_string(),
+                    step: "Downloading Bun...".to_string(),
+                    progress: 0.2 + (installed_count as f32 / total_to_install as f32) * 0.6,
+                });
+            }
+            Self::download_bun(&app_dir, sender.clone()).await?;
+            installed_count += 1;
+        } else {
+            if let Some(ref s) = sender.clone() {
+                let _ = s.send(InstallStatus::InProgress {
+                    tool: "Bun".to_string(),
+                    step: "Done!".to_string(),
+                    progress: 1.0,
+                });
+            }
+            installed_count += 1;
+        }
+
+        if !javy_available {
+            if let Some(ref s) = sender.clone() {
+                let _ = s.send(InstallStatus::InProgress {
+                    tool: "Javy".to_string(),
+                    step: "Downloading Javy...".to_string(),
+                    progress: 0.2 + (installed_count as f32 / total_to_install as f32) * 0.6,
+                });
+            }
+            Self::download_javy(&app_dir, sender.clone()).await?;
+            installed_count += 1;
+        } else {
+            if let Some(ref s) = sender.clone() {
+                let _ = s.send(InstallStatus::InProgress {
+                    tool: "Javy".to_string(),
+                    step: "Done!".to_string(),
+                    progress: 1.0,
+                });
+            }
+            installed_count += 1;
+        }
+
+        if let Some(ref s) = sender.clone() {
+            let _ = s.send(InstallStatus::Success);
+        }
+
+        println!(
+            "All {} dependencies installed successfully",
+            installed_count
+        );
+        Ok(())
+    }
+
+    async fn check_tool_in_path(tool: &str) -> bool {
+        let cmd = if cfg!(target_os = "windows") {
+            Command::new("where").arg(tool).output()
+        } else {
+            Command::new("which").arg(tool).output()
+        };
+
+        match cmd {
+            Ok(output) => output.status.success(),
+            Err(_) => false,
+        }
+    }
+
+    pub async fn download_gleam(
+        app_dir: &PathBuf,
+        sender: Option<UnboundedSender<InstallStatus>>,
+    ) -> anyhow::Result<()> {
+        let gleam_dir = app_dir
+            .join("dependencies")
+            .join("gleam")
+            .join(GLEAM_VERSION);
+
+        if gleam_dir.exists() {
+            println!(
+                "Gleam v{} already cached at {}",
+                GLEAM_VERSION,
+                app_dir.display()
+            );
+            return Ok(());
+        }
+
+        println!("Downloading Gleam v{}...", GLEAM_VERSION);
+
+        let gleam_link = Self::get_gleam_download_url()?;
+        Self::download_and_extract(&gleam_link, &gleam_dir, "gleam", sender).await?;
+
+        println!("Gleam v{} downloaded successfully", GLEAM_VERSION);
+        Ok(())
+    }
+
+    pub async fn download_bun(
+        app_dir: &PathBuf,
+        sender: Option<UnboundedSender<InstallStatus>>,
+    ) -> anyhow::Result<()> {
+        let bun_dir = app_dir.join("dependencies").join("bun").join(BUN_VERSION);
+
+        if bun_dir.exists() {
+            println!(
+                "Bun v{} already cached at {}",
+                BUN_VERSION,
+                app_dir.display()
+            );
+            return Ok(());
+        }
+
+        println!("Downloading Bun v{}...", BUN_VERSION);
+
+        let bun_link = Self::get_bun_download_url()?;
+        Self::download_and_extract(&bun_link, &bun_dir, "bun", sender).await?;
+
+        println!("Bun v{} downloaded successfully", BUN_VERSION);
+        Ok(())
+    }
+
+    pub async fn download_javy(
+        app_dir: &PathBuf,
+        sender: Option<UnboundedSender<InstallStatus>>,
+    ) -> anyhow::Result<()> {
+        let javy_dir = app_dir.join("dependencies").join("javy").join(JAVY_VERSION);
+
+        if javy_dir.exists() {
+            println!(
+                "Javy v{} already cached at {}",
+                JAVY_VERSION,
+                app_dir.display()
+            );
+            return Ok(());
+        }
+
+        println!("Downloading Javy v{}...", JAVY_VERSION);
+
+        let javy_link = Self::get_javy_download_url()?;
+        Self::download_and_extract(&javy_link, &javy_dir, "javy", sender).await?;
+
+        println!("Javy v{} downloaded successfully", JAVY_VERSION);
+        Ok(())
+    }
+
+    async fn download_and_extract(
+        url: &str,
+        target_dir: &PathBuf,
+        tool_name: &str,
+        sender: Option<UnboundedSender<InstallStatus>>,
+    ) -> anyhow::Result<()> {
+        if let Some(ref s) = sender {
+            let _ = s.send(InstallStatus::InProgress {
+                step: format!("Creating directories for {}...", tool_name),
+                progress: 0.0,
+                tool: tool_name.to_string(),
+            });
+        }
+
+        fs::create_dir_all(target_dir).await?;
+
+        if let Some(ref s) = sender {
+            let _ = s.send(InstallStatus::InProgress {
+                step: format!("Downloading {}...", tool_name),
+                progress: 0.3,
+                tool: tool_name.to_string(),
+            });
+        }
+
+        let response = reqwest::get(url).await?;
+        let total_size = response.content_length().unwrap_or(0);
+        let mut downloaded = 0;
+        let mut stream = response.bytes_stream();
+
+        let temp_file = target_dir.join(format!("{}_download", tool_name));
+        let mut file = fs::File::create(&temp_file).await?;
+
+        while let Some(item) = stream.next().await {
+            let bytes = item?;
+            file.write_all(&bytes).await?;
+            downloaded += bytes.len() as u64;
+
+            if let Some(ref s) = sender {
+                let progress = 0.3 + (downloaded as f32 / total_size as f32) * 0.4;
+                let _ = s.send(InstallStatus::InProgress {
+                    step: format!("Downloading {}...", tool_name),
+                    progress,
+                    tool: tool_name.to_string(),
+                });
+            }
+        }
+
+        file.sync_all().await?;
+        drop(file);
+
+        if let Some(ref s) = sender {
+            let _ = s.send(InstallStatus::InProgress {
+                step: format!("Extracting {}...", tool_name),
+                progress: 0.7,
+                tool: tool_name.to_string(),
+            });
+        }
+
+        if url.ends_with(".zip") {
+            Self::extract_zip(&temp_file, target_dir).await?;
+        } else if url.ends_with(".tar.gz") {
+            Self::extract_tar_gz(&temp_file, target_dir).await?;
+        } else if url.ends_with(".gz") {
+            Self::extract_gz(&temp_file, target_dir, tool_name).await?;
+        }
+
+        fs::remove_file(&temp_file).await?;
+
+        if let Some(ref s) = sender {
+            let _ = s.send(InstallStatus::InProgress {
+                step: format!("{} installation complete", tool_name),
+                progress: 0.9,
+                tool: tool_name.to_string(),
+            });
+        }
+
+        Ok(())
+    }
+
+    async fn extract_zip(archive: &PathBuf, target_dir: &PathBuf) -> anyhow::Result<()> {
+        let file = std::fs::File::open(archive)?;
+        let mut archive = zip::ZipArchive::new(file)?;
+
+        for i in 0..archive.len() {
+            let mut file = archive.by_index(i)?;
+            let outpath = target_dir.join(file.name());
+
+            if file.is_dir() {
+                fs::create_dir_all(&outpath).await?;
+            } else {
+                if let Some(p) = outpath.parent() {
+                    fs::create_dir_all(p).await?;
+                }
+                let mut outfile = fs::File::create(&outpath).await?;
+                let mut buffer = Vec::new();
+                std::io::Read::read_to_end(&mut file, &mut buffer)?;
+                outfile.write_all(&buffer).await?;
+            }
+        }
+        Ok(())
+    }
+
+    async fn extract_tar_gz(archive: &PathBuf, target_dir: &PathBuf) -> anyhow::Result<()> {
+        let file = std::fs::File::open(archive)?;
+        let tar = flate2::read::GzDecoder::new(file);
+        let mut archive = tar::Archive::new(tar);
+
+        for entry in archive.entries()? {
+            let mut entry = entry?;
+            let path = target_dir.join(entry.path()?);
+            entry.unpack(path)?;
+        }
+        Ok(())
+    }
+
+    async fn extract_gz(
+        archive: &PathBuf,
+        target_dir: &PathBuf,
+        tool_name: &str,
+    ) -> anyhow::Result<()> {
+        let file = std::fs::File::open(archive)?;
+        let mut decoder = flate2::read::GzDecoder::new(file);
+        let mut buffer = Vec::new();
+        std::io::Read::read_to_end(&mut decoder, &mut buffer)?;
+
+        let exe_name = if cfg!(target_os = "windows") {
+            format!("{}.exe", tool_name)
+        } else {
+            tool_name.to_string()
+        };
+
+        let output_path = target_dir.join(exe_name);
+        let mut output_file = fs::File::create(&output_path).await?;
+        output_file.write_all(&buffer).await?;
+
+        #[cfg(unix)]
+        {
+            use std::os::unix::fs::PermissionsExt;
+            let mut perms = output_file.metadata().await?.permissions();
+            perms.set_mode(0o755);
+            fs::set_permissions(&output_path, perms).await?;
+        }
+
+        Ok(())
+    }
+
+    fn get_gleam_download_url() -> anyhow::Result<String> {
+        let gleam_link = {
+            #[cfg(target_os = "windows")]
+            {
+                let arch = {
+                    if cfg!(target_arch = "aarch64") {
+                        "aarch64"
+                    } else if cfg!(target_arch = "x86_64") {
+                        "x86_64"
+                    } else {
+                        anyhow::bail!(
+                            "This architecture is not supported for building the gleam project"
+                        );
+                    }
+                };
+                format!(
+                    "https://github.com/gleam-lang/gleam/releases/download/v{}/gleam-v{}-{}-pc-windows-msvc.zip",
+                    GLEAM_VERSION, GLEAM_VERSION, arch,
+                )
+            }
+
+            #[cfg(target_os = "linux")]
+            {
+                let arch = {
+                    if cfg!(target_arch = "aarch64") {
+                        "aarch64"
+                    } else if cfg!(target_arch = "x86_64") {
+                        "x86_64"
+                    } else {
+                        anyhow::bail!(
+                            "This architecture is not supported for building the gleam project"
+                        );
+                    }
+                };
+                format!(
+                    "https://github.com/gleam-lang/gleam/releases/download/v{}/gleam-v{}-{}-unknown-linux-musl.tar.gz",
+                    GLEAM_VERSION, GLEAM_VERSION, arch,
+                )
+            }
+
+            #[cfg(target_os = "macos")]
+            {
+                let arch = {
+                    if cfg!(target_arch = "aarch64") {
+                        "aarch64"
+                    } else if cfg!(target_arch = "x86_64") {
+                        "x86_64"
+                    } else {
+                        anyhow::bail!(
+                            "This architecture is not supported for building the gleam project"
+                        );
+                    }
+                };
+                format!(
+                    "https://github.com/gleam-lang/gleam/releases/download/v{}/gleam-v{}-{}-apple-darwin.tar.gz",
+                    GLEAM_VERSION, GLEAM_VERSION, arch,
+                )
+            }
+        };
+        Ok(gleam_link)
+    }
+
+    fn get_bun_download_url() -> anyhow::Result<String> {
+        let bun_link = {
+            #[cfg(target_os = "windows")]
+            {
+                let arch = {
+                    if cfg!(target_arch = "aarch64") {
+                        "aarch64"
+                    } else if cfg!(target_arch = "x86_64") {
+                        "x64"
+                    } else {
+                        anyhow::bail!(
+                            "This architecture is not supported for building the gleam project"
+                        );
+                    }
+                };
+                format!(
+                    "https://github.com/oven-sh/bun/releases/download/bun-v{}/bun-windows-{}.zip",
+                    BUN_VERSION, arch,
+                )
+            }
+
+            #[cfg(target_os = "linux")]
+            {
+                let arch = {
+                    if cfg!(target_arch = "aarch64") {
+                        "aarch64"
+                    } else if cfg!(target_arch = "x86_64") {
+                        "x64"
+                    } else {
+                        anyhow::bail!(
+                            "This architecture is not supported for building the gleam project"
+                        );
+                    }
+                };
+                format!(
+                    "https://github.com/oven-sh/bun/releases/download/bun-v{}/bun-linux-{}.zip",
+                    BUN_VERSION, arch,
+                )
+            }
+
+            #[cfg(target_os = "macos")]
+            {
+                let arch = {
+                    if cfg!(target_arch = "aarch64") {
+                        "aarch64"
+                    } else if cfg!(target_arch = "x86_64") {
+                        "x64"
+                    } else {
+                        anyhow::bail!(
+                            "This architecture is not supported for building the gleam project"
+                        );
+                    }
+                };
+                format!(
+                    "https://github.com/oven-sh/bun/releases/download/bun-v{}/bun-darwin-{}.zip",
+                    BUN_VERSION, arch,
+                )
+            }
+        };
+        Ok(bun_link)
+    }
+
+    fn get_javy_download_url() -> anyhow::Result<String> {
+        let javy_link = {
+            #[cfg(target_os = "windows")]
+            {
+                let arch = {
+                    if cfg!(target_arch = "aarch64") {
+                        anyhow::bail!(
+                            "This arch is not available for prebuilt download. Please build this from source"
+                        );
+                    } else if cfg!(target_arch = "x86_64") {
+                        "x86_64"
+                    } else {
+                        anyhow::bail!(
+                            "This architecture is not supported for building the gleam project"
+                        );
+                    }
+                };
+                format!(
+                    "https://github.com/bytecodealliance/javy/releases/download/v{}/javy-{}-windows-v{}.gz",
+                    JAVY_VERSION, arch, JAVY_VERSION
+                )
+            }
+
+            #[cfg(target_os = "linux")]
+            {
+                let arch = {
+                    if cfg!(target_arch = "aarch64") {
+                        "arm"
+                    } else if cfg!(target_arch = "x86_64") {
+                        "x86_64"
+                    } else {
+                        anyhow::bail!(
+                            "This architecture is not supported for building the gleam project"
+                        );
+                    }
+                };
+                format!(
+                    "https://github.com/bytecodealliance/javy/releases/download/v{}/javy-{}-linux-v{}.gz",
+                    JAVY_VERSION, arch, JAVY_VERSION
+                )
+            }
+
+            #[cfg(target_os = "macos")]
+            {
+                let arch = {
+                    if cfg!(target_arch = "aarch64") {
+                        "arm"
+                    } else if cfg!(target_arch = "x86_64") {
+                        "x86_64"
+                    } else {
+                        anyhow::bail!(
+                            "This architecture is not supported for building the gleam project"
+                        );
+                    }
+                };
+                format!(
+                    "https://github.com/bytecodealliance/javy/releases/download/v{}/javy-{}-macos-v{}.gz",
+                    JAVY_VERSION, arch, JAVY_VERSION
+                )
+            }
+        };
+        Ok(javy_link)
+    }
+}
+
+#[tokio::test]
+async fn check_if_dependencies_install() {
+    GleamScriptCompiler::ensure_dependencies(None)
+        .await
+        .unwrap();
+}
diff --git a/eucalyptus-editor/src/build/mod.rs b/eucalyptus-editor/src/build/mod.rs
index dfd18ae..ff61777 100644
--- a/eucalyptus-editor/src/build/mod.rs
+++ b/eucalyptus-editor/src/build/mod.rs
@@ -1,3 +1,5 @@
+pub mod gleam;
+
 use std::{collections::HashMap, fs, path::PathBuf, process::Command};
 
 use clap::ArgMatches;
diff --git a/eucalyptus-editor/src/camera.rs b/eucalyptus-editor/src/camera.rs
index 7447bbe..f83bebb 100644
--- a/eucalyptus-editor/src/camera.rs
+++ b/eucalyptus-editor/src/camera.rs
@@ -1,4 +1,4 @@
-use crate::editor::component::Component;
+use crate::editor::component::InspectableComponent;
 use crate::editor::{EntityType, Signal, StaticallyKept, UndoableAction};
 use dropbear_engine::camera::Camera;
 use egui::{CollapsingHeader, Ui};
@@ -6,7 +6,7 @@ use eucalyptus_core::camera::{CameraAction, CameraComponent, CameraFollowTarget,
 use hecs::Entity;
 use std::time::Instant;
 
-impl Component for Camera {
+impl InspectableComponent for Camera {
     fn inspect(
         &mut self,
         entity: &mut Entity,
@@ -81,7 +81,7 @@ pub enum UndoableCameraAction {
     Type(Entity, CameraType),
 }
 
-impl Component for CameraComponent {
+impl InspectableComponent for CameraComponent {
     fn inspect(
         &mut self,
         _entity: &mut Entity,
@@ -159,7 +159,7 @@ impl Component for CameraComponent {
     }
 }
 
-impl Component for CameraFollowTarget {
+impl InspectableComponent for CameraFollowTarget {
     fn inspect(
         &mut self,
         _entity: &mut Entity,
diff --git a/eucalyptus-editor/src/debug.rs b/eucalyptus-editor/src/debug.rs
index 023d66d..1852032 100644
--- a/eucalyptus-editor/src/debug.rs
+++ b/eucalyptus-editor/src/debug.rs
@@ -1,249 +1,195 @@
 //! Used to aid with debugging any issues with the editor.
+use crate::build::gleam::GleamScriptCompiler;
+use crate::build::gleam::InstallStatus;
 use crate::editor::Signal;
-use egui::{Ui, Window, ProgressBar};
-use eucalyptus_core::scripting::build::GleamScriptCompiler;
+use egui::ProgressBar;
+use egui::Ui;
+use egui::Window;
 use tokio::sync::mpsc;
 
-#[derive(Debug, Clone)]
-pub enum DependencyProgress {
-    Starting,
-    CheckingPath(String),
-    Downloading(String),
-    Extracting(String),
-    Completed(String),
-    Error(String),
-    Finished,
-}
-
 pub struct DependencyInstaller {
-    pub progress_receiver: Option<mpsc::UnboundedReceiver<DependencyProgress>>,
-    pub current_progress: Vec<String>,
+    pub progress_receiver: Option<mpsc::UnboundedReceiver<InstallStatus>>,
     pub is_installing: bool,
-    pub progress_value: f32,
+
+    pub gleam_progress: f32,
+    pub bun_progress: f32,
+    pub javy_progress: f32,
+
+    pub gleam_status: String,
+    pub bun_status: String,
+    pub javy_status: String,
 }
 
 impl Default for DependencyInstaller {
     fn default() -> Self {
         Self {
             progress_receiver: None,
-            current_progress: Vec::new(),
             is_installing: false,
-            progress_value: 0.0,
+            gleam_progress: 0.0,
+            bun_progress: 0.0,
+            javy_progress: 0.0,
+            gleam_status: "Not started".to_string(),
+            bun_status: "Not started".to_string(),
+            javy_status: "Not started".to_string(),
         }
     }
 }
 
-/// Show a menu bar for debug. A new "Debug" menu button will show up on the editors menu bar.
-pub(crate) fn show_menu_bar(ui: &mut Ui, signal: &mut Signal, dependency_installer: &mut DependencyInstaller) {
-    ui.menu_button("Debug", |ui_debug| {
-        if ui_debug.button("Panic").clicked() {
-            log::warn!("Panic caused on purpose from Menu Button Click");
-            panic!("Testing out panicking with new panic module, this is a test")
-        }
-
-        if ui_debug.button("Show Entities Loaded").clicked() {
-            log::info!("Show Entities Loaded under Debug Menu is clicked");
-            *signal = Signal::LogEntities;
-        }
-
-        ui_debug.add_enabled_ui(!dependency_installer.is_installing, |ui| {
-            if ui.button("Ensure dependencies").clicked() {
-                log::info!("Clicked ensure dependencies from debug menu");
-                start_dependency_installation(dependency_installer);
-            }
-        });
-
-        if ui_debug.button("Evaluate script").clicked() {
-            log::info!("Evaluating script");
-        }
-    });
-}
-
-pub(crate) fn show_dependency_progress_window(
-    ctx: &egui::Context,
-    dependency_installer: &mut DependencyInstaller,
-) {
-    if let Some(receiver) = &mut dependency_installer.progress_receiver {
-        while let Ok(progress) = receiver.try_recv() {
-            match &progress {
-                DependencyProgress::Starting => {
-                    dependency_installer.current_progress.clear();
-                    dependency_installer.current_progress.push("Starting dependency check...".to_string());
-                    dependency_installer.progress_value = 0.0;
-                }
-                DependencyProgress::CheckingPath(tool) => {
-                    dependency_installer.current_progress.push(format!("Checking if {} is in PATH...", tool));
-                    dependency_installer.progress_value = 0.1;
-                }
-                DependencyProgress::Downloading(tool) => {
-                    dependency_installer.current_progress.push(format!("Downloading {}...", tool));
-                    dependency_installer.progress_value += 0.25;
-                }
-                DependencyProgress::Extracting(tool) => {
-                    dependency_installer.current_progress.push(format!("Extracting {}...", tool));
-                    dependency_installer.progress_value += 0.1;
-                }
-                DependencyProgress::Completed(tool) => {
-                    dependency_installer.current_progress.push(format!("✓ {} ready", tool));
-                    dependency_installer.progress_value += 0.1;
-                }
-                DependencyProgress::Error(error) => {
-                    dependency_installer.current_progress.push(format!("❌ Error: {}", error));
-                }
-                DependencyProgress::Finished => {
-                    dependency_installer.current_progress.push("✓ All dependencies ready!".to_string());
-                    dependency_installer.progress_value = 1.0;
-                    dependency_installer.is_installing = false;
-                    // dependency_installer.progress_receiver = None;
+impl DependencyInstaller {
+    pub fn update_progress(&mut self) {
+        let mut local_prog_rec = false;
+        let mut update_tool_status: (bool, String, f32, String) = Default::default();
+        if let Some(receiver) = &mut self.progress_receiver {
+            while let Ok(status) = receiver.try_recv() {
+                match status {
+                    InstallStatus::NotStarted => {
+                        self.is_installing = false;
+                    }
+                    InstallStatus::InProgress {
+                        tool,
+                        step,
+                        progress,
+                    } => {
+                        self.is_installing = true;
+                        update_tool_status =
+                            (true, String::from(&tool), progress, String::from(&step));
+                    }
+                    InstallStatus::Success => {
+                        self.is_installing = false;
+                        local_prog_rec = true;
+                        self.gleam_status = "Complete".to_string();
+                        self.gleam_progress = 1.0;
+                        self.bun_status = "Complete".to_string();
+                        self.bun_progress = 1.0;
+                        self.javy_status = "Complete".to_string();
+                        self.javy_progress = 1.0;
+                    }
+                    InstallStatus::Failed(msg) => {
+                        self.is_installing = false;
+                        log::error!("Installation error: {}", msg);
+                        self.gleam_status = format!("Error: {}", msg);
+                        self.bun_status = format!("Error: {}", msg);
+                        self.javy_status = format!("Error: {}", msg);
+                    }
                 }
             }
         }
-    }
-
-    if dependency_installer.is_installing || !dependency_installer.current_progress.is_empty() {
-        Window::new("Dependency Installation")
-            .collapsible(false)
-            .resizable(false)
-            .show(ctx, |ui| {
-                ui.vertical(|ui| {
-                    ui.add(
-                        ProgressBar::new(dependency_installer.progress_value)
-                            .show_percentage()
-                            .animate(dependency_installer.is_installing)
-                    );
-                    
-                    ui.separator();
-                    
-                    egui::ScrollArea::vertical()
-                        .max_height(200.0)
-                        .show(ui, |ui| {
-                            for message in &dependency_installer.current_progress {
-                                ui.label(message);
-                            }
-                        });
-                    
-                    if !dependency_installer.is_installing && ui.button("Close").clicked() {
-                        dependency_installer.current_progress.clear();
-                    }
-                });
-            });
-    }
-}
-
-fn start_dependency_installation(dependency_installer: &mut DependencyInstaller) {
-    let (sender, receiver) = mpsc::unbounded_channel();
-    dependency_installer.progress_receiver = Some(receiver);
-    dependency_installer.is_installing = true;
-    dependency_installer.progress_value = 0.0;
-    
-    tokio::spawn(async move {
-        let _ = sender.send(DependencyProgress::Starting);
-        
-        match ensure_dependencies_with_progress(sender.clone()).await {
-            Ok(_) => {
-                let _ = sender.send(DependencyProgress::Finished);
-            }
-            Err(e) => {
-                let _ = sender.send(DependencyProgress::Error(e.to_string()));
-                let _ = sender.send(DependencyProgress::Finished);
-            }
+        if local_prog_rec {
+            self.progress_receiver = None;
         }
-    });
-}
-
-async fn ensure_dependencies_with_progress(
-    progress_sender: mpsc::UnboundedSender<DependencyProgress>,
-) -> anyhow::Result<()> {
-    let tools = vec![
-        ("gleam", "Gleam"),
-        ("bun", "Bun"), 
-        ("javy", "Javy"),
-    ];
-    
-    let mut tools_to_download = Vec::new();
-    
-    for (tool_cmd, tool_name) in &tools {
-        let _ = progress_sender.send(DependencyProgress::CheckingPath(tool_name.to_string()));
-        
-        let available = check_tool_in_path(tool_cmd).await;
-        if !available {
-            tools_to_download.push((*tool_cmd, *tool_name));
-        } else {
-            let _ = progress_sender.send(DependencyProgress::Completed(format!("{} (found in PATH)", tool_name)));
+        if update_tool_status.0 {
+            self.update_tool_status(
+                update_tool_status.1.as_str(),
+                update_tool_status.2,
+                update_tool_status.3.as_str(),
+            );
         }
     }
-    
-    if tools_to_download.is_empty() {
-        return Ok(());
-    }
-    
-    let app_dir = app_dirs2::app_dir(app_dirs2::AppDataType::UserData, &eucalyptus_core::scripting::build::APP_INFO, "")
-        .map_err(|e| anyhow::anyhow!("Failed to get app directory: {}", e))?;
-    
-    for (tool_cmd, tool_name) in tools_to_download {
-        let _ = progress_sender.send(DependencyProgress::Downloading(tool_name.to_string()));
-        
-        match tool_cmd {
+
+    fn update_tool_status(&mut self, tool: &str, progress: f32, status: &str) {
+        match tool.to_lowercase().as_str() {
             "gleam" => {
-                if let Err(e) = download_gleam_with_progress(&app_dir, progress_sender.clone()).await {
-                    let _ = progress_sender.send(DependencyProgress::Error(format!("Failed to download Gleam: {}", e)));
-                    return Err(e);
-                }
+                self.gleam_progress = progress;
+                self.gleam_status = status.to_string();
             }
             "bun" => {
-                if let Err(e) = download_bun_with_progress(&app_dir, progress_sender.clone()).await {
-                    let _ = progress_sender.send(DependencyProgress::Error(format!("Failed to download Bun: {}", e)));
-                    return Err(e);
-                }
+                self.bun_progress = progress;
+                self.bun_status = status.to_string();
             }
             "javy" => {
-                if let Err(e) = download_javy_with_progress(&app_dir, progress_sender.clone()).await {
-                    let _ = progress_sender.send(DependencyProgress::Error(format!("Failed to download Javy: {}", e)));
-                    return Err(e);
-                }
+                self.javy_progress = progress;
+                self.javy_status = status.to_string();
             }
             _ => {}
         }
-        
-        let _ = progress_sender.send(DependencyProgress::Completed(tool_name.to_string()));
     }
-    
-    Ok(())
-}
 
-async fn check_tool_in_path(tool: &str) -> bool {
-    let cmd = if cfg!(target_os = "windows") {
-        std::process::Command::new("where").arg(tool).output()
-    } else {
-        std::process::Command::new("which").arg(tool).output()
-    };
+    pub fn show_installation_window(&mut self, ctx: &egui::Context) {
+        Window::new("Installing Dependencies")
+            .resizable(true)
+            .collapsible(false)
+            .default_width(400.0)
+            .show(ctx, |ui| {
+                ui.heading("Installing Dependencies");
+
+                ui.separator();
+
+                ui.label("Gleam:");
+                ui.label(&self.gleam_status);
+                ui.add(ProgressBar::new(self.gleam_progress).show_percentage());
+                ui.separator();
+
+                ui.label("Bun:");
+                ui.label(&self.bun_status);
+                ui.add(ProgressBar::new(self.bun_progress).show_percentage());
+                ui.separator();
+
+                ui.label("Javy:");
+                ui.label(&self.javy_status);
+                ui.add(ProgressBar::new(self.javy_progress).show_percentage());
+                ui.separator();
+
+                let overall_progress =
+                    (self.gleam_progress + self.bun_progress + self.javy_progress) / 3.0;
+                ui.label("Overall Progress:");
+                ui.add(ProgressBar::new(overall_progress).show_percentage());
 
-    match cmd {
-        Ok(output) => output.status.success(),
-        Err(_) => false,
+                ui.separator();
+
+                if ui.button("Cancel").clicked() {
+                    self.is_installing = false;
+                    self.progress_receiver = None;
+                }
+            });
     }
 }
 
-async fn download_gleam_with_progress(
-    app_dir: &std::path::PathBuf,
-    progress_sender: mpsc::UnboundedSender<DependencyProgress>,
-) -> anyhow::Result<()> {
-    let _ = progress_sender.send(DependencyProgress::Extracting("Gleam".to_string()));
-    GleamScriptCompiler::download_gleam(app_dir).await
-}
+pub(crate) fn show_menu_bar(
+    ui: &mut Ui,
+    signal: &mut Signal,
+    dependency_installer: &mut DependencyInstaller,
+) {
+    ui.menu_button("Debug", |ui_debug| {
+        if ui_debug.button("Panic").clicked() {
+            log::warn!("Panic caused on purpose from Menu Button Click");
+            panic!("Testing out panicking with new panic module, this is a test")
+        }
 
-async fn download_bun_with_progress(
-    app_dir: &std::path::PathBuf,
-    progress_sender: mpsc::UnboundedSender<DependencyProgress>,
-) -> anyhow::Result<()> {
-    let _ = progress_sender.send(DependencyProgress::Extracting("Bun".to_string()));
-    GleamScriptCompiler::download_bun(app_dir).await
-}
+        if ui_debug.button("Show Entities Loaded").clicked() {
+            log::info!("Show Entities Loaded under Debug Menu is clicked");
+            *signal = Signal::LogEntities;
+        }
+
+        ui_debug.add_enabled_ui(!dependency_installer.is_installing, |ui| {
+            if ui.button("Ensure dependencies").clicked() {
+                log::info!("Clicked ensure dependencies from debug menu");
+
+                let (sender, receiver) = mpsc::unbounded_channel();
+                dependency_installer.progress_receiver = Some(receiver);
+                dependency_installer.is_installing = true;
+
+                dependency_installer.gleam_progress = 0.0;
+                dependency_installer.bun_progress = 0.0;
+                dependency_installer.javy_progress = 0.0;
+                dependency_installer.gleam_status = "Starting...".to_string();
+                dependency_installer.bun_status = "Starting...".to_string();
+                dependency_installer.javy_status = "Starting...".to_string();
+
+                tokio::task::spawn(async move {
+                    match GleamScriptCompiler::ensure_dependencies(Some(sender.clone())).await {
+                        Ok(_) => {
+                            let _ = sender.send(InstallStatus::Success);
+                        }
+                        Err(e) => {
+                            let _ = sender.send(InstallStatus::Failed(e.to_string()));
+                        }
+                    }
+                });
+            }
+        });
 
-async fn download_javy_with_progress(
-    app_dir: &std::path::PathBuf,
-    progress_sender: mpsc::UnboundedSender<DependencyProgress>,
-) -> anyhow::Result<()> {
-    let _ = progress_sender.send(DependencyProgress::Extracting("Javy".to_string()));
-    GleamScriptCompiler::download_javy(app_dir).await
-}
\ No newline at end of file
+        if ui_debug.button("Evaluate script").clicked() {
+            log::info!("Evaluating script");
+        }
+    });
+}
diff --git a/eucalyptus-editor/src/editor/component.rs b/eucalyptus-editor/src/editor/component.rs
index 5f031f8..1318763 100644
--- a/eucalyptus-editor/src/editor/component.rs
+++ b/eucalyptus-editor/src/editor/component.rs
@@ -12,7 +12,7 @@ use glam::Vec3;
 use hecs::Entity;
 use std::time::Instant;
 
-pub trait Component {
+pub trait InspectableComponent {
     fn inspect(
         &mut self,
         entity: &mut hecs::Entity,
@@ -24,7 +24,7 @@ pub trait Component {
     );
 }
 
-impl Component for Transform {
+impl InspectableComponent for Transform {
     fn inspect(
         &mut self,
         entity: &mut Entity,
@@ -405,7 +405,7 @@ impl Component for Transform {
     }
 }
 
-impl Component for ScriptComponent {
+impl InspectableComponent for ScriptComponent {
     fn inspect(
         &mut self,
         _entity: &mut Entity,
@@ -506,7 +506,7 @@ impl Component for ScriptComponent {
     }
 }
 
-impl Component for AdoptedEntity {
+impl InspectableComponent for AdoptedEntity {
     fn inspect(
         &mut self,
         entity: &mut Entity,
@@ -552,7 +552,7 @@ impl Component for AdoptedEntity {
     }
 }
 
-impl Component for Light {
+impl InspectableComponent for Light {
     fn inspect(
         &mut self,
         entity: &mut Entity,
@@ -597,7 +597,7 @@ impl Component for Light {
     }
 }
 
-impl Component for LightComponent {
+impl InspectableComponent for LightComponent {
     fn inspect(
         &mut self,
         _entity: &mut Entity,
diff --git a/eucalyptus-editor/src/editor/dock.rs b/eucalyptus-editor/src/editor/dock.rs
index bfa96cf..aaaee6f 100644
--- a/eucalyptus-editor/src/editor/dock.rs
+++ b/eucalyptus-editor/src/editor/dock.rs
@@ -3,7 +3,7 @@ use crate::editor::ViewportMode;
 use std::{collections::HashSet, sync::LazyLock};
 
 use crate::APP_INFO;
-use crate::editor::component::Component;
+use crate::editor::component::InspectableComponent;
 use crate::editor::scene::PENDING_SPAWNS;
 use dropbear_engine::{
     entity::Transform,
@@ -16,24 +16,21 @@ use eucalyptus_core::states::{Node, RESOURCES, ResourceType};
 use eucalyptus_core::utils::PendingSpawn;
 use log;
 use parking_lot::Mutex;
-use transform_gizmo_egui::{
-    EnumSet, Gizmo, GizmoConfig, GizmoExt, GizmoMode,
-    math::{DMat4, DVec3},
-};
+use transform_gizmo_egui::{EnumSet, Gizmo, GizmoConfig, GizmoExt, GizmoMode, math::DVec3};
 
 pub struct EditorTabViewer<'a> {
     pub view: egui::TextureId,
     pub nodes: Vec<EntityNode>,
     pub tex_size: Extent3d,
     pub gizmo: &'a mut Gizmo,
-    pub world: &'a mut Arc<World>,
+    pub world: Arc<RwLock<World>>,
     pub selected_entity: &'a mut Option<hecs::Entity>,
     pub viewport_mode: &'a mut ViewportMode,
     pub undo_stack: &'a mut Vec<UndoableAction>,
     pub signal: &'a mut Signal,
     pub gizmo_mode: &'a mut EnumSet<GizmoMode>,
     pub editor_mode: &'a mut EditorState,
-    pub active_camera: &'a mut Option<hecs::Entity>,
+    pub active_camera: &'a mut Arc<Mutex<Option<hecs::Entity>>>,
 }
 
 impl<'a> EditorTabViewer<'a> {
@@ -69,7 +66,6 @@ impl<'a> EditorTabViewer<'a> {
     }
 }
 
-
 #[derive(Clone, Debug)]
 pub struct DraggedAsset {
     pub name: String,
@@ -134,9 +130,10 @@ impl<'a> TabViewer for EditorTabViewer<'a> {
 
         match tab {
             EditorTab::Viewport => {
+                log_once::debug_once!("Viewport focused");
                 // ------------------- Template for querying active camera -----------------
                 // if let Some(active_camera) = self.active_camera {
-                //     if let Ok(mut q) = self.world.query_one::<(&Camera, &CameraComponent, Option<&CameraFollowTarget>)>(*active_camera) {
+                //     if let Ok(mut q) = self.world.read().query_one::<(&Camera, &CameraComponent, Option<&CameraFollowTarget>)>(*active_camera) {
                 //         if let Some((camera, component, follow_target)) = q.get() {
 
                 //         } else {
@@ -194,151 +191,156 @@ impl<'a> TabViewer for EditorTabViewer<'a> {
                 );
 
                 if image_response.clicked() {
-                    if let Some(active_camera) = self.active_camera {
-                        if let Ok(mut q) = self.world.query_one::<(
-                            &Camera,
-                            &CameraComponent,
-                            Option<&CameraFollowTarget>,
-                        )>(*active_camera)
+                    let active_cam = self.active_camera.lock();
+                    if let Some(active_camera) = *active_cam {
                         {
-                            if let Some((camera, _, _)) = q.get() {
-                                if let Some(click_pos) =
-                                    ui.ctx().input(|i| i.pointer.interact_pos())
-                                {
-                                    let viewport_rect = image_response.rect;
-                                    let local_pos = click_pos - viewport_rect.min;
+                            if let Ok(mut q) = self.world.read().query_one::<(
+                                &Camera,
+                                &CameraComponent,
+                                Option<&CameraFollowTarget>,
+                            )>(active_camera)
+                            {
+                                if let Some((camera, _, _)) = q.get() {
+                                    if let Some(click_pos) =
+                                        ui.ctx().input(|i| i.pointer.interact_pos())
+                                    {
+                                        let viewport_rect = image_response.rect;
+                                        let local_pos = click_pos - viewport_rect.min;
 
-                                    let ndc_x = (2.0 * local_pos.x / viewport_rect.width()) - 1.0;
-                                    let ndc_y = 1.0 - (2.0 * local_pos.y / viewport_rect.height());
+                                        let ndc_x = (2.0 * local_pos.x / viewport_rect.width()) - 1.0;
+                                        let ndc_y = 1.0 - (2.0 * local_pos.y / viewport_rect.height());
 
-                                    let view_matrix = glam::DMat4::look_at_lh(
-                                        camera.eye,
-                                        camera.target,
-                                        camera.up,
-                                    );
+                                        let view_matrix = glam::DMat4::look_at_lh(
+                                            camera.eye,
+                                            camera.target,
+                                            camera.up,
+                                        );
 
-                                    let proj_matrix = glam::DMat4::perspective_lh(
-                                        camera.fov_y.to_radians(),
-                                        camera.aspect,
-                                        camera.znear,
-                                        camera.zfar,
-                                    );
+                                        let proj_matrix = glam::DMat4::perspective_lh(
+                                            camera.fov_y.to_radians(),
+                                            camera.aspect,
+                                            camera.znear,
+                                            camera.zfar,
+                                        );
 
-                                    if !view_matrix.is_finite() {
-                                        log::error!("Invalid view matrix");
-                                        return;
-                                    }
-                                    if !proj_matrix.is_finite() {
-                                        log::error!("Invalid projection matrix");
-                                        return;
-                                    }
+                                        if !view_matrix.is_finite() {
+                                            log::error!("Invalid view matrix");
+                                            return;
+                                        }
+                                        if !proj_matrix.is_finite() {
+                                            log::error!("Invalid projection matrix");
+                                            return;
+                                        }
 
-                                    let view_proj = proj_matrix * view_matrix;
-                                    let inv_view_proj = view_proj.inverse();
+                                        let view_proj = proj_matrix * view_matrix;
+                                        let inv_view_proj = view_proj.inverse();
 
-                                    if !inv_view_proj.is_finite() {
-                                        log::error!("Cannot invert view-projection matrix");
-                                        return;
-                                    }
+                                        if !inv_view_proj.is_finite() {
+                                            log::error!("Cannot invert view-projection matrix");
+                                            return;
+                                        }
 
-                                    let ray_start_ndc =
-                                        glam::DVec4::new(ndc_x as f64, ndc_y as f64, 0.0, 1.0);
-                                    let ray_end_ndc =
-                                        glam::DVec4::new(ndc_x as f64, ndc_y as f64, 1.0, 1.0);
+                                        let ray_start_ndc =
+                                            glam::DVec4::new(ndc_x as f64, ndc_y as f64, 0.0, 1.0);
+                                        let ray_end_ndc =
+                                            glam::DVec4::new(ndc_x as f64, ndc_y as f64, 1.0, 1.0);
 
-                                    let ray_start_world = inv_view_proj * ray_start_ndc;
-                                    let ray_end_world = inv_view_proj * ray_end_ndc;
+                                        let ray_start_world = inv_view_proj * ray_start_ndc;
+                                        let ray_end_world = inv_view_proj * ray_end_ndc;
 
-                                    if ray_start_world.w == 0.0 || ray_end_world.w == 0.0 {
-                                        log::error!("Invalid homogeneous coordinates");
-                                        return;
-                                    }
+                                        if ray_start_world.w == 0.0 || ray_end_world.w == 0.0 {
+                                            log::error!("Invalid homogeneous coordinates");
+                                            return;
+                                        }
 
-                                    let ray_start = ray_start_world.truncate() / ray_start_world.w;
-                                    let ray_end = ray_end_world.truncate() / ray_end_world.w;
+                                        let ray_start = ray_start_world.truncate() / ray_start_world.w;
+                                        let ray_end = ray_end_world.truncate() / ray_end_world.w;
 
-                                    if !ray_start.is_finite() || !ray_end.is_finite() {
-                                        log::error!(
+                                        if !ray_start.is_finite() || !ray_end.is_finite() {
+                                            log::error!(
                                             "Invalid ray points - start: {:?}, end: {:?}",
                                             ray_start,
                                             ray_end
                                         );
-                                        return;
-                                    }
+                                            return;
+                                        }
 
-                                    let ray_direction = (ray_end - ray_start).normalize();
+                                        let ray_direction = (ray_end - ray_start).normalize();
 
-                                    if !ray_direction.is_finite() {
-                                        log::error!("Invalid ray direction: {:?}", ray_direction);
-                                        return;
-                                    }
+                                        if !ray_direction.is_finite() {
+                                            log::error!("Invalid ray direction: {:?}", ray_direction);
+                                            return;
+                                        }
 
-                                    let mut closest_distance = f64::INFINITY;
-                                    let mut selected_entity_id: Option<hecs::Entity> = None;
-                                    let mut entity_count = 0;
+                                        let (selected_entity_id, entity_count) = {
+                                            let mut closest_distance = f64::INFINITY;
+                                            let mut selected_entity_id: Option<hecs::Entity> = None;
+                                            let mut entity_count = 0;
 
-                                    for (entity_id, (transform, _)) in
-                                        self.world.query::<(&Transform, &AdoptedEntity)>().iter()
-                                    {
-                                        entity_count += 1;
-                                        let entity_pos = transform.position;
-                                        let sphere_radius = transform.scale.max_element() * 1.5;
-
-                                        let to_sphere = entity_pos - ray_start;
-                                        let projection = to_sphere.dot(ray_direction);
-
-                                        if projection > 0.0 {
-                                            let closest_point =
-                                                ray_start + ray_direction * projection;
-                                            let distance_to_sphere =
-                                                (closest_point - entity_pos).length();
-
-                                            if distance_to_sphere <= sphere_radius {
-                                                let discriminant = sphere_radius * sphere_radius
-                                                    - distance_to_sphere * distance_to_sphere;
-                                                if discriminant >= 0.0 {
-                                                    let intersection_distance =
-                                                        projection - discriminant.sqrt();
-
-                                                    if intersection_distance < closest_distance {
-                                                        closest_distance = intersection_distance;
-                                                        selected_entity_id = Some(entity_id);
+                                            {
+                                                let world_read_guard = self.world.read();
+                                                for (entity_id, (transform, _)) in
+                                                    world_read_guard.query::<(&Transform, &AdoptedEntity)>().iter()
+                                                {
+                                                    entity_count += 1;
+                                                    let entity_pos = transform.position;
+                                                    let sphere_radius = transform.scale.max_element() * 1.5;
+                                                    let to_sphere = entity_pos - ray_start;
+                                                    let projection = to_sphere.dot(ray_direction);
+                                                    if projection > 0.0 {
+                                                        let closest_point =
+                                                            ray_start + ray_direction * projection;
+                                                        let distance_to_sphere =
+                                                            (closest_point - entity_pos).length();
+                                                        if distance_to_sphere <= sphere_radius {
+                                                            let discriminant = sphere_radius * sphere_radius
+                                                                - distance_to_sphere * distance_to_sphere;
+                                                            if discriminant >= 0.0 {
+                                                                let intersection_distance =
+                                                                    projection - discriminant.sqrt();
+                                                                if intersection_distance < closest_distance {
+                                                                    closest_distance = intersection_distance;
+                                                                    selected_entity_id = Some(entity_id);
+                                                                }
+                                                            }
+                                                        }
                                                     }
                                                 }
                                             }
-                                        }
-                                    }
 
-                                    log::debug!("Total entities checked: {}", entity_count);
+                                            (selected_entity_id, entity_count)
+                                        };
 
-                                    if !matches!(self.editor_mode, EditorState::Playing) {
-                                        if let Some(entity_id) = selected_entity_id {
-                                            *self.selected_entity = Some(entity_id);
-                                            log::debug!("Selected entity: {:?}", entity_id);
-                                        } else {
-                                            // *self.selected_entity = None;
-                                            if entity_count == 0 {
-                                                log::debug!("No entities in world to select");
+                                        log::debug!("Total entities checked: {}", entity_count);
+
+                                        if !matches!(self.editor_mode, EditorState::Playing) {
+                                            if let Some(entity_id) = selected_entity_id {
+                                                *self.selected_entity = Some(entity_id);
+                                                log::debug!("Selected entity: {:?}", entity_id);
                                             } else {
-                                                log::debug!(
+                                                if entity_count == 0 {
+                                                    log::debug!("No entities in world.read() to select");
+                                                } else {
+                                                    log::debug!(
                                                     "No entity hit by ray (checked {} entities)",
                                                     entity_count
                                                 );
+                                                }
                                             }
                                         }
                                     }
-                                }
-                            } else {
-                                log_once::warn_once!(
+                                } else {
+                                    log_once::warn_once!(
                                     "Unable to fetch the query result of camera: {:?}",
                                     active_camera
                                 )
-                            }
-                        } else {
-                            log_once::warn_once!(
+                                }
+                            } else {
+                                log_once::warn_once!(
                                 "Unable to query camera, component and option<camerafollowtarget> for active camera: {:?}",
                                 active_camera
                             );
+                            }
                         }
                     } else {
                         log_once::warn_once!("No active camera found");
@@ -350,106 +352,82 @@ impl<'a> TabViewer for EditorTabViewer<'a> {
                 // Note to self: fuck you >:(
                 // Note to self: ok wow thats pretty rude im trying my best >﹏<
                 // Note to self: finally holy shit i got it working
-
-                if let Some(active_camera) = self.active_camera {
-                    if let Ok(mut q) =
-                        self.world
-                            .query_one::<(&Camera, &CameraComponent, Option<&CameraFollowTarget>)>(
-                                *active_camera,
-                            )
-                    {
-                        if let Some((camera, _, _)) = q.get() {
-                            self.gizmo.update_config(GizmoConfig {
-                                view_matrix: DMat4::look_at_lh(
-                                    DVec3::new(
-                                        camera.eye.x as f64,
-                                        camera.eye.y as f64,
-                                        camera.eye.z as f64,
-                                    ),
-                                    DVec3::new(
-                                        camera.target.x as f64,
-                                        camera.target.y as f64,
-                                        camera.target.z as f64,
-                                    ),
-                                    DVec3::new(
-                                        camera.up.x as f64,
-                                        camera.up.y as f64,
-                                        camera.up.z as f64,
-                                    ),
-                                )
-                                .into(),
-                                projection_matrix: DMat4::perspective_infinite_reverse_lh(
-                                    camera.fov_y as f64,
-                                    display_width as f64 / display_height as f64,
-                                    camera.znear as f64,
-                                )
-                                .into(),
-                                viewport: image_rect,
-                                modes: *self.gizmo_mode,
-                                orientation: transform_gizmo_egui::GizmoOrientation::Global,
-                                snapping,
-                                snap_distance: 1.0,
-                                ..Default::default()
-                            });
+                let active_cam = self.active_camera.lock();
+                if let Some(active_camera) = *active_cam {
+                    let camera_data = {
+                        let world = self.world.read();
+                        if let Ok(mut q) = world.query_one::<(&Camera, &CameraComponent, Option<&CameraFollowTarget>)>(active_camera) {
+                            let val = q.get();
+                            if let Some(val) = val {
+                                Some(val.0.clone())
+                            } else {
+                                log::warn!("Queried camera but unable to get value");
+                                None
+                            }
                         } else {
-                            log_once::warn_once!(
-                                "Unable to fetch the query result of camera: {:?}",
-                                active_camera
-                            )
+                            log::warn!("Unable to query camera");
+                            None
                         }
-                    } else {
-                        log_once::warn_once!(
-                            "Unable to query camera, component and option<camerafollowtarget> for active camera: {:?}",
-                            active_camera
-                        );
+                    };
+
+                    if let Some(camera) = camera_data {
+                        self.gizmo.update_config(GizmoConfig {
+                            view_matrix: camera.view_mat.into(),
+                            projection_matrix: camera.proj_mat.into(),
+                            viewport: image_rect,
+                            modes: *self.gizmo_mode,
+                            orientation: transform_gizmo_egui::GizmoOrientation::Global,
+                            snapping,
+                            snap_distance: 1.0,
+                            ..Default::default()
+                        });
                     }
-                } else {
-                    log_once::warn_once!("No active camera found");
                 }
-
                 if !matches!(self.viewport_mode, ViewportMode::None) {
                     if let Some(entity_id) = self.selected_entity {
-                        if let Ok(transform) =
-                            Arc::get_mut(&mut self.world).unwrap().query_one_mut::<&mut Transform>(*entity_id)
                         {
-                            let was_focused = cfg.is_focused;
-                            cfg.is_focused = self.gizmo.is_focused();
+                            if let Ok(transform) = self.world.write()
+                                .query_one_mut::<&mut Transform>(*entity_id)
+                            {
+                                let was_focused = cfg.is_focused;
+                                cfg.is_focused = self.gizmo.is_focused();
 
-                            if cfg.is_focused && !was_focused {
-                                cfg.old_pos = *transform;
-                            }
+                                if cfg.is_focused && !was_focused {
+                                    cfg.old_pos = *transform;
+                                }
 
-                            let gizmo_transform =
-                                transform_gizmo_egui::math::Transform::from_scale_rotation_translation(
-                                    transform.scale,
-                                    transform.rotation,
-                                    transform.position,
-                                );
+                                let gizmo_transform =
+                                    transform_gizmo_egui::math::Transform::from_scale_rotation_translation(
+                                        transform.scale,
+                                        transform.rotation,
+                                        transform.position,
+                                    );
 
-                            if let Some((_result, new_transforms)) =
-                                self.gizmo.interact(ui, &[gizmo_transform])
-                            {
-                                if let Some(new_transform) = new_transforms.first() {
-                                    transform.position = new_transform.translation.into();
-                                    transform.rotation = new_transform.rotation.into();
-                                    transform.scale = new_transform.scale.into();
+                                if let Some((_result, new_transforms)) =
+                                    self.gizmo.interact(ui, &[gizmo_transform])
+                                {
+                                    if let Some(new_transform) = new_transforms.first() {
+                                        transform.position = new_transform.translation.into();
+                                        transform.rotation = new_transform.rotation.into();
+                                        transform.scale = new_transform.scale.into();
+                                    }
                                 }
-                            }
 
-                            if was_focused && !cfg.is_focused {
-                                let transform_changed = cfg.old_pos.position != transform.position
-                                    || cfg.old_pos.rotation != transform.rotation
-                                    || cfg.old_pos.scale != transform.scale;
-
-                                if transform_changed {
-                                    UndoableAction::push_to_undo(
-                                        &mut self.undo_stack,
-                                        UndoableAction::Transform(
-                                            entity_id.clone(),
-                                            cfg.old_pos.clone(),
-                                        ),
-                                    );
-                                    log::debug!("Pushed transform action to stack");
+                                if was_focused && !cfg.is_focused {
+                                    let transform_changed = cfg.old_pos.position != transform.position
+                                        || cfg.old_pos.rotation != transform.rotation
+                                        || cfg.old_pos.scale != transform.scale;
+
+                                    if transform_changed {
+                                        UndoableAction::push_to_undo(
+                                            &mut self.undo_stack,
+                                            UndoableAction::Transform(
+                                                entity_id.clone(),
+                                                cfg.old_pos.clone(),
+                                            ),
+                                        );
+                                        log::debug!("Pushed transform action to stack");
+                                    }
                                 }
                             }
                         }
@@ -644,18 +622,21 @@ impl<'a> TabViewer for EditorTabViewer<'a> {
                                             if is_d_clicked {
                                                 if matches!(asset_type, ResourceType::Model) {
                                                     let mut spawn_position = DVec3::default();
-                                                    if let Some(active_camera) = self.active_camera {
-                                                        if let Ok(mut q) = self.world.query_one::<(&Camera, &CameraComponent, Option<&CameraFollowTarget>)>(*active_camera) {
-                                                            if let Some((camera, _, _)) = q.get() {
-                                                                spawn_position = camera.eye;
+                                                    {
+                                                        let active_cam = self.active_camera.lock();
+                                                        if let Some(active_camera) = *active_cam {
+                                                            if let Ok(mut q) = self.world.read().query_one::<(&Camera, &CameraComponent, Option<&CameraFollowTarget>)>(active_camera) {
+                                                                if let Some((camera, _, _)) = q.get() {
+                                                                    spawn_position = camera.eye;
+                                                                } else {
+                                                                    log_once::warn_once!("Unable to fetch the query result of camera: {:?}", active_camera)
+                                                                }
                                                             } else {
-                                                                log_once::warn_once!("Unable to fetch the query result of camera: {:?}", active_camera)
+                                                                log_once::warn_once!("Unable to query camera, component and option<camerafollowtarget> for active camera: {:?}", active_camera);
                                                             }
                                                         } else {
-                                                            log_once::warn_once!("Unable to query camera, component and option<camerafollowtarget> for active camera: {:?}", active_camera);
+                                                            log_once::warn_once!("No active camera found");
                                                         }
-                                                    } else {
-                                                        log_once::warn_once!("No active camera found");
                                                     }
 
                                                     let asset = DraggedAsset {
@@ -714,207 +695,216 @@ impl<'a> TabViewer for EditorTabViewer<'a> {
             }
             EditorTab::ResourceInspector => {
                 if let Some(entity) = self.selected_entity {
-                    if let Ok((
-                        e,
-                        transform,
-                        _props,
-                        script,
-                        camera,
-                        camera_component,
-                        follow_target,
-                    )) = Arc::get_mut(&mut self.world).unwrap().query_one_mut::<(
-                        &mut AdoptedEntity,
-                        Option<&mut Transform>,
-                        Option<&ModelProperties>,
-                        Option<&mut ScriptComponent>,
-                        Option<&mut Camera>,
-                        Option<&mut CameraComponent>,
-                        Option<&mut CameraFollowTarget>,
-                    )>(*entity)
                     {
-                        e.inspect(
-                            entity,
-                            &mut cfg,
-                            ui,
-                            self.undo_stack,
-                            self.signal,
-                            &mut String::new(),
-                        );
-                        if let Some(t) = transform {
-                            t.inspect(
-                                entity,
-                                &mut cfg,
-                                ui,
-                                self.undo_stack,
-                                self.signal,
-                                e.label_mut(),
-                            );
-                        }
-
-                        if let (Some(camera), Some(camera_component)) = (camera, camera_component) {
-                            ui.separator();
-                            ui.label("Camera Components:");
-                            camera.inspect(
-                                entity,
-                                &mut cfg,
-                                ui,
-                                self.undo_stack,
-                                self.signal,
-                                &mut String::new(),
-                            );
-                            camera_component.inspect(
-                                entity,
-                                &mut cfg,
-                                ui,
-                                self.undo_stack,
-                                self.signal,
-                                &mut camera.label.clone(),
-                            );
+                        let world = self.world.read();
+                        // Note: Use self.world.read() and query_one instead of self.world.write() and query_one_mut as
+                        // that causes a deadlock
+                            if let Ok(mut q) = world.query_one::<(
+                                &mut AdoptedEntity,
+                                Option<&mut Transform>,
+                                Option<&ModelProperties>,
+                                Option<&mut ScriptComponent>,
+                                Option<&mut Camera>,
+                                Option<&mut CameraComponent>,
+                                Option<&mut CameraFollowTarget>,
+                            )>(*entity)
+                            {
+                                if let Some((
+                                                e,
+                                                transform,
+                                                _props,
+                                                script,
+                                                camera,
+                                                camera_component,
+                                                follow_target,
+                                            )) = q.get() {
+                                    e.inspect(
+                                        entity,
+                                        &mut cfg,
+                                        ui,
+                                        self.undo_stack,
+                                        self.signal,
+                                        &mut String::new(),
+                                    );
+                                    if let Some(t) = transform {
+                                        t.inspect(
+                                            entity,
+                                            &mut cfg,
+                                            ui,
+                                            self.undo_stack,
+                                            self.signal,
+                                            e.label_mut(),
+                                        );
+                                    }
 
-                            if let Some(target) = follow_target {
-                                target.inspect(
-                                    entity,
-                                    &mut cfg,
-                                    ui,
-                                    self.undo_stack,
-                                    self.signal,
-                                    &mut camera.label.clone(),
-                                );
-                            }
-                        }
+                                    if let (Some(camera), Some(camera_component)) = (camera, camera_component) {
+                                        ui.separator();
+                                        ui.label("Camera Components:");
+                                        camera.inspect(
+                                            entity,
+                                            &mut cfg,
+                                            ui,
+                                            self.undo_stack,
+                                            self.signal,
+                                            &mut String::new(),
+                                        );
+                                        camera_component.inspect(
+                                            entity,
+                                            &mut cfg,
+                                            ui,
+                                            self.undo_stack,
+                                            self.signal,
+                                            &mut camera.label.clone(),
+                                        );
 
-                        // if let Some(props) = _props {
-                        //     props.inspect(entity, &mut cfg, ui, self.undo_stack, self.signal, e.label_mut());
-                        // }
-
-                        if let Some(script) = script {
-                            script.inspect(
-                                entity,
-                                &mut cfg,
-                                ui,
-                                self.undo_stack,
-                                self.signal,
-                                e.label_mut(),
-                            );
-                        }
+                                        if let Some(target) = follow_target {
+                                            target.inspect(
+                                                entity,
+                                                &mut cfg,
+                                                ui,
+                                                self.undo_stack,
+                                                self.signal,
+                                                &mut camera.label.clone(),
+                                            );
+                                        }
+                                    }
 
-                        if let Some(t) = cfg.label_last_edit {
-                            if t.elapsed() >= Duration::from_millis(500) {
-                                if let Some(ent) = cfg.old_label_entity.take() {
-                                    if let Some(orig) = cfg.label_original.take() {
-                                        UndoableAction::push_to_undo(
-                                            &mut self.undo_stack,
-                                            UndoableAction::Label(ent, orig, EntityType::Entity),
+                                    // if let Some(props) = _props {
+                                    //     props.inspect(entity, &mut cfg, ui, self.undo_stack, self.signal, e.label_mut());
+                                    // }
+
+                                    if let Some(script) = script {
+                                        script.inspect(
+                                            entity,
+                                            &mut cfg,
+                                            ui,
+                                            self.undo_stack,
+                                            self.signal,
+                                            e.label_mut(),
                                         );
-                                        log::debug!(
+                                    }
+
+                                    if let Some(t) = cfg.label_last_edit {
+                                        if t.elapsed() >= Duration::from_millis(500) {
+                                            if let Some(ent) = cfg.old_label_entity.take() {
+                                                if let Some(orig) = cfg.label_original.take() {
+                                                    UndoableAction::push_to_undo(
+                                                        &mut self.undo_stack,
+                                                        UndoableAction::Label(ent, orig, EntityType::Entity),
+                                                    );
+                                                    log::debug!(
                                             "Pushed label change to undo stack after 500ms debounce period"
                                         );
+                                                }
+                                            }
+                                            cfg.label_last_edit = None;
+                                        }
                                     }
                                 }
-                                cfg.label_last_edit = None;
+                            } else {
+                                log_once::debug_once!("Unable to query entity inside resource inspector");
                             }
-                        }
-                    } else {
-                        log_once::debug_once!("Unable to query entity inside resource inspector");
-                    }
 
-                    if let Ok((light, transform, props)) =
-                        Arc::get_mut(&mut self.world).unwrap()
-                            .query_one_mut::<(&mut Light, &mut Transform, &mut LightComponent)>(
-                                *entity,
-                            )
-                    {
-                        light.inspect(
-                            entity,
-                            &mut cfg,
-                            ui,
-                            self.undo_stack,
-                            self.signal,
-                            &mut String::new(),
-                        );
-                        transform.inspect(
-                            entity,
-                            &mut cfg,
-                            ui,
-                            self.undo_stack,
-                            self.signal,
-                            &mut light.label,
-                        );
-                        props.inspect(
-                            entity,
-                            &mut cfg,
-                            ui,
-                            self.undo_stack,
-                            self.signal,
-                            &mut light.label,
-                        );
-                        if let Some(t) = cfg.label_last_edit {
-                            if t.elapsed() >= Duration::from_millis(500) {
-                                if let Some(ent) = cfg.old_label_entity.take() {
-                                    if let Some(orig) = cfg.label_original.take() {
-                                        UndoableAction::push_to_undo(
-                                            &mut self.undo_stack,
-                                            UndoableAction::Label(ent, orig, EntityType::Light),
-                                        );
-                                        log::debug!(
+                            if let Ok(mut q) = world
+                                .query_one::<(&mut Light, &mut Transform, &mut LightComponent)>(*entity)
+                            {
+                                if let Some((light, transform, props)) = q.get() {
+                                    light.inspect(
+                                        entity,
+                                        &mut cfg,
+                                        ui,
+                                        self.undo_stack,
+                                        self.signal,
+                                        &mut String::new(),
+                                    );
+                                    transform.inspect(
+                                        entity,
+                                        &mut cfg,
+                                        ui,
+                                        self.undo_stack,
+                                        self.signal,
+                                        &mut light.label,
+                                    );
+                                    props.inspect(
+                                        entity,
+                                        &mut cfg,
+                                        ui,
+                                        self.undo_stack,
+                                        self.signal,
+                                        &mut light.label,
+                                    );
+                                    if let Some(t) = cfg.label_last_edit {
+                                        if t.elapsed() >= Duration::from_millis(500) {
+                                            if let Some(ent) = cfg.old_label_entity.take() {
+                                                if let Some(orig) = cfg.label_original.take() {
+                                                    UndoableAction::push_to_undo(
+                                                        &mut self.undo_stack,
+                                                        UndoableAction::Label(ent, orig, EntityType::Light),
+                                                    );
+                                                    log::debug!(
                                             "Pushed label change to undo stack after 500ms debounce period"
                                         );
+                                                }
+                                            }
+                                            cfg.label_last_edit = None;
+                                        }
                                     }
                                 }
-                                cfg.label_last_edit = None;
+                            } else {
+                                log_once::debug_once!("Unable to query light inside resource inspector");
                             }
-                        }
-                    } else {
-                        log_once::debug_once!("Unable to query light inside resource inspector");
-                    }
 
-                    if let Ok((camera, camera_component, follow_target)) =
-                        Arc::get_mut(&mut self.world).unwrap().query_one_mut::<(
-                            &mut Camera,
-                            &mut CameraComponent,
-                            Option<&mut CameraFollowTarget>,
-                        )>(*entity)
-                    {
-                        camera.inspect(
-                            entity,
-                            &mut cfg,
-                            ui,
-                            self.undo_stack,
-                            self.signal,
-                            &mut String::new(),
-                        );
-                        camera_component.inspect(
-                            entity,
-                            &mut cfg,
-                            ui,
-                            self.undo_stack,
-                            self.signal,
-                            &mut camera.label.clone(),
-                        );
-                        if let Some(target) = follow_target {
-                            target.inspect(
-                                entity,
-                                &mut cfg,
-                                ui,
-                                self.undo_stack,
-                                self.signal,
-                                &mut camera.label.clone(),
-                            );
-                        }
+                            if let Ok(mut q) =
+                                world.query_one::<(
+                                    &mut Camera,
+                                    &mut CameraComponent,
+                                    Option<&mut CameraFollowTarget>,
+                                )>(*entity)
+                            {
+                                if let Some((camera, camera_component, follow_target)) = q.get() {
+                                    camera.inspect(
+                                        entity,
+                                        &mut cfg,
+                                        ui,
+                                        self.undo_stack,
+                                        self.signal,
+                                        &mut String::new(),
+                                    );
+                                    camera_component.inspect(
+                                        entity,
+                                        &mut cfg,
+                                        ui,
+                                        self.undo_stack,
+                                        self.signal,
+                                        &mut camera.label.clone(),
+                                    );
+                                    if let Some(target) = follow_target {
+                                        target.inspect(
+                                            entity,
+                                            &mut cfg,
+                                            ui,
+                                            self.undo_stack,
+                                            self.signal,
+                                            &mut camera.label.clone(),
+                                        );
+                                    }
 
-                        ui.separator();
-                        ui.label("Camera Controls:");
-                        if ui.button("Set as Active Camera").clicked() {
-                            *self.active_camera = Some(*entity);
-                            log::info!("Set camera '{}' as active", camera.label);
-                        }
+                                    ui.separator();
+                                    ui.label("Camera Controls:");
+                                    let mut active_camera = self.active_camera.lock();
+                                    if ui.button("Set as Active Camera").clicked() {
+                                        *active_camera = Some(*entity).into();
+                                        log::info!("Set camera '{}' as active", camera.label);
+                                    }
 
-                        if matches!(self.editor_mode, EditorState::Editing) {
-                            if ui.button("Switch to This Camera").clicked() {
-                                *self.active_camera = Some(*entity);
-                                log::info!("Switched to camera '{}'", camera.label);
+                                    if matches!(self.editor_mode, EditorState::Editing) {
+                                        if ui.button("Switch to This Camera").clicked() {
+                                            *active_camera = Some(*entity).into();
+                                            log::info!("Switched to camera '{}'", camera.label);
+                                        }
+                                    }
+                                }
                             }
-                        }
                     }
                 } else {
                     ui.label("No entity selected, therefore no info to provide. Go on, what are you waiting for? Click an entity!");
@@ -1027,16 +1017,23 @@ impl<'a> TabViewer for EditorTabViewer<'a> {
                         EditorTabMenuAction::AddComponent => {
                             log::debug!("Add Component clicked");
                             if let Some(entity) = self.selected_entity {
-                                if let Ok(..) = Arc::get_mut(&mut self.world).unwrap().query_one_mut::<&AdoptedEntity>(*entity)
                                 {
-                                    log::debug!("Queried selected entity, it is an entity");
-                                    *self.signal =
-                                        Signal::AddComponent(*entity, EntityType::Entity);
+                                    if let Ok(..) = self.world.write()
+                                        .query_one_mut::<&AdoptedEntity>(*entity)
+                                    {
+                                        log::debug!("Queried selected entity, it is an entity");
+                                        *self.signal =
+                                            Signal::AddComponent(*entity, EntityType::Entity);
+                                    }
                                 }
 
-                                if let Ok(..) = Arc::get_mut(&mut self.world).unwrap().query_one_mut::<&Light>(*entity) {
-                                    log::debug!("Queried selected entity, it is a light");
-                                    *self.signal = Signal::AddComponent(*entity, EntityType::Light);
+                                {
+                                    if let Ok(..) = self.world.write()
+                                        .query_one_mut::<&Light>(*entity)
+                                    {
+                                        log::debug!("Queried selected entity, it is a light");
+                                        *self.signal = Signal::AddComponent(*entity, EntityType::Light);
+                                    }
                                 }
                             } else {
                                 warn!(
@@ -1057,8 +1054,8 @@ impl<'a> TabViewer for EditorTabViewer<'a> {
                         EditorTabMenuAction::RemoveComponent => {
                             log::debug!("Remove Component clicked");
                             if let Some(entity) = self.selected_entity {
-                                if let Ok(script) =
-                                    Arc::get_mut(&mut self.world).unwrap().query_one_mut::<&ScriptComponent>(*entity)
+                                if let Ok(script) = self.world.write()
+                                    .query_one_mut::<&ScriptComponent>(*entity)
                                 {
                                     log::debug!(
                                         "Queried selected entity, it has a script component"
diff --git a/eucalyptus-editor/src/editor/input.rs b/eucalyptus-editor/src/editor/input.rs
index 4d285fd..857f33c 100644
--- a/eucalyptus-editor/src/editor/input.rs
+++ b/eucalyptus-editor/src/editor/input.rs
@@ -114,8 +114,8 @@ impl Keyboard for Editor {
             KeyCode::KeyC => {
                 if ctrl_pressed && !is_playing {
                     if let Some(entity) = &self.selected_entity {
-                        let query = self
-                            .world
+                        let world = self.world.read();
+                        let query = world
                             .query_one::<(&AdoptedEntity, &Transform, &ModelProperties)>(*entity);
                         if let Ok(mut q) = query {
                             if let Some((e, t, props)) = q.get() {
@@ -240,14 +240,20 @@ impl Mouse for Editor {
     // this impl doesn't have the mouse being recentered back to the center (to be fixed), this works as a usable alternative
     fn mouse_move(&mut self, position: PhysicalPosition<f64>) {
         if (self.is_viewport_focused && matches!(self.viewport_mode, ViewportMode::CameraMove))
-            || (matches!(self.editor_state, EditorState::Playing) && !self.input_state.is_cursor_locked)
+            || (matches!(self.editor_state, EditorState::Playing)
+                && !self.input_state.is_cursor_locked)
         {
             if let Some(last_pos) = self.input_state.last_mouse_pos {
                 let dx = position.x - last_pos.0;
                 let dy = position.y - last_pos.1;
-                
-                if let Some(active_camera) = self.active_camera {
-                    if let Ok(mut q) = self.world.query_one::<(&mut Camera, &CameraComponent, Option<&CameraFollowTarget>)>(active_camera) {
+
+                if let Some(active_camera) = *self.active_camera.lock() {
+                    if let Ok(mut q) = self.world.read().query_one::<(
+                        &mut Camera,
+                        &CameraComponent,
+                        Option<&CameraFollowTarget>,
+                    )>(active_camera)
+                    {
                         if let Some((camera, _, _)) = q.get() {
                             camera.track_mouse_delta(dx, dy);
                         }
@@ -256,7 +262,7 @@ impl Mouse for Editor {
             }
             self.input_state.last_mouse_pos = Some((position.x, position.y));
         }
-        
+
         self.input_state.mouse_pos = (position.x, position.y);
     }
 
@@ -264,33 +270,41 @@ impl Mouse for Editor {
     // for some reason, this doesn't work on linux but works on windows (not tested on anywhere else)
     fn mouse_move(&mut self, position: PhysicalPosition<f64>) {
         if (self.is_viewport_focused && matches!(self.viewport_mode, ViewportMode::CameraMove))
-            || (matches!(self.editor_state, EditorState::Playing) && !self.input_state.is_cursor_locked)
+            || (matches!(self.editor_state, EditorState::Playing)
+                && !self.input_state.is_cursor_locked)
         {
             if let Some(window) = &self.window {
                 let size = window.inner_size();
-                let center = PhysicalPosition::new(size.width as f64 / 2.0, size.height as f64 / 2.0);
-                
-                let distance_from_center = ((position.x - center.x).powi(2) + (position.y - center.y).powi(2)).sqrt();
-                
+                let center =
+                    PhysicalPosition::new(size.width as f64 / 2.0, size.height as f64 / 2.0);
+
+                let distance_from_center =
+                    ((position.x - center.x).powi(2) + (position.y - center.y).powi(2)).sqrt();
+
                 if distance_from_center > 5.0 {
                     let dx = position.x - center.x;
                     let dy = position.y - center.y;
-                    
+
                     if let Some(active_camera) = self.active_camera {
-                        if let Ok(mut q) = self.world.query_one::<(&mut Camera, &CameraComponent, Option<&CameraFollowTarget>)>(active_camera) {
+                        if let Ok(mut q) = self.world.query_one::<(
+                            &mut Camera,
+                            &CameraComponent,
+                            Option<&CameraFollowTarget>,
+                        )>(active_camera)
+                        {
                             if let Some((camera, _, _)) = q.get() {
                                 camera.track_mouse_delta(dx, dy);
                             }
                         }
                     }
-                    
+
                     let _ = window.set_cursor_position(center);
                 }
-                
+
                 window.set_cursor_visible(false);
             }
         }
-        
+
         self.input_state.mouse_pos = (position.x, position.y);
     }
 
diff --git a/eucalyptus-editor/src/editor/mod.rs b/eucalyptus-editor/src/editor/mod.rs
index 5cc8100..1fc3842 100644
--- a/eucalyptus-editor/src/editor/mod.rs
+++ b/eucalyptus-editor/src/editor/mod.rs
@@ -12,9 +12,9 @@ use std::{
     time::{Duration, Instant},
 };
 
-use crate::{build::build, debug::DependencyInstaller};
 use crate::camera::UndoableCameraAction;
 use crate::debug;
+use crate::{build::build, debug::DependencyInstaller};
 use dropbear_engine::{
     camera::Camera,
     entity::{AdoptedEntity, Transform},
@@ -26,7 +26,7 @@ use egui::{self, Context};
 use egui_dock_fork::{DockArea, DockState, NodeIndex, Style};
 use eucalyptus_core::{camera::{
     CameraAction, CameraComponent, CameraFollowTarget, CameraType, DebugCamera,
-}};
+}, states::WorldLoadingStatus};
 use eucalyptus_core::input::InputState;
 use eucalyptus_core::scripting::{ScriptAction, ScriptManager};
 use eucalyptus_core::states::{
@@ -37,22 +37,24 @@ use eucalyptus_core::utils::ViewportMode;
 use eucalyptus_core::{fatal, info, states, success, warn};
 use hecs::World;
 use log;
-use parking_lot::Mutex;
+use parking_lot::{Mutex, RwLock};
+use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
 use transform_gizmo_egui::{EnumSet, Gizmo, GizmoMode};
 use wgpu::{Color, Extent3d, RenderPipeline};
 use winit::{keyboard::KeyCode, window::Window};
+use dropbear_engine::graphics::{RenderContext, Shader};
 
 pub struct Editor {
     scene_command: SceneCommand,
-    world: Arc<World>,
-    dock_state: DockState<EditorTab>,
+    world: Arc<RwLock<World>>,
+    dock_state: Arc<Mutex<DockState<EditorTab>>>,
     texture_id: Option<egui::TextureId>,
     size: Extent3d,
     render_pipeline: Option<RenderPipeline>,
     light_manager: LightManager,
     color: Color,
 
-    active_camera: Option<hecs::Entity>,
+    active_camera: Arc<Mutex<Option<hecs::Entity>>>,
 
     is_viewport_focused: bool,
     // is_cursor_locked: bool,
@@ -60,7 +62,7 @@ pub struct Editor {
 
     show_new_project: bool,
     project_name: String,
-    project_path: Option<PathBuf>,
+    project_path: Arc<Mutex<Option<PathBuf>>>,
     pending_scene_switch: bool,
 
     gizmo: Gizmo,
@@ -77,10 +79,21 @@ pub struct Editor {
     script_manager: ScriptManager,
     play_mode_backup: Option<PlayModeBackup>,
 
+    /// State of the input
     input_state: InputState,
 
     // channels
+    /// A channel for installing dependencies.
     dep_installer: DependencyInstaller,
+    /// A threadsafe Unbounded Receiver, typically used for checking the status of the world loading
+    progress_tx: Option<UnboundedReceiver<WorldLoadingStatus>>,
+    /// Unused: A threadsafe Unbounded Sender
+    _progress_rx: Option<UnboundedSender<WorldLoadingStatus>>,
+    /// Used to check if the world has been loaded in
+    is_world_loaded: IsWorldLoadedYet,
+    /// Used to fetch the current status of the loading, so it can be used for different
+    /// egui loading windows or splash screens and such.
+    current_state: WorldLoadingStatus,
 }
 
 impl Editor {
@@ -96,7 +109,7 @@ impl Editor {
         let [_old, _] = surface.split_below(right, 0.5, vec![EditorTab::AssetViewer]);
 
         // this shit doesnt work :(
-        // nvm it works (sorta)
+        // nvm it works
         std::thread::spawn(move || {
             loop {
                 std::thread::sleep(Duration::from_secs(1));
@@ -112,13 +125,16 @@ impl Editor {
                         log::error!("{:#?}", t.backtrace());
                     }
                 }
-                panic!("Fatal: {} deadlocks detected, unable to continue on normal process", deadlocks.len());
+                panic!(
+                    "Fatal: {} deadlocks detected, unable to continue on normal process",
+                    deadlocks.len()
+                );
             }
         });
 
         Self {
             scene_command: SceneCommand::None,
-            dock_state,
+            dock_state: Arc::new(Mutex::new(dock_state)),
             texture_id: None,
             size: Extent3d::default(),
             render_pipeline: None,
@@ -126,10 +142,10 @@ impl Editor {
             is_viewport_focused: false,
             // is_cursor_locked: false,
             window: None,
-            world: Arc::new(World::new()),
+            world: Arc::new(RwLock::new(World::new())),
             show_new_project: false,
             project_name: String::new(),
-            project_path: None,
+            project_path: Arc::new(Mutex::new(None)),
             pending_scene_switch: false,
             gizmo: Gizmo::default(),
             selected_entity: None,
@@ -142,10 +158,12 @@ impl Editor {
             play_mode_backup: None,
             input_state: InputState::new(),
             light_manager: LightManager::new(),
-            active_camera: None,
-            dep_installer: DependencyInstaller::default()
-            // ..Default::default()
-            // note to self: DO NOT USE ..DEFAULT::DEFAULT(), IT WILL CAUSE OVERFLOW
+            active_camera: Arc::new(Mutex::new(None)),
+            dep_installer: DependencyInstaller::default(),
+            _progress_rx: None,
+            progress_tx: None,
+            is_world_loaded: IsWorldLoadedYet::new(),
+            current_state: WorldLoadingStatus::Idle,
         }
     }
 
@@ -181,7 +199,7 @@ impl Editor {
         scene.cameras.clear();
 
         for (id, (adopted, transform, properties, script)) in self
-            .world
+            .world.read()
             .query::<(
                 &AdoptedEntity,
                 Option<&Transform>,
@@ -206,7 +224,7 @@ impl Editor {
         }
 
         for (id, (light_component, transform, light)) in self
-            .world
+            .world.read()
             .query::<(
                 &dropbear_engine::lighting::LightComponent,
                 &Transform,
@@ -227,7 +245,7 @@ impl Editor {
         }
 
         for (_id, (camera, component, follow_target)) in self
-            .world
+            .world.read()
             .query::<(&Camera, &CameraComponent, Option<&CameraFollowTarget>)>()
             .iter()
         {
@@ -250,7 +268,8 @@ impl Editor {
 
         {
             let mut config = PROJECT.write();
-            config.dock_layout = Some(self.dock_state.clone());
+            let dock_state = self.dock_state.lock();
+            config.dock_layout = Some(dock_state.clone());
         }
 
         {
@@ -269,14 +288,92 @@ impl Editor {
         Ok(())
     }
 
-    pub async fn load_project_config(&mut self, graphics: Arc<SharedGraphicsContext>) -> anyhow::Result<()> {
+    /// The window when loading a project or a scene or anything that uses [`WorldLoadingStatus`]
+    fn show_project_loading_window(&mut self, ctx: &egui::Context) {
+        if let Some(ref mut rx) = self.progress_tx {
+            match rx.try_recv() {
+                Ok(status) => {
+                    match status {
+                        WorldLoadingStatus::LoadingEntity { index, name, total } => {
+                            log::debug!("Loading entity: {} ({}/{})", name, index + 1, total);
+                            self.current_state = WorldLoadingStatus::LoadingEntity { index, name, total };
+                        }
+                        WorldLoadingStatus::LoadingLight { index, name, total } => {
+                            log::debug!("Loading light: {} ({}/{})", name, index + 1, total);
+                            self.current_state = WorldLoadingStatus::LoadingLight { index, name, total };
+                        }
+                        WorldLoadingStatus::LoadingCamera { index, name, total } => {
+                            log::debug!("Loading camera: {} ({}/{})", name, index + 1, total);
+                            self.current_state = WorldLoadingStatus::LoadingCamera { index, name, total };
+                        }
+                        WorldLoadingStatus::Completed => {
+                            log::debug!("Received WorldLoadingStatus::Completed - project loading finished");
+                            self.is_world_loaded.mark_project_loaded();
+                            self.current_state = WorldLoadingStatus::Completed;
+                            self.progress_tx = None;
+                            println!("Returning back");
+                            return;
+                        }
+                        WorldLoadingStatus::Idle => {
+                            log::debug!("Project loading is idle");
+                        }
+                    }
+                }
+                Err(_) => {
+                    // log::debug!("Unable to receive the progress: {}", e);
+                }
+            }
+        } else {
+            log::debug!("No progress receiver available");
+        }
+
+        egui::Window::new("Loading Project")
+            .collapsible(false)
+            .resizable(false)
+            .anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0])
+            .fixed_size([300.0, 100.0])
+            .show(ctx, |ui| {
+                ui.vertical_centered(|ui| {
+                    ui.add_space(10.0);
+                    ui.horizontal(|ui| {
+                        ui.spinner();
+                        ui.label("Loading...");
+                    });
+                    // ui.add_space(5.0);
+                    // ui.add(egui::ProgressBar::new(progress).text(format!("{:.0}%", progress * 100.0)));
+                    match &self.current_state {
+                        WorldLoadingStatus::Idle => {ui.label("Initialising...");}
+                        WorldLoadingStatus::LoadingEntity { name, ..} => {ui.label(format!("Loading entity: {}", name));}
+                        WorldLoadingStatus::LoadingLight { name, .. } => {ui.label(format!("Loading light: {}", name));}
+                        WorldLoadingStatus::LoadingCamera { name, .. } => {ui.label(format!("Loading camera: {}", name));}
+                        WorldLoadingStatus::Completed => {ui.label("Done!");}
+                    }
+                });
+            });
+    }
+
+    /// Loads the project config.
+    ///
+    /// It uses an unbounded sender to send messages back to the receiver so it can
+    /// be used within threads.
+    pub async fn load_project_config(
+        // &mut self,
+        graphics: Arc<SharedGraphicsContext>,
+        sender: Option<UnboundedSender<WorldLoadingStatus>>,
+        world: Arc<RwLock<World>>,
+        active_camera: Arc<Mutex<Option<hecs::Entity>>>,
+        project_path: Arc<Mutex<Option<PathBuf>>>,
+        dock_state: Arc<Mutex<DockState<EditorTab>>>,
+    ) -> anyhow::Result<()> {
         {
             let config = PROJECT.read();
-
-            self.project_path = Some(config.project_path.clone());
+            let mut path = project_path.lock();
+            *path = Some(config.project_path.clone());
 
             if let Some(layout) = &config.dock_layout {
-                self.dock_state = layout.clone();
+                let mut dock = dock_state.lock();
+                let layout = layout.clone();
+                *dock = layout.clone();
             }
         }
 
@@ -287,8 +384,11 @@ impl Editor {
 
         {
             if let Some(first_scene) = first_scene_opt {
-                let cam = first_scene.load_into_world(Arc::get_mut(&mut self.world).unwrap(), graphics).await?;
-                self.active_camera = Some(cam);
+                let cam = first_scene
+                    .load_into_world(world, graphics, sender.clone())
+                    .await?;
+                let mut a_c = active_camera.lock();
+                *a_c = Some(cam).into();
 
                 log::info!(
                     "Successfully loaded scene with {} entities and {} camera configs",
@@ -296,8 +396,7 @@ impl Editor {
                     first_scene.cameras.len(),
                 );
             } else {
-                let existing_debug_camera = self
-                    .world
+                let existing_debug_camera = world.read()
                     .query::<(&Camera, &CameraComponent)>()
                     .iter()
                     .find_map(|(entity, (_, component))| {
@@ -310,23 +409,31 @@ impl Editor {
 
                 if let Some(camera_entity) = existing_debug_camera {
                     log::info!("Using existing debug camera");
-                    self.active_camera = Some(camera_entity);
+                    let mut a_c = active_camera.lock();
+                    *a_c = Some(camera_entity).into();
                 } else {
                     log::info!("No scenes found, creating default debug camera");
 
                     let debug_camera = Camera::predetermined(graphics, Some("Debug Camera"));
                     let component = DebugCamera::new();
 
-                    let e = Arc::get_mut(&mut self.world).unwrap().spawn((debug_camera, component));
-                    self.active_camera = Some(e);
+                    {
+                        let e = world.write()
+                            .spawn((debug_camera, component));
+                        let mut a_c = active_camera.lock();
+                        *a_c = Some(e).into();
+                    }
                 }
             }
         }
 
+        if let Some(ref s) = sender.clone() {
+            let _ = s.send(WorldLoadingStatus::Completed);
+        }
         Ok(())
     }
 
-    pub fn show_ui(&mut self, ctx: &Context) {
+    pub async fn show_ui(&mut self, ctx: &Context) {
         egui::TopBottomPanel::top("menu_bar").show(ctx, |ui| {
             egui::MenuBar::new().ui(ui, |ui| {
                 ui.menu_button("File", |ui| {
@@ -388,7 +495,8 @@ impl Editor {
                 ui.menu_button("Edit", |ui| {
                     if ui.button("Copy").clicked() {
                         if let Some(entity) = &self.selected_entity {
-                            let query = self.world.query_one::<(&AdoptedEntity, &Transform, &ModelProperties)>(*entity);
+                            let world = self.world.read();
+                            let query = world.query_one::<(&AdoptedEntity, &Transform, &ModelProperties)>(*entity);
                             if let Ok(mut q) = query {
                                 if let Some((e, t, props)) = q.get() {
                                     let s_entity = states::SceneEntity {
@@ -411,6 +519,7 @@ impl Editor {
                         } else {
                             warn!("Unable to copy entity: None selected");
                         }
+                        
                     }
 
                     if ui.button("Paste").clicked() {
@@ -431,19 +540,20 @@ impl Editor {
                 });
 
                 ui.menu_button("Window", |ui_window| {
+                    let mut dock_state = self.dock_state.lock();
                     if ui_window.button("Open Asset Viewer").clicked() {
-                        self.dock_state.push_to_focused_leaf(EditorTab::AssetViewer);
+                        dock_state.push_to_focused_leaf(EditorTab::AssetViewer);
                     }
                     if ui_window.button("Open Resource Inspector").clicked() {
-                        self.dock_state
+                        dock_state
                             .push_to_focused_leaf(EditorTab::ResourceInspector);
                     }
                     if ui_window.button("Open Entity List").clicked() {
-                        self.dock_state
+                        dock_state
                             .push_to_focused_leaf(EditorTab::ModelEntityList);
                     }
                     if ui_window.button("Open Viewport").clicked() {
-                        self.dock_state.push_to_focused_leaf(EditorTab::Viewport);
+                        dock_state.push_to_focused_leaf(EditorTab::Viewport);
                     }
                 });
                 {
@@ -456,16 +566,18 @@ impl Editor {
         });
 
         egui::CentralPanel::default().show(&ctx, |ui| {
-            DockArea::new(&mut self.dock_state)
+            let mut dock_state = self.dock_state.lock();
+            
+            DockArea::new(&mut dock_state)
                 .style(Style::from_egui(ui.style().as_ref()))
                 .show_inside(
                     ui,
                     &mut EditorTabViewer {
                         view: self.texture_id.unwrap(),
-                        nodes: EntityNode::from_world(&self.world),
+                        nodes: EntityNode::from_world(&self.world.clone().read()),
                         gizmo: &mut self.gizmo,
                         tex_size: self.size,
-                        world: &mut self.world,
+                        world: self.world.clone(),
                         selected_entity: &mut self.selected_entity,
                         viewport_mode: &mut self.viewport_mode,
                         undo_stack: &mut self.undo_stack,
@@ -477,11 +589,12 @@ impl Editor {
                 );
         });
 
+        let mut project_path = self.project_path.lock();
         crate::utils::show_new_project_window(
             ctx,
             &mut self.show_new_project,
             &mut self.project_name,
-            &mut self.project_path,
+            &mut project_path,
             |name, path| {
                 crate::utils::start_project_creation(name.to_string(), Some(path.clone()));
                 self.pending_scene_switch = true;
@@ -494,9 +607,139 @@ impl Editor {
         }
     }
 
+    /// Restores transform components back to its original state before PlayMode.
+    pub fn restore(&mut self) -> anyhow::Result<()> {
+        if let Some(backup) = &self.play_mode_backup {
+            for (entity_id, original_transform, original_properties, original_script) in
+                &backup.entities
+            {
+                if let Ok(mut transform) = self.world.read().get::<&mut Transform>(*entity_id) {
+                    *transform = *original_transform;
+                }
+
+                if let Ok(mut properties) = self.world.read().get::<&mut ModelProperties>(*entity_id) {
+                    *properties = original_properties.clone();
+                }
+
+                let has_script = self.world.read().get::<&ScriptComponent>(*entity_id).is_ok();
+                match (has_script, original_script) {
+                    (true, Some(original)) => {
+                        if let Ok(mut script) = self.world.read().get::<&mut ScriptComponent>(*entity_id)
+                        {
+                            *script = original.clone();
+                        }
+                    }
+                    (true, None) => {
+                        {
+                            let _ = self.world.write()
+                                .remove_one::<ScriptComponent>(*entity_id);
+                        }
+                    }
+                    (false, Some(original)) => {
+                        {
+                            let _ = self.world.write()
+                                .insert_one(*entity_id, original.clone());
+                        }
+                    }
+                    (false, None) => {
+                    }
+                }
+            }
+
+            for (entity_id, original_camera, original_component, original_follow_target) in
+                &backup.camera_data
+            {
+                if let Ok(mut camera) = self.world.read().get::<&mut Camera>(*entity_id) {
+                    *camera = original_camera.clone();
+                }
+
+                if let Ok(mut component) = self.world.read().get::<&mut CameraComponent>(*entity_id) {
+                    *component = original_component.clone();
+                }
+
+                let has_follow_target = self.world.read().get::<&CameraFollowTarget>(*entity_id).is_ok();
+                match (has_follow_target, original_follow_target) {
+                    (true, Some(original)) => {
+                        if let Ok(mut follow_target) =
+                            self.world.read().get::<&mut CameraFollowTarget>(*entity_id)
+                        {
+                            *follow_target = original.clone();
+                        }
+                    }
+                    (true, None) => {
+                        {
+                            let _ = self.world.write()
+                                .remove_one::<CameraFollowTarget>(*entity_id);
+                        }
+                    }
+                    (false, Some(original)) => {
+                        {
+                            let _ = self.world.write()
+                                .insert_one(*entity_id, original.clone());
+                        }
+                    }
+                    (false, None) => {
+                        // No change needed
+                    }
+                }
+            }
+
+            log::info!("Restored scene from play mode backup");
+
+            self.play_mode_backup = None;
+            Ok(())
+        } else {
+            Err(anyhow::anyhow!("No play mode backup found to restore"))
+        }
+    }
+
+    pub fn create_backup(&mut self) -> anyhow::Result<()> {
+        let mut entities = Vec::new();
+
+        for (entity_id, (_, transform, properties)) in self
+            .world.read()
+            .query::<(&AdoptedEntity, &Transform, &ModelProperties)>()
+            .iter()
+        {
+            let script = self
+                .world.read()
+                .query_one::<&ScriptComponent>(entity_id)
+                .ok()
+                .and_then(|mut s| s.get().map(|script| script.clone()));
+            entities.push((entity_id, *transform, properties.clone(), script));
+        }
+
+        let mut camera_data = Vec::new();
+
+        for (entity_id, (camera, component, follow_target)) in self
+            .world.read()
+            .query::<(&Camera, &CameraComponent, Option<&CameraFollowTarget>)>()
+            .iter()
+        {
+            camera_data.push((
+                entity_id,
+                camera.clone(),
+                component.clone(),
+                follow_target.cloned(),
+            ));
+        }
+
+        self.play_mode_backup = Some(PlayModeBackup {
+            entities,
+            camera_data,
+        });
+
+        log::info!(
+            "Created play mode backup with {} entities and {} cameras",
+            self.play_mode_backup.as_ref().unwrap().entities.len(),
+            self.play_mode_backup.as_ref().unwrap().camera_data.len()
+        );
+        Ok(())
+    }
+
     pub fn switch_to_debug_camera(&mut self) {
         let debug_camera = self
-            .world
+            .world.read()
             .query::<(&Camera, &CameraComponent)>()
             .iter()
             .find_map(|(e, (_cam, comp))| {
@@ -508,7 +751,8 @@ impl Editor {
             });
 
         if let Some(camera_entity) = debug_camera {
-            self.active_camera = Some(camera_entity);
+            let mut active_camera = self.active_camera.lock();
+            *active_camera = Some(camera_entity);
             info!("Switched to debug camera");
         } else {
             warn!("No debug camera found in the world");
@@ -517,7 +761,7 @@ impl Editor {
 
     pub fn switch_to_player_camera(&mut self) {
         let player_camera = self
-            .world
+            .world.read()
             .query::<(&Camera, &CameraComponent)>()
             .iter()
             .find_map(|(e, (_cam, comp))| {
@@ -529,7 +773,8 @@ impl Editor {
             });
 
         if let Some(camera_entity) = player_camera {
-            self.active_camera = Some(camera_entity);
+            let mut active_camera = self.active_camera.lock();
+            *active_camera = Some(camera_entity);
             info!("Switched to player camera");
         } else {
             warn!("No player camera found in the world");
@@ -537,9 +782,10 @@ impl Editor {
     }
 
     pub fn is_using_debug_camera(&self) -> bool {
-        if let Some(active_camera_entity) = self.active_camera {
+        let active_camera = self.active_camera.lock();
+        if let Some(active_camera_entity) = *active_camera {
             if let Ok(mut query) = self
-                .world
+                .world.read()
                 .query_one::<&CameraComponent>(active_camera_entity)
             {
                 if let Some(component) = query.get() {
@@ -549,6 +795,63 @@ impl Editor {
         }
         false
     }
+
+    /// Loads all the wgpu resources such as renderer.
+    ///
+    /// **Note**: To be ran AFTER [`Editor::load_project_config`]
+    pub fn load_wgpu_nerdy_stuff<'a>(&mut self, graphics: &mut RenderContext<'a>) {
+        let shader = Shader::new(
+            graphics.shared.clone(),
+            include_str!("../../../resources/shaders/shader.wgsl"),
+            Some("viewport_shader"),
+        );
+
+        self.light_manager.create_light_array_resources(graphics.shared.clone());
+
+        if let Some(active_camera) = *self.active_camera.lock() {
+            if let Ok(mut q) = self
+                .world.read()
+                .query_one::<(&Camera, &CameraComponent, Option<&CameraFollowTarget>)>(
+                    active_camera,
+                )
+            {
+                if let Some((camera, _component, _follow_target)) = q.get() {
+                    let pipeline = graphics.create_render_pipline(
+                        &shader,
+                        vec![
+                            &graphics.shared.texture_bind_layout.clone(),
+                            camera.layout(),
+                            self.light_manager.layout(),
+                        ],
+                        None,
+                    );
+                    self.render_pipeline = Some(pipeline);
+
+                    self.light_manager.create_render_pipeline(
+                        graphics.shared.clone(),
+                        include_str!("../../../resources/shaders/light.wgsl"),
+                        camera,
+                        Some("Light Pipeline"),
+                    );
+                } else {
+                    log_once::warn_once!(
+                        "Unable to fetch the query result of camera: {:?}",
+                        active_camera
+                    )
+                }
+            } else {
+                log_once::warn_once!(
+                    "Unable to query camera, component and option<camerafollowtarget> for active camera: {:?}",
+                    active_camera
+                );
+            }
+        } else {
+            log_once::warn_once!("No active camera found");
+        }
+
+        self.window = Some(graphics.shared.window.clone());
+        self.is_world_loaded.mark_rendering_loaded();
+    }
 }
 
 pub static LOGGED: LazyLock<Mutex<HashSet<String>>> = LazyLock::new(|| Mutex::new(HashSet::new()));
@@ -643,9 +946,13 @@ fn show_entity_tree(
 /// Describes an action that is undoable
 #[derive(Debug)]
 pub enum UndoableAction {
+    /// A change in transform. The entity + the old transform. Undoing will revert the transform
     Transform(hecs::Entity, Transform),
+    /// A spawn of the entity. Undoing will delete the entity
     Spawn(hecs::Entity),
+    /// A change of label of the entity. Undoing will revert its label
     Label(hecs::Entity, String, EntityType),
+    /// Removing a component. Undoing will add back the component.
     RemoveComponent(hecs::Entity, ComponentType),
     #[allow(dead_code)]
     CameraAction(UndoableCameraAction),
@@ -665,105 +972,117 @@ impl UndoableAction {
         // log::debug!("Undo Stack contents: {:#?}", undo_stack);
     }
 
-    pub fn undo(&self, world: &mut hecs::World) -> anyhow::Result<()> {
+    pub fn undo(&self, world: Arc<RwLock<World>>) -> anyhow::Result<()> {
         match self {
             UndoableAction::Transform(entity, transform) => {
-                if let Ok(mut q) = world.query_one::<&mut Transform>(*entity) {
-                    if let Some(e_t) = q.get() {
-                        *e_t = *transform;
-                        log::debug!("Reverted transform");
-                        Ok(())
+                {
+                    if let Ok(mut q) = world.write().query_one::<&mut Transform>(*entity) {
+                        if let Some(e_t) = q.get() {
+                            *e_t = *transform;
+                            log::debug!("Reverted transform");
+                            Ok(())
+                        } else {
+                            Err(anyhow::anyhow!("Unable to query the entity"))
+                        }
                     } else {
-                        Err(anyhow::anyhow!("Unable to query the entity"))
+                        Err(anyhow::anyhow!("Could not find an entity to query"))
                     }
-                } else {
-                    Err(anyhow::anyhow!("Could not find an entity to query"))
                 }
             }
             UndoableAction::Spawn(entity) => {
-                if world.despawn(*entity).is_ok() {
-                    log::debug!("Undid spawn by despawning entity {:?}", entity);
-                    Ok(())
-                } else {
-                    Err(anyhow::anyhow!("Failed to despawn entity {:?}", entity))
+                {
+                    if world.write().despawn(*entity).is_ok() {
+                        log::debug!("Undid spawn by despawning entity {:?}", entity);
+                        Ok(())
+                    } else {
+                        Err(anyhow::anyhow!("Failed to despawn entity {:?}", entity))
+                    }
                 }
             }
             UndoableAction::Label(entity, original_label, entity_type) => match entity_type {
                 EntityType::Entity => {
-                    if let Ok(mut q) = world.query_one::<&mut AdoptedEntity>(*entity) {
-                        if let Some(adopted) = q.get() {
-                            adopted.model_mut().label = original_label.clone();
-                            log::debug!(
+                    {
+                        if let Ok(mut q) = world.write().query_one::<&mut AdoptedEntity>(*entity) {
+                            if let Some(adopted) = q.get() {
+                                adopted.model_mut().label = original_label.clone();
+                                log::debug!(
                                 "Reverted label for entity {:?} to '{}'",
                                 entity,
                                 original_label
                             );
-                            Ok(())
-                        } else {
-                            Err(anyhow::anyhow!(
+                                Ok(())
+                            } else {
+                                Err(anyhow::anyhow!(
                                 "Unable to query the entity for label revert"
                             ))
-                        }
-                    } else {
-                        Err(anyhow::anyhow!(
+                            }
+                        } else {
+                            Err(anyhow::anyhow!(
                             "Could not find an entity to query for label revert"
                         ))
+                        }
                     }
                 }
                 EntityType::Light => {
-                    if let Ok(mut q) = world.query_one::<&mut Light>(*entity) {
-                        if let Some(adopted) = q.get() {
-                            adopted.label = original_label.clone();
-                            log::debug!(
+                    {
+                        if let Ok(mut q) = world.write().query_one::<&mut Light>(*entity) {
+                            if let Some(adopted) = q.get() {
+                                adopted.label = original_label.clone();
+                                log::debug!(
                                 "Reverted label for light {:?} to '{}'",
                                 entity,
                                 original_label
                             );
-                            Ok(())
-                        } else {
-                            Err(anyhow::anyhow!(
+                                Ok(())
+                            } else {
+                                Err(anyhow::anyhow!(
                                 "Unable to query the light for label revert"
                             ))
-                        }
-                    } else {
-                        Err(anyhow::anyhow!(
+                            }
+                        } else {
+                            Err(anyhow::anyhow!(
                             "Could not find a light to query for label revert"
                         ))
+                        }
                     }
                 }
                 EntityType::Camera => {
-                    if let Ok(mut q) = world.query_one::<&mut Camera>(*entity) {
-                        if let Some(adopted) = q.get() {
-                            adopted.label = original_label.clone();
-                            log::debug!(
+                    {
+                        if let Ok(mut q) = world.write().query_one::<&mut Camera>(*entity) {
+                            if let Some(adopted) = q.get() {
+                                adopted.label = original_label.clone();
+                                log::debug!(
                                 "Reverted label for camera {:?} to '{}'",
                                 entity,
                                 original_label
                             );
-                            Ok(())
-                        } else {
-                            Err(anyhow::anyhow!(
+                                Ok(())
+                            } else {
+                                Err(anyhow::anyhow!(
                                 "Unable to query the camera for label revert"
                             ))
-                        }
-                    } else {
-                        Err(anyhow::anyhow!(
+                            }
+                        } else {
+                            Err(anyhow::anyhow!(
                             "Could not find a camera to query for label revert"
                         ))
+                        }
                     }
                 }
             },
             UndoableAction::RemoveComponent(entity, c_type) => {
                 match c_type {
                     ComponentType::Script(component) => {
-                        world.insert_one(*entity, component.clone())?;
+                        { world.write().insert_one(*entity, component.clone())?; }
                     }
                     ComponentType::Camera(camera, component, follow) => {
                         if let Some(f) = follow {
-                            world
-                                .insert(*entity, (camera.clone(), component.clone(), f.clone()))?;
+                            {
+                                world.write()
+                                    .insert(*entity, (camera.clone(), component.clone(), f.clone()))?;
+                            }
                         } else {
-                            world.insert(*entity, (camera.clone(), component.clone()))?;
+                            { world.write().insert(*entity, (camera.clone(), component.clone()))?; }
                         }
                     }
                 }
@@ -772,35 +1091,43 @@ impl UndoableAction {
             UndoableAction::CameraAction(action) => {
                 match action {
                     UndoableCameraAction::Speed(entity, speed) => {
-                        if let Ok((cam, comp)) =
-                            world.query_one_mut::<(&mut Camera, &mut CameraComponent)>(*entity)
                         {
-                            comp.speed = *speed;
-                            comp.update(cam);
+                            if let Ok((cam, comp)) =
+                                world.write().query_one_mut::<(&mut Camera, &mut CameraComponent)>(*entity)
+                            {
+                                comp.speed = *speed;
+                                comp.update(cam);
+                            }
                         }
                     }
                     UndoableCameraAction::Sensitivity(entity, sensitivity) => {
-                        if let Ok((cam, comp)) =
-                            world.query_one_mut::<(&mut Camera, &mut CameraComponent)>(*entity)
                         {
-                            comp.sensitivity = *sensitivity;
-                            comp.update(cam);
+                            if let Ok((cam, comp)) =
+                                world.write().query_one_mut::<(&mut Camera, &mut CameraComponent)>(*entity)
+                            {
+                                comp.sensitivity = *sensitivity;
+                                comp.update(cam);
+                            }
                         }
                     }
                     UndoableCameraAction::FOV(entity, fov) => {
-                        if let Ok((cam, comp)) =
-                            world.query_one_mut::<(&mut Camera, &mut CameraComponent)>(*entity)
                         {
-                            comp.fov_y = *fov;
-                            comp.update(cam);
+                            if let Ok((cam, comp)) =
+                                world.write().query_one_mut::<(&mut Camera, &mut CameraComponent)>(*entity)
+                            {
+                                comp.fov_y = *fov;
+                                comp.update(cam);
+                            }
                         }
                     }
                     UndoableCameraAction::Type(entity, camera_type) => {
-                        if let Ok((cam, comp)) =
-                            world.query_one_mut::<(&mut Camera, &mut CameraComponent)>(*entity)
                         {
-                            comp.camera_type = *camera_type;
-                            comp.update(cam);
+                            if let Ok((cam, comp)) =
+                                world.write().query_one_mut::<(&mut Camera, &mut CameraComponent)>(*entity)
+                            {
+                                comp.camera_type = *camera_type;
+                                comp.update(cam);
+                            }
                         }
                     }
                 };
@@ -853,136 +1180,60 @@ pub struct PlayModeBackup {
     )>,
 }
 
-impl PlayModeBackup {
-    pub fn create_backup(editor: &mut Editor) -> anyhow::Result<()> {
-        let mut entities = Vec::new();
-
-        for (entity_id, (_, transform, properties)) in editor
-            .world
-            .query::<(&AdoptedEntity, &Transform, &ModelProperties)>()
-            .iter()
-        {
-            let script = editor
-                .world
-                .query_one::<&ScriptComponent>(entity_id)
-                .ok()
-                .and_then(|mut s| s.get().map(|script| script.clone()));
-            entities.push((entity_id, *transform, properties.clone(), script));
-        }
+pub enum EditorState {
+    Editing,
+    Playing,
+}
 
-        let mut camera_data = Vec::new();
+pub enum PendingSpawn2 {
+    CreateLight,
+    CreatePlane,
+    CreateCube,
+    CreateCamera,
+}
 
-        for (entity_id, (camera, component, follow_target)) in editor
-            .world
-            .query::<(&Camera, &CameraComponent, Option<&CameraFollowTarget>)>()
-            .iter()
-        {
-            camera_data.push((
-                entity_id,
-                camera.clone(),
-                component.clone(),
-                follow_target.cloned(),
-            ));
-        }
 
-        editor.play_mode_backup = Some(PlayModeBackup {
-            entities,
-            camera_data,
-        });
+pub(crate) struct IsWorldLoadedYet {
+    /// Whether the project configuration and world data has been loaded
+    pub project_loaded: bool,
+    /// Whether the scene rendering and UI setup is complete
+    pub scene_loaded: bool,
+    /// Checks if the wgpu rendering contexts have been initialised for rendering
+    pub rendering_loaded: bool,
+}
 
-        log::info!(
-            "Created play mode backup with {} entities and {} cameras",
-            editor.play_mode_backup.as_ref().unwrap().entities.len(),
-            editor.play_mode_backup.as_ref().unwrap().camera_data.len()
-        );
-        Ok(())
+impl IsWorldLoadedYet {
+    pub fn new() -> Self {
+        Self {
+            project_loaded: false,
+            scene_loaded: false,
+            rendering_loaded: false,
+        }
     }
 
-    pub fn restore(editor: &mut Editor) -> anyhow::Result<()> {
-        if let Some(backup) = &editor.play_mode_backup {
-            // Restore entity states
-            for (entity_id, original_transform, original_properties, original_script) in
-                &backup.entities
-            {
-                if let Ok(mut transform) = editor.world.get::<&mut Transform>(*entity_id) {
-                    *transform = *original_transform;
-                }
-
-                if let Ok(mut properties) = editor.world.get::<&mut ModelProperties>(*entity_id) {
-                    *properties = original_properties.clone();
-                }
-
-                let has_script = editor.world.get::<&ScriptComponent>(*entity_id).is_ok();
-                match (has_script, original_script) {
-                    (true, Some(original)) => {
-                        if let Ok(mut script) = editor.world.get::<&mut ScriptComponent>(*entity_id)
-                        {
-                            *script = original.clone();
-                        }
-                    }
-                    (true, None) => {
-                        let _ = Arc::get_mut(&mut editor.world).unwrap().remove_one::<ScriptComponent>(*entity_id);
-                    }
-                    (false, Some(original)) => {
-                        let _ = Arc::get_mut(&mut editor.world).unwrap().insert_one(*entity_id, original.clone());
-                    }
-                    (false, None) => {
-                        // No change needed
-                    }
-                }
-            }
-
-            // Restore camera states
-            for (entity_id, original_camera, original_component, original_follow_target) in
-                &backup.camera_data
-            {
-                if let Ok(mut camera) = editor.world.get::<&mut Camera>(*entity_id) {
-                    *camera = original_camera.clone();
-                }
-
-                if let Ok(mut component) = editor.world.get::<&mut CameraComponent>(*entity_id) {
-                    *component = original_component.clone();
-                }
+    pub fn is_fully_loaded(&self) -> bool {
+        self.project_loaded && self.scene_loaded
+    }
 
-                let has_follow_target = editor.world.get::<&CameraFollowTarget>(*entity_id).is_ok();
-                match (has_follow_target, original_follow_target) {
-                    (true, Some(original)) => {
-                        if let Ok(mut follow_target) =
-                            editor.world.get::<&mut CameraFollowTarget>(*entity_id)
-                        {
-                            *follow_target = original.clone();
-                        }
-                    }
-                    (true, None) => {
-                        let _ = Arc::get_mut(&mut editor.world).unwrap().remove_one::<CameraFollowTarget>(*entity_id);
-                    }
-                    (false, Some(original)) => {
-                        let _ = Arc::get_mut(&mut editor.world).unwrap().insert_one(*entity_id, original.clone());
-                    }
-                    (false, None) => {
-                        // No change needed
-                    }
-                }
-            }
+    pub fn is_project_ready(&self) -> bool {
+        self.project_loaded
+    }
 
-            log::info!("Restored scene from play mode backup");
+    pub fn mark_project_loaded(&mut self) {
+        self.project_loaded = true;
+    }
 
-            editor.play_mode_backup = None;
-            Ok(())
-        } else {
-            Err(anyhow::anyhow!("No play mode backup found to restore"))
-        }
+    pub fn mark_scene_loaded(&mut self) {
+        self.scene_loaded = true;
     }
-}
 
-pub enum EditorState {
-    Editing,
-    Playing,
+    pub fn mark_rendering_loaded(&mut self) {
+        self.rendering_loaded = true;
+    }
 }
 
-pub enum PendingSpawn2 {
-    CreateLight,
-    CreatePlane,
-    CreateCube,
-    CreateCamera,
-}
+impl Default for IsWorldLoadedYet {
+    fn default() -> Self {
+        Self::new()
+    }
+}
\ No newline at end of file
diff --git a/eucalyptus-editor/src/editor/scene.rs b/eucalyptus-editor/src/editor/scene.rs
index 1df6d3d..03621ef 100644
--- a/eucalyptus-editor/src/editor/scene.rs
+++ b/eucalyptus-editor/src/editor/scene.rs
@@ -1,24 +1,27 @@
+
 use super::*;
 use dropbear_engine::graphics::{InstanceRaw, RenderContext};
 use dropbear_engine::model::Model;
 use dropbear_engine::starter::plane::PlaneBuilder;
 use dropbear_engine::{
     entity::{AdoptedEntity, Transform},
-    graphics::Shader,
     lighting::{Light, LightComponent},
     model::{DrawLight, DrawModel},
     scene::{Scene, SceneCommand},
 };
 use egui::{Align2, Image};
 use eucalyptus_core::camera::PlayerCamera;
-use eucalyptus_core::states::Value;
+use eucalyptus_core::states::{Value, WorldLoadingStatus};
 use eucalyptus_core::utils::{PROTO_TEXTURE, PendingSpawn};
 use eucalyptus_core::{logging, scripting, success_without_console, warn_without_console};
+use hecs::Entity;
 use log;
 use parking_lot::Mutex;
+use tokio::sync::mpsc::unbounded_channel;
 use wgpu::Color;
 use wgpu::util::DeviceExt;
 use winit::{event_loop::ActiveEventLoop, keyboard::KeyCode};
+use std::sync::LazyLock;
 
 pub static PENDING_SPAWNS: LazyLock<Mutex<Vec<PendingSpawn>>> =
     LazyLock::new(|| Mutex::new(Vec::new()));
@@ -26,64 +29,52 @@ pub static PENDING_SPAWNS: LazyLock<Mutex<Vec<PendingSpawn>>> =
 #[async_trait::async_trait]
 impl Scene for Editor {
     async fn load<'a>(&mut self, graphics: &mut RenderContext<'a>) {
-        if self.active_camera.is_none() {
-            self.load_project_config(graphics.shared.clone()).await.unwrap();
-        }
-
-        let shader = Shader::new(
-            graphics.shared.clone(),
-            include_str!("../../../resources/shaders/shader.wgsl"),
-            Some("viewport_shader"),
-        );
+        let (tx, rx) = unbounded_channel::<WorldLoadingStatus>();
+        self.progress_tx = Some(rx);
 
-        self.light_manager.create_light_array_resources(graphics.shared.clone());
-
-        if let Some(active_camera) = self.active_camera {
-            if let Ok(mut q) = self
-                .world
-                .query_one::<(&Camera, &CameraComponent, Option<&CameraFollowTarget>)>(
-                    active_camera,
-                )
-            {
-                if let Some((camera, _component, _follow_target)) = q.get() {
-                    let pipeline = graphics.create_render_pipline(
-                        &shader,
-                        vec![
-                            &graphics.shared.texture_bind_layout.clone(),
-                            camera.layout(),
-                            self.light_manager.layout(),
-                        ],
-                        None,
-                    );
-                    self.render_pipeline = Some(pipeline);
+        let graphics_shared = graphics.shared.clone();
+        let world_clone = self.world.clone();
+        let active_camera_clone = self.active_camera.clone();
+        let project_path_clone = self.project_path.clone();
+        let dock_state_clone = self.dock_state.clone();
 
-                    self.light_manager.create_render_pipeline(
-                        graphics.shared.clone(),
-                        include_str!("../../../resources/shaders/light.wgsl"),
-                        camera,
-                        Some("Light Pipeline"),
-                    );
-                } else {
-                    log_once::warn_once!(
-                        "Unable to fetch the query result of camera: {:?}",
-                        active_camera
-                    )
+        tokio::task::spawn_blocking(move || {
+            tokio::runtime::Handle::current().block_on(async {
+                {
+                    if let Err(e) = Self::load_project_config(graphics_shared, Some(tx), world_clone, active_camera_clone, project_path_clone, dock_state_clone).await {
+                        log::error!("Failed to load project config: {}", e);
+                    }
                 }
-            } else {
-                log_once::warn_once!(
-                    "Unable to query camera, component and option<camerafollowtarget> for active camera: {:?}",
-                    active_camera
-                );
-            }
-        } else {
-            log_once::warn_once!("No active camera found");
-        }
+            })
+        });
 
         self.window = Some(graphics.shared.window.clone());
+        self.is_world_loaded.mark_scene_loaded();
     }
 
     async fn update<'a>(&mut self, dt: f32, graphics: &mut RenderContext<'a>) {
-        if let Some((_, tab)) = self.dock_state.find_active_focused() {
+        if !self.is_world_loaded.is_project_ready() {
+            log_once::debug_once!("Project is not loaded yet");
+            self.show_project_loading_window(&graphics.shared.get_egui_context());
+            return;
+        } else {
+            log_once::debug_once!("Project has loaded successfully");
+        }
+
+        if !self.is_world_loaded.is_fully_loaded() {
+            log::debug!("Scene is not fully loaded, initializing...");
+            // self.load(graphics).await;
+            return;
+        } else {
+            log_once::debug_once!("Scene has fully loaded");
+        }
+
+        if !self.is_world_loaded.rendering_loaded && self.is_world_loaded.is_fully_loaded() {
+            self.load_wgpu_nerdy_stuff(graphics);
+            return;
+        }
+
+        if let Some((_, tab)) = self.dock_state.lock().find_active_focused() {
             self.is_viewport_focused = matches!(tab, EditorTab::Viewport);
         } else {
             self.is_viewport_focused = false;
@@ -95,11 +86,22 @@ impl Scene for Editor {
         };
 
         for spawn in spawns_to_process {
-            match AdoptedEntity::new(graphics.shared.clone(), &spawn.asset_path, Some(&spawn.asset_name)).await {
+            match AdoptedEntity::new(
+                graphics.shared.clone(),
+                &spawn.asset_path,
+                Some(&spawn.asset_name),
+            )
+            .await
+            {
                 Ok(adopted) => {
-                    let entity_id = Arc::get_mut(&mut self.world).unwrap()
-                        .spawn((adopted, spawn.transform, spawn.properties));
-                    
+                    let entity_id = {
+                        self.world.write().spawn((
+                            adopted,
+                            spawn.transform,
+                            spawn.properties,
+                        ))
+                    };
+
                     self.selected_entity = Some(entity_id);
 
                     UndoableAction::push_to_undo(
@@ -125,20 +127,25 @@ impl Scene for Editor {
             }
 
             let mut script_entities = Vec::new();
-            for (entity_id, script) in Arc::get_mut(&mut self.world).unwrap().query::<&mut ScriptComponent>().iter() {
-                log_once::debug_once!(
-                    "Script Entity -> id: {:?}, component: {:?}",
-                    entity_id,
-                    script
-                );
-                script.name = script
-                    .path
-                    .file_name()
-                    .unwrap()
-                    .to_str()
-                    .unwrap()
-                    .to_string();
-                script_entities.push((entity_id, script.name.clone()));
+            {
+                for (entity_id, script) in self.world.read()
+                    .query::<&mut ScriptComponent>()
+                    .iter()
+                {
+                    log_once::debug_once!(
+                        "Script Entity -> id: {:?}, component: {:?}",
+                        entity_id,
+                        script
+                    );
+                    script.name = script
+                        .path
+                        .file_name()
+                        .unwrap()
+                        .to_str()
+                        .unwrap()
+                        .to_string();
+                    script_entities.push((entity_id, script.name.clone()));
+                }
             }
 
             if script_entities.is_empty() {
@@ -149,7 +156,7 @@ impl Scene for Editor {
                 if let Err(e) = self.script_manager.update_entity_script(
                     entity_id,
                     &script_name,
-                    &mut self.world,
+                    self.world.clone(),
                     &self.input_state,
                     dt,
                 ) {
@@ -184,14 +191,13 @@ impl Scene for Editor {
                 .copied()
                 .collect();
 
-            // Handle camera input through ECS
-            if let Some(active_camera) = self.active_camera {
-                if let Ok(mut query) = self
-                    .world
+            let active_cam = self.active_camera.lock();
+            if let Some(active_camera) = *active_cam {
+                let world = self.world.read();
+                if let Ok(mut query) = world
                     .query_one::<(&mut Camera, &CameraComponent)>(active_camera)
                 {
                     if let Some((camera, component)) = query.get() {
-                        // Handle keyboard input based on camera type
                         match component.camera_type {
                             CameraType::Debug => {
                                 DebugCamera::handle_keyboard_input(camera, &movement_keys);
@@ -210,7 +216,6 @@ impl Scene for Editor {
                                 );
                             }
                             CameraType::Normal => {
-                                // Handle normal camera input if needed
                                 DebugCamera::handle_keyboard_input(camera, &movement_keys);
                                 DebugCamera::handle_mouse_input(
                                     camera,
@@ -222,29 +227,46 @@ impl Scene for Editor {
                     }
                 }
             }
+            
         }
 
         match &self.signal {
-            Signal::Paste(scene_entity) => {
-                match &scene_entity.model_path.ref_type {
-                    dropbear_engine::utils::ResourceReferenceType::None => {
-                        warn!("Resource has a reference type of None");
-                        self.signal = Signal::None;
-                    },
-                    dropbear_engine::utils::ResourceReferenceType::File(reference) => {
-                        match &scene_entity.model_path.to_project_path(self.project_path.clone().unwrap()) {
+            Signal::Paste(scene_entity) => match &scene_entity.model_path.ref_type {
+                dropbear_engine::utils::ResourceReferenceType::None => {
+                    warn!("Resource has a reference type of None");
+                    self.signal = Signal::None;
+                }
+                dropbear_engine::utils::ResourceReferenceType::File(reference) => {
+                    let cloned = {
+                        let project_path = self.project_path.lock();
+                        project_path.clone()
+                    };
+                    if let Some(proj_root) = cloned {
+                        match &scene_entity
+                            .model_path
+                            .to_project_path(proj_root)
+                        {
                             Some(v) => {
-                                match AdoptedEntity::new(
-                                    graphics.shared.clone(),
-                                    v,
-                                    Some(&scene_entity.label),
-                                ).await {
+                                let entity = {
+                                    AdoptedEntity::new(
+                                        graphics.shared.clone(),
+                                        v,
+                                        Some(&scene_entity.label),
+                                    ).await
+                                };
+
+                                match entity
+                                {
                                     Ok(adopted) => {
-                                        let entity_id = Arc::get_mut(&mut self.world).unwrap().spawn((
-                                            adopted,
-                                            scene_entity.transform,
-                                            ModelProperties::default(),
-                                        ));
+                                        let entity_id = {
+                                            self.world.write().spawn((
+                                                adopted,
+                                                scene_entity.transform,
+                                                ModelProperties::default(),
+                                            ))
+                                        };
+                                        
+
                                         self.selected_entity = Some(entity_id);
                                         log::debug!(
                                             "Successfully paste-spawned {} with ID {:?}",
@@ -259,52 +281,67 @@ impl Scene for Editor {
                                         warn!("Failed to paste-spawn {}: {}", scene_entity.label, e);
                                     }
                                 }
-                            },
+                            }
                             None => {
-                                fatal!("Unable to convert resource reference [{}] to project related path", reference);
-                                self.signal = Signal::None;
-                            },
-                        };
-                    },
-                    dropbear_engine::utils::ResourceReferenceType::Bytes(bytes) => {
-                        let model = match Model::load_from_memory(graphics.shared.clone(), bytes, Some(&scene_entity.label)).await {
-                            Ok(v) => v,
-                            Err(e) => {
-                                fatal!("Unable to load from memory: {}", e);
+                                fatal!(
+                                    "Unable to convert resource reference [{}] to project related path",
+                                    reference
+                                );
                                 self.signal = Signal::None;
-                                return;
-                            },
+                            }
                         };
-                        let adopted = AdoptedEntity::adopt(
-                            graphics.shared.clone(),
-                            model,
-                        ).await;
-                        let entity_id = Arc::get_mut(&mut self.world).unwrap().spawn((
+                    } else {
+                        fatal!("Project path is not set");
+                        self.signal = Signal::None;
+                    }
+                }
+                dropbear_engine::utils::ResourceReferenceType::Bytes(bytes) => {
+                    let model = match Model::load_from_memory(
+                        graphics.shared.clone(),
+                        bytes,
+                        Some(&scene_entity.label),
+                    )
+                    .await
+                    {
+                        Ok(v) => v,
+                        Err(e) => {
+                            fatal!("Unable to load from memory: {}", e);
+                            self.signal = Signal::None;
+                            return;
+                        }
+                    };
+                    let adopted = AdoptedEntity::adopt(graphics.shared.clone(), model).await;
+
+                    let entity_id = {
+                        self.world.write().spawn((
                             adopted,
                             scene_entity.transform,
                             ModelProperties::default(),
-                        ));
-                        self.selected_entity = Some(entity_id);
-                        log::debug!(
-                            "Successfully paste-spawned {} with ID {:?}",
-                            scene_entity.label,
-                            entity_id
-                        );
+                        ))
+                    };
+                    
+                    self.selected_entity = Some(entity_id);
+                    log::debug!(
+                        "Successfully paste-spawned {} with ID {:?}",
+                        scene_entity.label,
+                        entity_id
+                    );
 
-                        success_without_console!("Paste!");
-                        self.signal = Signal::Copy(scene_entity.clone());
-                    },
-                    _ => {
-                        warn!("Unable to copy, not of bytes or path");
-                        self.signal = Signal::None;
-                        return;
-                    }
+                    success_without_console!("Paste!");
+                    self.signal = Signal::Copy(scene_entity.clone());
                 }
-            }
+                _ => {
+                    warn!("Unable to copy, not of bytes or path");
+                    self.signal = Signal::None;
+                    return;
+                }
+            },
             Signal::Delete => {
                 if let Some(sel_e) = &self.selected_entity {
-                    let is_viewport_cam =
-                        if let Ok(mut q) = Arc::get_mut(&mut self.world).unwrap().query_one::<&CameraComponent>(*sel_e) {
+                    {
+                        let is_viewport_cam = if let Ok(mut q) = self.world.read()
+                            .query_one::<&CameraComponent>(*sel_e)
+                        {
                             if let Some(c) = q.get() {
                                 if matches!(c.camera_type, CameraType::Debug) {
                                     true
@@ -317,38 +354,42 @@ impl Scene for Editor {
                         } else {
                             false
                         };
-                    if is_viewport_cam {
-                        warn!("You can't delete the viewport camera");
-                        self.signal = Signal::None;
-                    } else {
-                        match Arc::get_mut(&mut self.world).unwrap().despawn(*sel_e) {
-                            Ok(_) => {
-                                info!("Decimated entity");
-                                self.signal = Signal::None;
-                            }
-                            Err(e) => {
-                                warn!("Failed to delete entity: {}", e);
-                                self.signal = Signal::None;
+                        if is_viewport_cam {
+                            warn!("You can't delete the viewport camera");
+                            self.signal = Signal::None;
+                        } else {
+                            match self.world.write().despawn(*sel_e) {
+                                Ok(_) => {
+                                    info!("Decimated entity");
+                                    self.signal = Signal::None;
+                                }
+                                Err(e) => {
+                                    warn!("Failed to delete entity: {}", e);
+                                    self.signal = Signal::None;
+                                }
                             }
+                            // println!("is world still locked here [{}]: {}", file!(), self.world.is_locked_exclusive())
                         }
                     }
                 }
             }
             Signal::Undo => {
-                if let Some(action) = self.undo_stack.pop() {
-                    match action.undo(&mut Arc::get_mut(&mut self.world).unwrap()) {
-                        Ok(_) => {
-                            info!("Undid action");
-                        }
-                        Err(e) => {
-                            warn!("Failed to undo action: {}", e);
+                {
+                    if let Some(action) = self.undo_stack.pop() {
+                        match action.undo(self.world.clone()) {
+                            Ok(_) => {
+                                info!("Undid action");
+                            }
+                            Err(e) => {
+                                warn!("Failed to undo action: {}", e);
+                            }
                         }
+                    } else {
+                        warn_without_console!("Nothing to undo");
+                        log::debug!("No undoable actions in stack");
                     }
-                } else {
-                    warn_without_console!("Nothing to undo");
-                    log::debug!("No undoable actions in stack");
+                    self.signal = Signal::None;
                 }
-                self.signal = Signal::None;
             }
             Signal::None => {}
             Signal::Copy(_) => {}
@@ -365,19 +406,25 @@ impl Scene for Editor {
                                     path: moved_path.clone(),
                                 };
 
-                                let replaced = if let Ok(mut sc) =
-                                    Arc::get_mut(&mut self.world).unwrap().get::<&mut ScriptComponent>(selected_entity)
-                                {
-                                    sc.name = new_script.name.clone();
-                                    sc.path = new_script.path.clone();
-                                    true
-                                } else {
+                                let replaced = {
+                                    let world = self.world.read();
+                                    if let Ok(mut sc) = world.get::<&mut ScriptComponent>(selected_entity) {
+                                        sc.name = new_script.name.clone();
+                                        sc.path = new_script.path.clone();
+                                        true
+                                    } else {
+                                        false
+                                    }
+                                };
+
+                                if !replaced {
                                     match scripting::attach_script_to_entity(
-                                        &mut Arc::get_mut(&mut self.world).unwrap(),
+                                        self.world.clone(),
                                         selected_entity,
                                         new_script.clone(),
                                     ) {
-                                        Ok(_) => false,
+                                        Ok(_) => {
+                                        }
                                         Err(e) => {
                                             fatal!(
                                                 "Failed to attach script to entity {:?}: {}",
@@ -388,12 +435,15 @@ impl Scene for Editor {
                                             return;
                                         }
                                     }
-                                };
+                                }
 
-                                if let Err(e) =
-                                    scripting::convert_entity_to_group(&Arc::get_mut(&mut self.world).unwrap(), selected_entity)
                                 {
-                                    log::warn!("convert_entity_to_group failed (non-fatal): {}", e);
+                                    if let Err(e) = scripting::convert_entity_to_group(
+                                        self.world.clone(),
+                                        selected_entity,
+                                    ) {
+                                        log::warn!("convert_entity_to_group failed (non-fatal): {}", e);
+                                    }
                                 }
 
                                 success!(
@@ -424,31 +474,40 @@ impl Scene for Editor {
                             path: script_path.clone(),
                         };
 
-                        let replaced = if let Ok(mut sc) =
-                            Arc::get_mut(&mut self.world).unwrap().get::<&mut ScriptComponent>(selected_entity)
-                        {
-                            sc.name = new_script.name.clone();
-                            sc.path = new_script.path.clone();
-                            true
-                        } else {
+                        let replaced = {
+                            let world = self.world.read();
+                            if let Ok(mut sc) = world.get::<&mut ScriptComponent>(selected_entity) {
+                                sc.name = new_script.name.clone();
+                                sc.path = new_script.path.clone();
+                                true
+                            } else {
+                                false
+                            }
+                        };
+
+                        if !replaced {
                             match scripting::attach_script_to_entity(
-                                Arc::get_mut(&mut self.world).unwrap(),
+                                self.world.clone(),
                                 selected_entity,
                                 new_script.clone(),
                             ) {
-                                Ok(_) => false,
+                                Ok(_) => {
+                                }
                                 Err(e) => {
                                     fatal!("Failed to attach new script: {}", e);
                                     self.signal = Signal::None;
                                     return;
                                 }
                             }
-                        };
+                        }
 
-                        if let Err(e) =
-                            scripting::convert_entity_to_group(&Arc::get_mut(&mut self.world).unwrap(), selected_entity)
                         {
-                            log::warn!("convert_entity_to_group failed (non-fatal): {}", e);
+                            if let Err(e) = scripting::convert_entity_to_group(
+                                self.world.clone(),
+                                selected_entity,
+                            ) {
+                                log::warn!("convert_entity_to_group failed (non-fatal): {}", e);
+                            }
                         }
 
                         success!(
@@ -466,14 +525,25 @@ impl Scene for Editor {
                 }
                 ScriptAction::RemoveScript => {
                     if let Some(selected_entity) = self.selected_entity {
-                        if let Ok(script) =
-                            Arc::get_mut(&mut self.world).unwrap().remove_one::<ScriptComponent>(selected_entity)
+                        let mut success = false;
+                        let mut comp = ScriptComponent::default();
                         {
-                            success!("Removed script from entity {:?}", selected_entity);
-
-                            if let Err(e) =
-                                scripting::convert_entity_to_group(&Arc::get_mut(&mut self.world).unwrap(), selected_entity)
+                            if let Ok(script) = self.world.write()
+                                .remove_one::<ScriptComponent>(selected_entity)
                             {
+                                success!("Removed script from entity {:?}", selected_entity);
+                                success = true;
+                                comp = script.clone();
+                            } else {
+                                warn!("No script component found on entity {:?}", selected_entity);
+                            }
+                        }
+
+                        if success {
+                            if let Err(e) = scripting::convert_entity_to_group(
+                                self.world.clone(),
+                                selected_entity,
+                            ) {
                                 log::warn!("convert_entity_to_group failed (non-fatal): {}", e);
                             }
                             log::debug!("Pushing remove component to undo stack");
@@ -481,11 +551,9 @@ impl Scene for Editor {
                                 &mut self.undo_stack,
                                 UndoableAction::RemoveComponent(
                                     selected_entity,
-                                    ComponentType::Script(script),
+                                    ComponentType::Script(comp),
                                 ),
                             );
-                        } else {
-                            warn!("No script component found on entity {:?}", selected_entity);
                         }
                     } else {
                         warn!("No entity selected to remove script from");
@@ -495,16 +563,22 @@ impl Scene for Editor {
                 }
                 ScriptAction::EditScript => {
                     if let Some(selected_entity) = self.selected_entity {
-                        if let Ok(mut q) = Arc::get_mut(&mut self.world).unwrap().query_one::<&ScriptComponent>(selected_entity)
-                        {
-                            if let Some(script) = q.get() {
-                                match open::that(script.path.clone()) {
-                                    Ok(()) => {
-                                        success!("Opened {}", script.name)
-                                    }
-                                    Err(e) => {
-                                        warn!("Error while opening {}: {}", script.name, e);
-                                    }
+                        let script_opt = {
+                            let world = self.world.read();
+                            if let Ok(mut q) = world.query_one::<&ScriptComponent>(selected_entity) {
+                                q.get().cloned()
+                            } else {
+                                None
+                            }
+                        };
+
+                        if let Some(script) = script_opt {
+                            match open::that(script.path.clone()) {
+                                Ok(()) => {
+                                    success!("Opened {}", script.name)
+                                }
+                                Err(e) => {
+                                    warn!("Error while opening {}: {}", script.name, e);
                                 }
                             }
                         } else {
@@ -517,15 +591,14 @@ impl Scene for Editor {
                 }
             },
             Signal::Play => {
-                // Check if a player camera target exists
                 let has_player_camera_target = self
-                    .world
+                    .world.read()
                     .query::<(&Camera, &CameraComponent, &CameraFollowTarget)>()
                     .iter()
                     .any(|(_, (_, comp, _))| matches!(comp.camera_type, CameraType::Player));
 
                 if has_player_camera_target {
-                    if let Err(e) = PlayModeBackup::create_backup(self) {
+                    if let Err(e) = self.create_backup() {
                         fatal!("Failed to create play mode backup: {}", e);
                         self.signal = Signal::None;
                         return;
@@ -536,8 +609,13 @@ impl Scene for Editor {
                     self.switch_to_player_camera();
 
                     let mut script_entities = Vec::new();
-                    for (entity_id, script) in Arc::get_mut(&mut self.world).unwrap().query::<&ScriptComponent>().iter() {
-                        script_entities.push((entity_id, script.clone()));
+                    {
+                        for (entity_id, script) in self.world.read()
+                            .query::<&ScriptComponent>()
+                            .iter()
+                        {
+                            script_entities.push((entity_id, script.clone()));
+                        }
                     }
 
                     for (entity_id, script) in script_entities {
@@ -547,21 +625,33 @@ impl Scene for Editor {
                             script.path.display()
                         );
 
-                        let bytes = match std::fs::read(&script.path) {
+                        let bytes = match tokio::fs::read_to_string(&script.path).await {
                             Ok(val) => val,
                             Err(e) => {
-                                fatal!("Unable to read script {} to bytes because {}", &script.path.display(), e);
+                                fatal!(
+                                    "Unable to read script {} to bytes because {}",
+                                    &script.path.display(),
+                                    e
+                                );
                                 self.signal = Signal::None;
                                 return;
-                            },
+                            }
                         };
-                        
-                        match self.script_manager.load_script(&script.path.file_name().unwrap().to_string_lossy().to_string(), bytes) {
+
+                        match self.script_manager.load_script(
+                            &script
+                                .path
+                                .file_name()
+                                .unwrap()
+                                .to_string_lossy()
+                                .to_string(),
+                            bytes,
+                        ) {
                             Ok(script_name) => {
                                 if let Err(e) = self.script_manager.init_entity_script(
                                     entity_id,
                                     &script_name,
-                                    &mut self.world,
+                                    self.world.clone(),
                                     &self.input_state,
                                 ) {
                                     log::warn!(
@@ -592,7 +682,7 @@ impl Scene for Editor {
                 self.signal = Signal::None;
             }
             Signal::StopPlaying => {
-                if let Err(e) = PlayModeBackup::restore(self) {
+                if let Err(e) = self.restore() {
                     warn!("Failed to restore from play mode backup: {}", e);
                     log::warn!("Failed to restore scene state: {}", e);
                 }
@@ -601,9 +691,10 @@ impl Scene for Editor {
 
                 self.switch_to_debug_camera();
 
-                for (entity_id, _) in Arc::get_mut(&mut self.world).unwrap().query::<&ScriptComponent>().iter() {
-                    self.script_manager.remove_entity_script(entity_id);
-                }
+                // already kills itself
+                // for (entity_id, _) in Arc::get_mut(&mut self.world).unwrap().query::<&ScriptComponent>().iter() {
+                //     self.script_manager.remove_entity_script(entity_id);
+                // }
 
                 success!("Exited play mode");
                 log::info!("Back to the editor you go...");
@@ -612,9 +703,8 @@ impl Scene for Editor {
             }
             Signal::CameraAction(action) => match action {
                 CameraAction::SetPlayerTarget { entity, offset } => {
-                    // Find player camera and add/update CameraFollowTarget component
                     let player_camera = self
-                        .world
+                        .world.read()
                         .query::<(&Camera, &CameraComponent)>()
                         .iter()
                         .find_map(|(e, (_, comp))| {
@@ -627,8 +717,9 @@ impl Scene for Editor {
 
                     if let Some(camera_entity) = player_camera {
                         let mut follow_target = (false, CameraFollowTarget::default());
-                        // Find the target entity label
-                        if let Ok(mut query) = Arc::get_mut(&mut self.world).unwrap().query_one::<&AdoptedEntity>(*entity) {
+                        if let Ok(mut query) = self.world.read()
+                            .query_one::<&AdoptedEntity>(*entity)
+                        {
                             if let Some(adopted) = query.get() {
                                 follow_target = (
                                     true,
@@ -640,16 +731,19 @@ impl Scene for Editor {
                             }
                         }
 
-                        if follow_target.0 {
-                            let _ = Arc::get_mut(&mut self.world).unwrap().insert_one(camera_entity, follow_target);
-                            info!("Set player camera target to entity {:?}", entity);
+                        {
+                            if follow_target.0 {
+                                let _ = self.world.write()
+                                    .insert_one(camera_entity, follow_target);
+                                info!("Set player camera target to entity {:?}", entity);
+                            }
                         }
                     }
                     self.signal = Signal::None;
                 }
                 CameraAction::ClearPlayerTarget => {
                     let player_camera = self
-                        .world
+                        .world.read()
                         .query::<(&Camera, &CameraComponent)>()
                         .iter()
                         .find_map(|(e, (_, comp))| {
@@ -661,7 +755,10 @@ impl Scene for Editor {
                         });
 
                     if let Some(camera_entity) = player_camera {
-                        let _ = Arc::get_mut(&mut self.world).unwrap().remove_one::<CameraFollowTarget>(camera_entity);
+                        {
+                            let _ = self.world.write()
+                                .remove_one::<CameraFollowTarget>(camera_entity);
+                        }
                     }
                     info!("Cleared player camera target");
                     self.signal = Signal::None;
@@ -670,7 +767,9 @@ impl Scene for Editor {
             Signal::AddComponent(entity, e_type) => {
                 match e_type {
                     EntityType::Entity => {
-                        if let Ok(e) = Arc::get_mut(&mut self.world).unwrap().query_one_mut::<&AdoptedEntity>(*entity) {
+                        if let Ok(e) = self.world.write()
+                            .query_one_mut::<&AdoptedEntity>(*entity)
+                        {
                             let mut local_signal: Option<Signal> = None;
                             let label = e.label().clone();
                             let mut show = true;
@@ -692,15 +791,17 @@ impl Scene for Editor {
                                             "Adding scripting component to entity [{}]",
                                             label
                                         );
-                                        if let Err(e) = Arc::get_mut(&mut self.world).unwrap()
-                                            .insert_one(*entity, ScriptComponent::default())
                                         {
-                                            warn!(
+                                            if let Err(e) = self.world.write()
+                                                .insert_one(*entity, ScriptComponent::default())
+                                            {
+                                                warn!(
                                                 "Failed to add scripting component to entity: {}",
                                                 e
                                             );
-                                        } else {
-                                            success!("Added the scripting component");
+                                            } else {
+                                                success!("Added the scripting component");
+                                            }
                                         }
                                         local_signal = Some(Signal::None);
                                     }
@@ -716,8 +817,7 @@ impl Scene for Editor {
                                             label
                                         );
 
-                                        let has_camera = self
-                                            .world
+                                        let has_camera = self.world.read()
                                             .query_one::<(&Camera, &CameraComponent)>(*entity)
                                             .is_ok();
 
@@ -733,15 +833,17 @@ impl Scene for Editor {
                                             );
                                             let component = CameraComponent::new();
 
-                                            if let Err(e) =
-                                                Arc::get_mut(&mut self.world).unwrap().insert(*entity, (camera, component))
                                             {
-                                                warn!(
+                                                if let Err(e) = self.world.write()
+                                                    .insert(*entity, (camera, component))
+                                                {
+                                                    warn!(
                                                     "Failed to add camera component to entity: {}",
                                                     e
                                                 );
-                                            } else {
-                                                success!("Added the camera component");
+                                                } else {
+                                                    success!("Added the camera component");
+                                                }
                                             }
                                         }
                                         local_signal = Some(Signal::None);
@@ -760,83 +862,92 @@ impl Scene for Editor {
                         }
                     }
                     EntityType::Light => {
-                        if let Ok(light) = Arc::get_mut(&mut self.world).unwrap().query_one_mut::<&Light>(*entity) {
-                            let mut show = true;
-                            egui::Window::new(format!("Add component for {}", light.label))
-                                .scroll([false, true])
-                                .anchor(Align2::CENTER_CENTER, [0.0, 0.0])
-                                .enabled(true)
-                                .open(&mut show)
-                                .title_bar(true)
-                                .show(&graphics.shared.get_egui_context(), |ui| {
-                                    if ui
-                                        .add_sized(
-                                            [ui.available_width(), 30.0],
-                                            egui::Button::new("Scripting"),
-                                        )
-                                        .clicked()
-                                    {
-                                        log::debug!(
+                        {
+                            if let Ok(light) = self.world.write()
+                                .query_one_mut::<&Light>(*entity)
+                            {
+                                let mut show = true;
+                                egui::Window::new(format!("Add component for {}", light.label))
+                                    .scroll([false, true])
+                                    .anchor(Align2::CENTER_CENTER, [0.0, 0.0])
+                                    .enabled(true)
+                                    .open(&mut show)
+                                    .title_bar(true)
+                                    .show(&graphics.shared.get_egui_context(), |ui| {
+                                        if ui
+                                            .add_sized(
+                                                [ui.available_width(), 30.0],
+                                                egui::Button::new("Scripting"),
+                                            )
+                                            .clicked()
+                                        {
+                                            log::debug!(
                                             "Adding scripting component to light [{}]",
                                             light.label
                                         );
 
-                                        success!(
+                                            success!(
                                             "Added the scripting component to light [{}]",
                                             light.label
                                         );
-                                        self.signal = Signal::None;
-                                    }
-                                });
-                            if !show {
-                                self.signal = Signal::None;
-                            }
-                        } else {
-                            log_once::warn_once!(
+                                            self.signal = Signal::None;
+                                        }
+                                    });
+                                if !show {
+                                    self.signal = Signal::None;
+                                }
+                            } else {
+                                log_once::warn_once!(
                                 "Failed to add component to light: no light component found"
                             );
+                            }
                         }
                     }
                     EntityType::Camera => {
-                        if let Ok((cam, _comp)) = Arc::get_mut(&mut self.world).unwrap()
-                            .query_one_mut::<(&Camera, &CameraComponent)>(*entity)
                         {
-                            let mut show = true;
-                            egui::Window::new(format!("Add component for {}", cam.label))
-                                .scroll([false, true])
-                                .anchor(Align2::CENTER_CENTER, [0.0, 0.0])
-                                .enabled(true)
-                                .open(&mut show)
-                                .title_bar(true)
-                                .show(&graphics.shared.get_egui_context(), |ui| {
-                                    egui_extras::install_image_loaders(ui.ctx());
-                                    ui.add(Image::from_bytes(
-                                        "bytes://theres_nothing",
-                                        include_bytes!("../../../resources/theres_nothing.jpg"),
-                                    ));
-                                    ui.label("Theres nothing...");
-                                    // // scripting
-                                    // if ui.add_sized([ui.available_width(), 30.0], egui::Button::new("Scripting")).clicked() {
-                                    //     log::debug!("Adding scripting component to camera [{}]", cam.label);
-
-                                    //     success!("Added the scripting component to camera [{}]", cam.label);
-                                    //     self.signal = Signal::None;
-                                    // }
-                                });
-                            if !show {
-                                self.signal = Signal::None;
-                            }
-                        } else {
-                            log_once::warn_once!(
+                            if let Ok((cam, _comp)) = self.world.write()
+                                .query_one_mut::<(&Camera, &CameraComponent)>(*entity)
+                            {
+                                let mut show = true;
+                                egui::Window::new(format!("Add component for {}", cam.label))
+                                    .scroll([false, true])
+                                    .anchor(Align2::CENTER_CENTER, [0.0, 0.0])
+                                    .enabled(true)
+                                    .open(&mut show)
+                                    .title_bar(true)
+                                    .show(&graphics.shared.get_egui_context(), |ui| {
+                                        egui_extras::install_image_loaders(ui.ctx());
+                                        ui.add(Image::from_bytes(
+                                            "bytes://theres_nothing.jpg",
+                                            include_bytes!("../../../resources/theres_nothing.jpg"),
+                                        ));
+                                        ui.label("Theres nothing...");
+                                        // // scripting
+                                        // if ui.add_sized([ui.available_width(), 30.0], egui::Button::new("Scripting")).clicked() {
+                                        //     log::debug!("Adding scripting component to camera [{}]", cam.label);
+
+                                        //     success!("Added the scripting component to camera [{}]", cam.label);
+                                        //     self.signal = Signal::None;
+                                        // }
+                                    });
+                                if !show {
+                                    self.signal = Signal::None;
+                                }
+                            } else {
+                                log_once::warn_once!(
                                 "Failed to add component to light: no light component found"
                             );
+                            }
                         }
                     }
                 }
             }
-            Signal::RemoveComponent(entity, c_type) => match c_type {
+            Signal::RemoveComponent(entity, c_type) =>
+            {match c_type {
                 ComponentType::Script(_) => {
-                    match Arc::get_mut(&mut self.world).unwrap().remove_one::<ScriptComponent>(*entity) {
+                    match self.world.write()
+                        .remove_one::<ScriptComponent>(*entity)
+                    {
                         Ok(component) => {
                             success!("Removed script component from entity {:?}", entity);
                             UndoableAction::push_to_undo(
@@ -855,9 +966,13 @@ impl Scene for Editor {
                 }
                 ComponentType::Camera(_, _, follow) => {
                     if let Some(_) = follow {
-                        match Arc::get_mut(&mut self.world).unwrap()
-                            .remove::<(Camera, CameraComponent, CameraFollowTarget)>(*entity)
-                        {
+                        match self.world.write().remove::<(
+                            Camera,
+                            CameraComponent,
+                            CameraFollowTarget,
+                        )>(
+                            *entity
+                        ) {
                             Ok(component) => {
                                 success!("Removed camera component from entity {:?}", entity);
                                 UndoableAction::push_to_undo(
@@ -877,7 +992,9 @@ impl Scene for Editor {
                             }
                         };
                     } else {
-                        match Arc::get_mut(&mut self.world).unwrap().remove::<(Camera, CameraComponent)>(*entity) {
+                        match self.world.write()
+                            .remove::<(Camera, CameraComponent)>(*entity)
+                        {
                             Ok(component) => {
                                 success!("Removed camera component from entity {:?}", entity);
                                 UndoableAction::push_to_undo(
@@ -894,9 +1011,8 @@ impl Scene for Editor {
                         };
                     }
                 }
-            },
+            }},
             Signal::CreateEntity => {
-                // self.show_add_entity_window = true;
                 let mut show = true;
                 egui::Window::new("Add Entity")
                     .scroll([false, true])
@@ -937,8 +1053,9 @@ impl Scene for Editor {
                 }
             }
             Signal::LogEntities => {
-                log::info!("====================");
-                for entity in Arc::get_mut(&mut self.world).unwrap().iter() {
+                log::debug!("====================");
+                let mut counter = 0;
+                for entity in self.world.read().iter() {
                     if let Some(entity) = entity.get::<&AdoptedEntity>() {
                         log::info!("Model: {:?}", entity.label());
                     }
@@ -946,64 +1063,99 @@ impl Scene for Editor {
                     if let Some(entity) = entity.get::<&Light>() {
                         log::info!("Light: {:?}", entity.label());
                     }
+
+                    if let Some(_) = entity.get::<&Camera>() {
+                        log::info!("Camera");
+                    }
+                    counter += 1;
                 }
-                log::info!("====================");
+                log::debug!("====================");
+                info!("Total entity count: {}", counter);
                 self.signal = Signal::None;
-            },
+            }
             Signal::Spawn(entity_type) => {
                 match entity_type {
                     crate::editor::PendingSpawn2::CreateLight => {
                         let transform = Transform::new();
                         let component = LightComponent::default();
-                        let light = Light::new(graphics.shared.clone(), &component, &transform, Some("Light")).await;
-                        Arc::get_mut(&mut self.world).unwrap().spawn((light, component, transform));
+                        let light = Light::new(
+                            graphics.shared.clone(),
+                            &component,
+                            &transform,
+                            Some("Light"),
+                        )
+                        .await;
+                        {
+                            self.world.write()
+                                .spawn((light, component, transform));
+                        }
                         success!("Created new light");
-                    },
+                    }
                     crate::editor::PendingSpawn2::CreatePlane => {
                         let plane = PlaneBuilder::new()
                             .with_size(500.0, 200.0)
-                            .build(
-                                graphics.shared.clone(),
-                                PROTO_TEXTURE,
-                                Some("Plane")
-                            ).await.unwrap();
+                            .build(graphics.shared.clone(), PROTO_TEXTURE, Some("Plane"))
+                            .await
+                            .unwrap();
 
                         let transform = Transform::new();
                         let mut props = ModelProperties::new();
-                        props.custom_properties.insert("width".to_string(), Value::Float(500.0));
-                        props.custom_properties.insert("height".to_string(), Value::Float(200.0));
-                        props.custom_properties.insert("tiles_x".to_string(), Value::Int(500));
-                        props.custom_properties.insert("tiles_z".to_string(), Value::Int(200));
-                        Arc::get_mut(&mut self.world).unwrap().spawn((plane, transform, props));
+                        props
+                            .custom_properties
+                            .insert("width".to_string(), Value::Float(500.0));
+                        props
+                            .custom_properties
+                            .insert("height".to_string(), Value::Float(200.0));
+                        props
+                            .custom_properties
+                            .insert("tiles_x".to_string(), Value::Int(500));
+                        props
+                            .custom_properties
+                            .insert("tiles_z".to_string(), Value::Int(200));
+                        {
+                            self.world.write()
+                                .spawn((plane, transform, props));
+                        }
                         success!("Created new plane");
-                    },
+                    }
                     crate::editor::PendingSpawn2::CreateCube => {
                         let model = Model::load_from_memory(
                             graphics.shared.clone(),
                             include_bytes!("../../../resources/cube.glb"),
-                            Some("Cube")
-                        ).await;
+                            Some("Cube"),
+                        )
+                        .await;
                         match model {
                             Ok(model) => {
                                 let cube = AdoptedEntity::adopt(
                                     graphics.shared.clone(),
                                     model,
                                     // Some("Cube")
-                                ).await;
-                                Arc::get_mut(&mut self.world).unwrap().spawn((cube, Transform::new(), ModelProperties::new()));
+                                )
+                                .await;
+                                {
+                                    self.world.write().spawn((
+                                        cube,
+                                        Transform::new(),
+                                        ModelProperties::new(),
+                                    ));
+                                }
                             }
                             Err(e) => {
                                 fatal!("Failed to load cube model: {}", e);
                             }
                         }
                         success!("Created new cube");
-                    },
+                    }
                     crate::editor::PendingSpawn2::CreateCamera => {
                         let camera = Camera::predetermined(graphics.shared.clone(), None);
                         let component = CameraComponent::new();
-                        Arc::get_mut(&mut self.world).unwrap().spawn((camera, component));
+                        {
+                            self.world.write()
+                                .spawn((camera, component));
+                        }
                         success!("Created new camera");
-                    },
+                    }
                 }
                 self.signal = Signal::None;
             }
@@ -1013,56 +1165,114 @@ impl Scene for Editor {
         self.size = current_size;
 
         let new_aspect = current_size.width as f64 / current_size.height as f64;
-        if let Some(active_camera) = self.active_camera {
-            if let Ok(mut query) = Arc::get_mut(&mut self.world).unwrap().query_one::<&mut Camera>(active_camera) {
-                if let Some(camera) = query.get() {
-                    camera.aspect = new_aspect;
+
+        {
+            let active_cam = self.active_camera.lock();
+            if let Some(active_camera) = *active_cam {
+                let world = self.world.read();
+                if let Ok(mut query) = world.query_one::<&mut Camera>(active_camera) {
+                    if let Some(camera) = query.get() {
+                        camera.aspect = new_aspect;
+                    }
                 }
             }
+            
         }
 
-        for (_entity_id, (camera, _component, follow_target)) in self
-            .world
-            .query::<(&mut Camera, &CameraComponent, Option<&CameraFollowTarget>)>()
-            .iter()
-        {
-            if let Some(target) = follow_target {
-                for (_target_entity_id, (adopted, transform)) in
-                    self.world.query::<(&AdoptedEntity, &Transform)>().iter()
-                {
-                    if adopted.label() == &target.follow_target {
-                        let target_pos = transform.position;
-                        camera.eye = target_pos + target.offset;
-                        camera.target = target_pos;
-                        break;
+        let camera_follow_data: Vec<(Entity, String, glam::Vec3)> = {
+            let world = self.world.read();
+            world
+                .query::<(&Camera, &CameraComponent, Option<&CameraFollowTarget>)>()
+                .iter()
+                .filter_map(|(entity_id, (_, _, follow_target))| {
+                    follow_target.map(|target| {
+                        (
+                            entity_id,
+                            target.follow_target.clone(),
+                            target.offset.as_vec3()
+                        )
+                    })
+                })
+                .collect()
+        };
+        
+
+        for (camera_entity, target_label, offset) in camera_follow_data {
+            let target_position = {
+                let world = self.world.read();
+                world
+                    .query::<(&AdoptedEntity, &Transform)>()
+                    .iter()
+                    .find_map(|(_, (adopted, transform))| {
+                        if adopted.label() == &target_label {
+                            Some(transform.position)
+                        } else {
+                            None
+                        }
+                    })
+            };
+            
+
+            if let Some(pos) = target_position {
+                let world = self.world.read();
+                if let Ok(mut query) = world.query_one::<&mut Camera>(camera_entity) {
+                    if let Some(camera) = query.get() {
+                        camera.eye = pos + offset.as_dvec3();
+                        camera.target = pos;
                     }
                 }
             }
+            
         }
 
-        for (_entity_id, (camera, component)) in self
-            .world
-            .query::<(&mut Camera, &mut CameraComponent)>()
-            .iter()
         {
-            component.update(camera);
-            camera.update(graphics.shared.clone());
+            let world = self.world.read();
+            for (_entity_id, (camera, component)) in world
+                .query::<(&mut Camera, &mut CameraComponent)>()
+                .iter()
+            {
+                component.update(camera);
+                camera.update(graphics.shared.clone());
+            }
         }
+        
+        {
+            {
+                let mut world = self.world.write();
+                let query = world
+                    .query_mut::<(&mut AdoptedEntity, &Transform)>();
+                for (_, (entity, transform)) in query {
+                    entity.update(graphics.shared.clone(), transform);
+                }
+            }
+            
 
-        let query = Arc::get_mut(&mut self.world).unwrap().query_mut::<(&mut AdoptedEntity, &Transform)>();
-        for (_, (entity, transform)) in query {
-            entity.update(graphics.shared.clone(), transform);
+            {
+                let mut world = self.world.write();
+                let light_query =
+                    world
+                        .query_mut::<(&mut LightComponent, &Transform, &mut Light)>();
+                for (_, (light_component, transform, light)) in light_query {
+                    light.update(light_component, transform);
+                }
+            }
+            
         }
 
-        let light_query = Arc::get_mut(&mut self.world).unwrap()
-            .query_mut::<(&mut LightComponent, &Transform, &mut Light)>();
-        for (_, (light_component, transform, light)) in light_query {
-            light.update(light_component, transform);
+        {
+            let mut world = self.world.read();
+            self.light_manager.update(
+                graphics.shared.clone(),
+                &mut world,
+            );
         }
-
-        self.light_manager.update(graphics.shared.clone(), &Arc::get_mut(&mut self.world).unwrap());
         
-        crate::debug::show_dependency_progress_window(&graphics.shared.get_egui_context(), &mut self.dep_installer);
+
+        if self.dep_installer.is_installing {
+            self.dep_installer
+                .show_installation_window(&mut graphics.shared.get_egui_context());
+        }
+        self.dep_installer.update_progress();
     }
 
     async fn render<'a>(&mut self, graphics: &mut RenderContext<'a>) {
@@ -1077,73 +1287,105 @@ impl Scene for Editor {
         self.color = color.clone();
         self.size = graphics.shared.viewport_texture.size.clone();
         self.texture_id = Some(*graphics.shared.texture_id.clone());
-        self.show_ui(&graphics.shared.get_egui_context());
+        { self.show_ui(&graphics.shared.get_egui_context()).await; }
 
         self.window = Some(graphics.shared.window.clone());
         logging::render(&graphics.shared.get_egui_context());
         if let Some(pipeline) = &self.render_pipeline {
-            if let Some(active_camera) = self.active_camera {
-                if let Ok(mut query) = self.world.query_one::<&Camera>(active_camera) {
-                    if let Some(camera) = query.get() {
-                        let mut light_query = self.world.query::<(&Light, &LightComponent)>();
-                        let mut entity_query = self.world.query::<(&AdoptedEntity, &Transform)>();
-                        {
-                            let mut render_pass = graphics.clear_colour(color);
-
-                            if let Some(light_pipeline) = &self.light_manager.pipeline {
-                                render_pass.set_pipeline(light_pipeline);
-                                for (_, (light, component)) in light_query.iter() {
-                                    if component.enabled {
-                                        render_pass.set_vertex_buffer(
-                                            1,
-                                            light.instance_buffer.as_ref().unwrap().slice(..),
-                                        );
-                                        render_pass.draw_light_model(
-                                            light.model(),
-                                            camera.bind_group(),
-                                            light.bind_group(),
-                                        );
-                                    }
-                                }
-                            }
-
-                            let mut model_batches: HashMap<*const Model, Vec<InstanceRaw>> =
-                                HashMap::new();
-
-                            for (_, (entity, _)) in entity_query.iter() {
-                                let model_ptr = entity.model() as *const Model;
-                                let instance_raw = entity.instance.to_raw();
-                                model_batches
-                                    .entry(model_ptr)
-                                    .or_insert(Vec::new())
-                                    .push(instance_raw);
-                            }
-
-                            render_pass.set_pipeline(pipeline);
+            if let Some(active_camera) = *self.active_camera.lock() {
+                let cam = {
+                    let world = self.world.read();
+                    if let Ok(mut query) = world.query_one::<&Camera>(active_camera) {
+                        if let Some(camera) = query.get() {
+                            Some(camera.clone())
+                        } else {
+                            None
+                        }
+                    } else {
+                        None
+                    }
+                };
+                
+
+                if let Some(camera) = cam {
+                    let lights = {
+                        let world = self.world.read();
+                        let mut lights = Vec::new();
+                        let mut light_query = world.query::<(&Light, &LightComponent)>();
+                        for (_, (light, comp)) in light_query.iter() {
+                            lights.push((light.clone(), comp.clone()));
+                        }
+                        lights
+                    };
+                    
 
-                            for (model_ptr, instances) in model_batches {
-                                let model = unsafe { &*model_ptr };
+                    let entities = {
+                        let world = self.world.read();
+                        let mut entities = Vec::new();
+                        let mut entity_query = world.query::<(&AdoptedEntity, &Transform)>();
+                        for (_, (entity, transform)) in entity_query.iter() {
+                            entities.push((entity.clone(), transform.clone()));
+                        }
+                        entities
+                    };
+                    
 
-                                let instance_buffer = graphics.shared.device.create_buffer_init(
-                                    &wgpu::util::BufferInitDescriptor {
-                                        label: Some("Batched Instance Buffer"),
-                                        contents: bytemuck::cast_slice(&instances),
-                                        usage: wgpu::BufferUsages::VERTEX,
-                                    },
+                    {
+                        let mut render_pass = graphics.clear_colour(color);
+                        if let Some(light_pipeline) = &self.light_manager.pipeline {
+                            render_pass.set_pipeline(light_pipeline);
+                            for (light, _component) in &lights {
+                                render_pass.set_vertex_buffer(
+                                    1,
+                                    light.instance_buffer.as_ref().unwrap().slice(..),
                                 );
-
-                                render_pass.set_vertex_buffer(1, instance_buffer.slice(..));
-                                render_pass.draw_model_instanced(
-                                    model,
-                                    0..instances.len() as u32,
+                                render_pass.draw_light_model(
+                                    light.model(),
                                     camera.bind_group(),
-                                    self.light_manager.bind_group(),
+                                    light.bind_group(),
                                 );
                             }
                         }
+                        
+
+                        let mut model_batches: HashMap<*const Model, Vec<InstanceRaw>> =
+                            HashMap::new();
+                        for (entity, _) in &entities {
+                            let model_ptr = entity.model() as *const Model;
+                            let instance_raw = entity.instance.to_raw();
+                            model_batches
+                                .entry(model_ptr)
+                                .or_insert(Vec::new())
+                                .push(instance_raw);
+                        }
+
+                        render_pass.set_pipeline(pipeline);
+                        for (model_ptr, instances) in model_batches {
+                            let model = unsafe { &*model_ptr };
+                            let instance_buffer = graphics.shared.device.create_buffer_init(
+                                &wgpu::util::BufferInitDescriptor {
+                                    label: Some("Batched Instance Buffer"),
+                                    contents: bytemuck::cast_slice(&instances),
+                                    usage: wgpu::BufferUsages::VERTEX,
+                                },
+                            );
+                            render_pass.set_vertex_buffer(1, instance_buffer.slice(..));
+                            render_pass.draw_model_instanced(
+                                model,
+                                0..instances.len() as u32,
+                                camera.bind_group(),
+                                self.light_manager.bind_group(),
+                            );
+                        }
                     }
+                } else {
+                    log_once::error_once!("Camera returned None");
                 }
+            } else {
+                log_once::error_once!("No active camera found");
             }
+        } else {
+            log_once::error_once!("No render pipeline exists");
         }
     }
 
diff --git a/eucalyptus-editor/src/main.rs b/eucalyptus-editor/src/main.rs
index a32a3a6..a8fa5c0 100644
--- a/eucalyptus-editor/src/main.rs
+++ b/eucalyptus-editor/src/main.rs
@@ -136,6 +136,7 @@ async fn main() -> anyhow::Result<()> {
 
                 (scene_manager, input_manager)
             })
+            .await
             .unwrap();
         }
         _ => unreachable!(),
diff --git a/eucalyptus-editor/src/menu.rs b/eucalyptus-editor/src/menu.rs
index f378490..7caa31b 100644
--- a/eucalyptus-editor/src/menu.rs
+++ b/eucalyptus-editor/src/menu.rs
@@ -5,7 +5,9 @@ use std::{
 
 use anyhow::anyhow;
 use dropbear_engine::{
-    graphics::RenderContext, input::{Controller, Keyboard, Mouse}, scene::{Scene, SceneCommand}
+    graphics::RenderContext,
+    input::{Controller, Keyboard, Mouse},
+    scene::{Scene, SceneCommand},
 };
 use egui::{self, FontId, Frame, RichText};
 use egui_toast_fork::{ToastOptions, Toasts};
@@ -160,83 +162,90 @@ impl Scene for MainMenu {
             graphics.shared.window.inner_size().height as f32 - 100.0,
         );
         let egui_ctx = graphics.shared.get_egui_context();
-
+        let mut local_open_project = false;
         egui::CentralPanel::default()
-                .frame(Frame::new())
-                .show(&egui_ctx, |ui| {
-                    ui.vertical_centered(|ui| {
-                        ui.add_space(64.0);
-                        ui.label(RichText::new("Eucalyptus").font(FontId::proportional(32.0)));
-                        ui.add_space(40.0);
-
-                        let button_size = egui::vec2(300.0, 60.0);
-
-                        if ui
-                            .add_sized(button_size, egui::Button::new("New Project"))
-                            .clicked()
-                        {
-                            log::debug!("Creating new project");
-                            self.show_new_project = true;
-                        }
-                        ui.add_space(20.0);
-
-                        if ui
-                            .add_sized(button_size, egui::Button::new("Open Project"))
-                            .clicked()
-                        {
-                            log::debug!("Opening project");
-                            self.is_in_file_dialogue = true;
-                            if let Some(path) = rfd::FileDialog::new()
-                                .add_filter("Eucalyptus Configuration Files", &["eucp"])
-                                .pick_file()
-                            {
-                                match ProjectConfig::read_from(&path) {
-                                    Ok(config) => {
-                                        log::info!("Loaded project!");
-                                        let mut global = PROJECT.write();
-                                        *global = config;
-                                        // println!("Loaded config info: {:#?}", global);
-                                        self.scene_command =
-                                            SceneCommand::SwitchScene(String::from("editor"));
-                                    }
-                                    Err(e) => if e.to_string().contains("missing field") {
-                                        self.toast.add(egui_toast_fork::Toast {
-                                            kind: egui_toast_fork::ToastKind::Error,
-                                            text: format!("Your project version is not up to date with the current project version").into(),
-                                            options: ToastOptions::default()
-                                                .duration_in_seconds(10.0)
-                                                .show_progress(true),
-                                            ..Default::default()
-                                        });
-                                        log::error!("Failed to load project: {}", e);
-                                    }
-                                };
-                            } else {
-                                log::warn!("File dialog returned \"None\"");
-                            }
-                            self.is_in_file_dialogue = false;
-                        }
-                        ui.add_space(20.0);
+            .frame(Frame::new())
+            .show(&egui_ctx, |ui| {
+                ui.vertical_centered(|ui| {
+                    ui.add_space(64.0);
+                    ui.label(RichText::new("Eucalyptus").font(FontId::proportional(32.0)));
+                    ui.add_space(40.0);
 
-                        if ui
-                            .add_sized(button_size, egui::Button::new("Settings"))
-                            .clicked()
-                        {
-                            log::debug!("Settings (not implemented)");
-                        }
-                        ui.add_space(20.0);
+                    let button_size = egui::vec2(300.0, 60.0);
 
-                        if ui
-                            .add_sized(button_size, egui::Button::new("Quit"))
-                            .clicked()
-                        {
-                            self.scene_command = SceneCommand::Quit
-                        }
-                        ui.add_space(20.0);
-                    });
+                    if ui
+                        .add_sized(button_size, egui::Button::new("New Project"))
+                        .clicked()
+                    {
+                        log::debug!("Creating new project");
+                        self.show_new_project = true;
+                    }
+                    ui.add_space(20.0);
+
+                    if ui
+                        .add_sized(button_size, egui::Button::new("Open Project"))
+                        .clicked()
+                    {
+                        local_open_project = true;
+                    }
+                    ui.add_space(20.0);
+
+                    if ui
+                        .add_sized(button_size, egui::Button::new("Settings"))
+                        .clicked()
+                    {
+                        log::debug!("Settings (not implemented)");
+                    }
+                    ui.add_space(20.0);
+
+                    if ui
+                        .add_sized(button_size, egui::Button::new("Quit"))
+                        .clicked()
+                    {
+                        self.scene_command = SceneCommand::Quit
+                    }
+                    ui.add_space(20.0);
                 });
+            });
+
+        if local_open_project {
+            log::debug!("Opening project");
+            self.is_in_file_dialogue = true;
+            if let Some(path) = rfd::AsyncFileDialog::new()
+                .add_filter("Eucalyptus Configuration Files", &["eucp"])
+                .pick_file()
+                .await
+            {
+                match ProjectConfig::read_from(&path.into()) {
+                    Ok(config) => {
+                        log::info!("Loaded project!");
+                        let mut global = PROJECT.write();
+                        *global = config;
+                        // println!("Loaded config info: {:#?}", global);
+                        self.scene_command = SceneCommand::SwitchScene(String::from("editor"));
+                    }
+                    Err(e) => {
+                        if e.to_string().contains("missing field") {
+                            self.toast.add(egui_toast_fork::Toast {
+                            kind: egui_toast_fork::ToastKind::Error,
+                            text: format!("Your project version is not up to date with the current project version").into(),
+                            options: ToastOptions::default()
+                                .duration_in_seconds(10.0)
+                                .show_progress(true),
+                            ..Default::default()
+                        });
+                            log::error!("Failed to load project: {}", e);
+                        }
+                    }
+                };
+            } else {
+                log::warn!("File dialog returned \"None\"");
+            }
+            self.is_in_file_dialogue = false;
+        }
 
         let mut show_new_project = self.show_new_project;
+        let mut local_select_project = false;
         egui::Window::new("Create new project")
             .open(&mut show_new_project)
             .resizable(true)
@@ -260,16 +269,7 @@ impl Scene for MainMenu {
 
                     ui.add_space(5.0);
                     if ui.button("Choose Location").clicked() {
-                        self.is_in_file_dialogue = true;
-                        if let Some(path) = rfd::FileDialog::new()
-                            .set_title("Save Project")
-                            .set_file_name(&self.project_name)
-                            .pick_folder()
-                        {
-                            self.project_path = Some(path);
-                            log::debug!("Project will be saved at: {:?}", self.project_path);
-                        }
-                        self.is_in_file_dialogue = false;
+                        local_select_project = true;
                     }
 
                     let can_create = self.project_path.is_some() && !self.project_name.is_empty();
@@ -285,6 +285,20 @@ impl Scene for MainMenu {
             });
         self.show_new_project = show_new_project;
 
+        if local_select_project {
+            self.is_in_file_dialogue = true;
+            if let Some(path) = rfd::AsyncFileDialog::new()
+                .set_title("Save Project")
+                .set_file_name(&self.project_name)
+                .pick_folder()
+                .await
+            {
+                self.project_path = Some(path.into());
+                log::debug!("Project will be saved at: {:?}", self.project_path);
+            }
+            self.is_in_file_dialogue = false;
+        }
+
         if let Some(rx) = self.progress_rx.as_mut() {
             while let Ok(progress) = rx.try_recv() {
                 match progress {
diff --git a/redback-runtime b/redback-runtime
index ba32a23..5cb98c0 160000
--- a/redback-runtime
+++ b/redback-runtime
@@ -1 +1 @@
-Subproject commit ba32a2319d7b302c0d294311a9ad3135e9eb8503
+Subproject commit 5cb98c0d508c7f8fd7d6a268d101d6e0fde0f41f
diff --git a/src/dropbear.gleam b/src/dropbear.gleam
index e69de29..555e244 100644
--- a/src/dropbear.gleam
+++ b/src/dropbear.gleam
@@ -0,0 +1,3 @@
+/// Queries the attached entity. Returns a serialized string to be decoded. 
+@external(javascript, "dropbear", "queryAttachedEntity")
+fn raw_query_attached_entity() -> String
\ No newline at end of file
diff --git a/src/input.gleam b/src/input.gleam
index d6e411f..e69de29 100644
--- a/src/input.gleam
+++ b/src/input.gleam
@@ -1,2 +0,0 @@
-@external(javascript, "dropbear_input", "is_key_pressed")
-fn is_key_pressed(key_code: Int) -> Int
\ No newline at end of file
diff --git a/src/memory.gleam b/src/memory.gleam
deleted file mode 100644
index 2f65c7b..0000000
--- a/src/memory.gleam
+++ /dev/null
@@ -1 +0,0 @@
-//// Internal library for WASM memory sharing between the dropbear game engine. 
\ No newline at end of file
diff --git a/src/memory.js b/src/memory.js
deleted file mode 100644
index 9c81ea6..0000000
--- a/src/memory.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/// Javascript library for managing memory in WebAssembly for the dropbear engine Gleam interface. 
-
-class WasmMemoryManager {
-    constructor(memory) {
-        this.memory = memory;
-        this.nextFreeOffset = 1024;
-        this.allocations = new Map();
-    }
-
-    /// Fetches the new view of the memory after the memory is refreshed
-    getView() {
-        return new DataView(this.memory.buffer);
-    }
-}
\ No newline at end of file
diff --git a/ts/articles/page.md b/ts/articles/page.md
deleted file mode 100644
index e9168db..0000000
--- a/ts/articles/page.md
+++ /dev/null
@@ -1 +0,0 @@
-# Hello World
\ No newline at end of file