From 50bdb6098ad8a736e9c1faf8fe089670238eb4c3 Mon Sep 17 00:00:00 2001
From: NiseVoid <nisevoid@gmail.com>
Date: Thu, 9 Mar 2023 15:05:50 +0100
Subject: [PATCH] Update to bevy 0.10

---
 Cargo.toml                                    |   6 +-
 examples/bevy_scene.rs                        |  14 +--
 examples/conditional_widget.rs                |   4 +-
 examples/context.rs                           |   2 +-
 examples/main_menu.rs                         |   4 +-
 examples/quads.rs                             |   2 +-
 examples/render_target.rs                     |   3 +-
 examples/simple_state.rs                      |   2 +-
 examples/tabs/tab_button.rs                   |   4 +-
 examples/test_no_startup.rs                   |  14 +--
 examples/todo/input.rs                        |   2 +-
 examples/todo/items.rs                        |   2 +-
 examples/todo/todo.rs                         |   6 +-
 kayak_font/Cargo.toml                         |   5 +-
 kayak_font/src/bevy/mod.rs                    |   8 +-
 .../src/bevy/renderer/font_texture_cache.rs   |   4 +
 kayak_ui_macros/Cargo.toml                    |   1 -
 src/camera/camera.rs                          |  27 +----
 src/camera/mod.rs                             |   8 +-
 src/camera/ortho.rs                           |  17 +--
 src/context.rs                                |  22 ++--
 src/event.rs                                  |   8 +-
 src/event_dispatcher.rs                       |  53 +++++----
 src/input.rs                                  |  15 ++-
 src/layout_dispatcher.rs                      |   2 +-
 src/on_event.rs                               |  14 +--
 src/render/extract.rs                         |  35 ++++--
 src/render/mod.rs                             | 108 ++++++++----------
 src/render/ui_pass.rs                         |  11 +-
 src/render/unified/mod.rs                     |  19 +--
 src/render/unified/pipeline.rs                |   9 +-
 src/render/unified/shader.wgsl                |   2 +-
 src/render/unified/text.rs                    |   6 +-
 src/widgets/app.rs                            |  22 +---
 src/widgets/button.rs                         |   4 +-
 src/widgets/scroll/scroll_bar.rs              |   4 +-
 src/widgets/scroll/scroll_box.rs              |   4 +-
 src/widgets/text_box.rs                       |   4 +-
 src/widgets/window.rs                         |   6 +-
 src/window_size.rs                            |  30 +++--
 40 files changed, 258 insertions(+), 255 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index f39ff22..817f111 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,7 +7,6 @@ resolver = "2"
 authors = ["John Mitchell"]
 homepage = "https://github.com/StarArawn/kayak_ui"
 repository = "https://github.com/StarArawn/kayak_ui"
-license = "MIT OR Apache-2.0"
 license-file = "LICENSE"
 exclude = ["assets/*", "screenshots/*", "book"]
 
@@ -17,7 +16,7 @@ members = ["kayak_ui_macros", "kayak_font"]
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-bevy = { version = "0.9", default-features = false, features = ["bevy_ui"] }
+bevy = { version = "0.10", default-features = false, features = ["bevy_render", "bevy_asset", "bevy_winit", "bevy_core_pipeline"] }
 bytemuck = "1.12"
 dashmap = "5.4"
 kayak_font = { path = "./kayak_font", version = "0.2" }
@@ -32,7 +31,8 @@ instant = "0.1"
 
 [dev-dependencies]
 fastrand = "1.8"
-bevy-inspector-egui = "0.14"
+bevy-inspector-egui = "0.18"
+bevy = { version = "0.10", default-features = true }
 
 [[example]]
 name = "tabs"
diff --git a/examples/bevy_scene.rs b/examples/bevy_scene.rs
index bf8439b..ce16c36 100644
--- a/examples/bevy_scene.rs
+++ b/examples/bevy_scene.rs
@@ -1,6 +1,7 @@
 use bevy::{
     math::{Vec3Swizzles, Vec4Swizzles},
     prelude::*,
+    window::PrimaryWindow,
 };
 use kayak_ui::prelude::{widgets::*, *};
 
@@ -40,7 +41,7 @@ fn set_active_tile_target(
     cursor: Res<Input<MouseButton>>,
     event_context: Query<&EventDispatcher, With<GameUI>>,
     camera_transform: Query<&GlobalTransform, With<WorldCamera>>,
-    windows: Res<Windows>,
+    window: Query<&Window, With<PrimaryWindow>>,
 ) {
     if !cursor.just_pressed(MouseButton::Left) {
         // Only run this system when the mouse button is clicked
@@ -62,7 +63,7 @@ fn set_active_tile_target(
     // }
     // ```
 
-    let world_pos = cursor_to_world(&windows, camera_transform.single());
+    let world_pos = cursor_to_world(window.single(), camera_transform.single());
     let tile_pos = world_to_tile(world_pos);
     let mut tile = tile.single_mut();
     tile.target = tile_pos;
@@ -83,11 +84,11 @@ fn move_ghost_tile(
     mut tile: Query<&mut Transform, With<GhostTile>>,
     mut cursor_moved: EventReader<CursorMoved>,
     camera_transform: Query<&GlobalTransform, With<WorldCamera>>,
-    windows: Res<Windows>,
+    window: Query<&Window, With<PrimaryWindow>>,
 ) {
     for _ in cursor_moved.iter() {
         if !event_context.single().contains_cursor() {
-            let world_pos = cursor_to_world(&windows, camera_transform.single());
+            let world_pos = cursor_to_world(window.single(), camera_transform.single());
             let tile_pos = world_to_tile(world_pos);
             let mut ghost = tile.single_mut();
             ghost.translation.x = tile_pos.x;
@@ -139,8 +140,7 @@ fn world_setup(mut commands: Commands, active_color: Res<ActiveColor>) {
 }
 
 /// Get the world position of the cursor in 2D space
-fn cursor_to_world(windows: &Windows, camera_transform: &GlobalTransform) -> Vec2 {
-    let window = windows.get_primary().unwrap();
+fn cursor_to_world(window: &Window, camera_transform: &GlobalTransform) -> Vec2 {
     let size = Vec2::new(window.width(), window.height());
 
     let mut pos = window.cursor_position().unwrap_or_default();
@@ -181,7 +181,7 @@ fn startup(
         move |In((event_dispatcher_context, _, event, _)): In<(
             EventDispatcherContext,
             WidgetState,
-            Event,
+            KEvent,
             Entity,
         )>,
               mut active_color: ResMut<ActiveColor>| {
diff --git a/examples/conditional_widget.rs b/examples/conditional_widget.rs
index 1791f08..a3dd07f 100644
--- a/examples/conditional_widget.rs
+++ b/examples/conditional_widget.rs
@@ -48,7 +48,7 @@ fn my_widget_render(
                         text: "Show Window".into(),
                     }}
                     on_event={OnEvent::new(
-                        move |In((event_dispatcher_context, _, mut event, _entity)): In<(EventDispatcherContext, WidgetState, Event, Entity)>,
+                        move |In((event_dispatcher_context, _, mut event, _entity)): In<(EventDispatcherContext, WidgetState, KEvent, Entity)>,
                             mut query: Query<&mut MyWidgetState>| {
                             event.prevent_default();
                             event.stop_propagation();
@@ -78,7 +78,7 @@ fn my_widget_render(
                             <KButtonBundle
                                 button={KButton { text: "Hide Window".into(), ..Default::default() }}
                                 on_event={OnEvent::new(
-                                    move |In((event_dispatcher_context, _, mut event, _entity)): In<(EventDispatcherContext, WidgetState, Event, Entity)>,
+                                    move |In((event_dispatcher_context, _, mut event, _entity)): In<(EventDispatcherContext, WidgetState, KEvent, Entity)>,
                                         mut query: Query<&mut MyWidgetState>| {
                                         match event.event_type {
                                             EventType::Click(..) => {
diff --git a/examples/context.rs b/examples/context.rs
index a712519..0b8cac2 100644
--- a/examples/context.rs
+++ b/examples/context.rs
@@ -104,7 +104,7 @@ fn update_theme_button(
                             move |In((event_dispatcher_context, _, event, _entity)): In<(
                                 EventDispatcherContext,
                                 WidgetState,
-                                Event,
+                                KEvent,
                                 Entity,
                             )>,
                             query: Query<&ThemeButton>,
diff --git a/examples/main_menu.rs b/examples/main_menu.rs
index 40949d6..d4dcb75 100644
--- a/examples/main_menu.rs
+++ b/examples/main_menu.rs
@@ -49,7 +49,7 @@ fn menu_button_render(
         move |In((event_dispatcher_context, _, mut event, _entity)): In<(
             EventDispatcherContext,
             WidgetState,
-            Event,
+            KEvent,
             Entity,
         )>,
               mut query: Query<&mut ButtonState>| {
@@ -151,7 +151,7 @@ fn startup(
         move |In((event_dispatcher_context, _, event, _entity)): In<(
             EventDispatcherContext,
             WidgetState,
-            Event,
+            KEvent,
             Entity,
         )>,
               mut exit: EventWriter<AppExit>| {
diff --git a/examples/quads.rs b/examples/quads.rs
index 33216d6..431876e 100644
--- a/examples/quads.rs
+++ b/examples/quads.rs
@@ -39,7 +39,7 @@ fn my_quad_update(
             move |In((event_dispatcher_context, _, mut event, entity)): In<(
                 EventDispatcherContext,
                 WidgetState,
-                Event,
+                KEvent,
                 Entity,
             )>,
                   mut query: Query<(&mut KStyle, &MyQuad)>| {
diff --git a/examples/render_target.rs b/examples/render_target.rs
index d17bb3b..284771a 100644
--- a/examples/render_target.rs
+++ b/examples/render_target.rs
@@ -41,6 +41,7 @@ fn startup(
             label: None,
             size,
             dimension: TextureDimension::D2,
+            view_formats: &[TextureFormat::Bgra8UnormSrgb],
             format: TextureFormat::Bgra8UnormSrgb,
             mip_level_count: 1,
             sample_count: 1,
@@ -84,7 +85,7 @@ fn startup(
 
     commands.spawn(UICameraBundle {
         camera: Camera {
-            priority: -1,
+            order: -1,
             target: RenderTarget::Image(image_handle.clone()),
             ..Camera::default()
         },
diff --git a/examples/simple_state.rs b/examples/simple_state.rs
index 2e27896..4b1b64c 100644
--- a/examples/simple_state.rs
+++ b/examples/simple_state.rs
@@ -57,7 +57,7 @@ fn current_count_render(
                         ..Default::default()
                     }}
                     on_event={OnEvent::new(
-                        move |In((event_dispatcher_context, _, mut event, _entity)): In<(EventDispatcherContext, WidgetState, Event, Entity)>,
+                        move |In((event_dispatcher_context, _, mut event, _entity)): In<(EventDispatcherContext, WidgetState, KEvent, Entity)>,
                             mut query: Query<&mut CurrentCountState>| {
                             match event.event_type {
                                 EventType::Click(..) => {
diff --git a/examples/tabs/tab_button.rs b/examples/tabs/tab_button.rs
index 2741684..811a515 100644
--- a/examples/tabs/tab_button.rs
+++ b/examples/tabs/tab_button.rs
@@ -1,7 +1,7 @@
 use bevy::prelude::{Bundle, Color, Commands, Component, Entity, In, Query};
 use kayak_ui::{
     prelude::{
-        rsx, widgets::KButtonBundle, Corner, Event, EventDispatcherContext, EventType, KStyle,
+        rsx, widgets::KButtonBundle, Corner, EventDispatcherContext, EventType, KEvent, KStyle,
         KayakWidgetContext, OnEvent, StyleProp, Units, Widget, WidgetName, WidgetState,
     },
     widgets::KButton,
@@ -57,7 +57,7 @@ pub fn tab_button_render(
                 move |In((event_dispatcher_context, _, event, _entity)): In<(
                     EventDispatcherContext,
                     WidgetState,
-                    Event,
+                    KEvent,
                     Entity,
                 )>,
                       mut query: Query<&mut TabContext>| {
diff --git a/examples/test_no_startup.rs b/examples/test_no_startup.rs
index 060081e..4f59b26 100644
--- a/examples/test_no_startup.rs
+++ b/examples/test_no_startup.rs
@@ -1,15 +1,15 @@
 use bevy::prelude::*;
 use kayak_ui::prelude::{widgets::*, *};
 
-#[derive(Default, Clone, Copy, PartialEq, Hash, Eq, Debug)]
+#[derive(Default, Clone, Copy, PartialEq, Hash, Eq, Debug, States)]
 pub enum GameState {
     #[default]
     First,
     Second,
 }
 
-fn first_sys(mut state: ResMut<State<GameState>>) {
-    state.overwrite_replace(GameState::Second).unwrap();
+fn first_sys(mut state: ResMut<NextState<GameState>>) {
+    state.set(GameState::Second);
 }
 
 fn second_sys(
@@ -42,8 +42,8 @@ fn main() {
         .add_plugins(DefaultPlugins)
         .add_plugin(KayakContextPlugin)
         .add_plugin(KayakWidgets)
-        .add_state(GameState::First)
-        .add_system_set(SystemSet::on_enter(GameState::First).with_system(first_sys))
-        .add_system_set(SystemSet::on_enter(GameState::Second).with_system(second_sys))
-        .run()
+        .add_state::<GameState>()
+        .add_system(first_sys.in_schedule(OnEnter(GameState::First)))
+        .add_system(second_sys.in_schedule(OnEnter(GameState::Second)))
+        .run();
 }
diff --git a/examples/todo/input.rs b/examples/todo/input.rs
index 38b2da7..37017d9 100644
--- a/examples/todo/input.rs
+++ b/examples/todo/input.rs
@@ -52,7 +52,7 @@ pub fn render_todo_input(
         move |In((event_dispatcher_context, _, event, _)): In<(
             EventDispatcherContext,
             WidgetState,
-            Event,
+            KEvent,
             Entity,
         )>,
               mut todo_list: ResMut<TodoList>| {
diff --git a/examples/todo/items.rs b/examples/todo/items.rs
index 8892ece..d7adac9 100644
--- a/examples/todo/items.rs
+++ b/examples/todo/items.rs
@@ -50,7 +50,7 @@ pub fn render_todo_items(
                     move |In((event_dispatcher_context, _, event, _)): In<(
                         EventDispatcherContext,
                         WidgetState,
-                        Event,
+                        KEvent,
                         Entity,
                     )>,
                         mut todo_list: ResMut<TodoList>,| {
diff --git a/examples/todo/todo.rs b/examples/todo/todo.rs
index 4f62b88..2dc0a11 100644
--- a/examples/todo/todo.rs
+++ b/examples/todo/todo.rs
@@ -1,5 +1,5 @@
 use bevy::prelude::*;
-use bevy_inspector_egui::WorldInspectorPlugin;
+use bevy_inspector_egui::quick::WorldInspectorPlugin;
 use kayak_ui::prelude::{widgets::*, *};
 
 mod input;
@@ -106,10 +106,10 @@ fn main() {
     App::new()
         .insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0)))
         .add_plugins(DefaultPlugins)
-        .add_plugin(WorldInspectorPlugin::new())
+        .add_plugin(WorldInspectorPlugin::default())
         .add_plugin(KayakContextPlugin)
         .add_plugin(KayakWidgets)
-        .insert_non_send_resource(TodoList::new())
+        .insert_resource(TodoList::new())
         .add_startup_system(startup)
         .run()
 }
diff --git a/kayak_font/Cargo.toml b/kayak_font/Cargo.toml
index f219c8f..0802617 100644
--- a/kayak_font/Cargo.toml
+++ b/kayak_font/Cargo.toml
@@ -7,7 +7,6 @@ resolver = "2"
 authors = ["John Mitchell"]
 homepage = "https://github.com/StarArawn/kayak_ui"
 repository = "https://github.com/StarArawn/kayak_ui"
-license = "MIT OR Apache-2.0"
 license-file = "../LICENSE"
 exclude = ["assets/*"]
 
@@ -28,8 +27,8 @@ image = "0.24"
 # Provides UAX #14 line break segmentation
 xi-unicode = "0.3"
 
-bevy = { version = "0.9", optional = true, default-features = false, features = ["bevy_asset", "bevy_render", "bevy_core_pipeline"] }
+bevy = { version = "0.10", optional = true, default-features = false, features = ["bevy_asset", "bevy_render", "bevy_core_pipeline"] }
 
 [dev-dependencies]
-bevy = { version = "0.9" }
+bevy = { version = "0.10" }
 bytemuck = "1.12.0"
diff --git a/kayak_font/src/bevy/mod.rs b/kayak_font/src/bevy/mod.rs
index d214010..97da832 100644
--- a/kayak_font/src/bevy/mod.rs
+++ b/kayak_font/src/bevy/mod.rs
@@ -11,8 +11,8 @@ mod loader;
 mod renderer;
 
 mod plugin {
-    use bevy::prelude::{AddAsset, Plugin};
-    use bevy::render::{RenderApp, RenderStage};
+    use bevy::prelude::{AddAsset, IntoSystemAppConfig, IntoSystemConfig, Plugin};
+    use bevy::render::{ExtractSchedule, RenderApp, RenderSet};
 
     use crate::bevy::font_texture::init_font_texture;
     use crate::KayakFont;
@@ -32,8 +32,8 @@ mod plugin {
             render_app
                 .init_resource::<FontTextureCache>()
                 .init_resource::<ExtractedFonts>()
-                .add_system_to_stage(RenderStage::Extract, extract_fonts)
-                .add_system_to_stage(RenderStage::Prepare, prepare_fonts);
+                .add_system(extract_fonts.in_schedule(ExtractSchedule))
+                .add_system(prepare_fonts.in_set(RenderSet::Prepare));
         }
     }
 }
diff --git a/kayak_font/src/bevy/renderer/font_texture_cache.rs b/kayak_font/src/bevy/renderer/font_texture_cache.rs
index ec1baec..eb7e153 100644
--- a/kayak_font/src/bevy/renderer/font_texture_cache.rs
+++ b/kayak_font/src/bevy/renderer/font_texture_cache.rs
@@ -126,6 +126,7 @@ impl FontTextureCache {
             mip_level_count: 1,
             sample_count: 1,
             dimension: TextureDimension::D2,
+            view_formats: &[format],
             format,
             usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
         };
@@ -163,6 +164,7 @@ impl FontTextureCache {
             texture,
             sampler,
             texture_view,
+            mip_level_count: 1,
             size: Vec2 {
                 x: size.0 as f32,
                 y: size.1 as f32,
@@ -184,6 +186,7 @@ impl FontTextureCache {
             mip_level_count: 1,
             sample_count: 1,
             dimension: TextureDimension::D2,
+            view_formats: &[TextureFormat::Rgba8Unorm],
             format: TextureFormat::Rgba8Unorm,
             usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
         };
@@ -208,6 +211,7 @@ impl FontTextureCache {
             texture,
             sampler,
             texture_view,
+            mip_level_count: 1,
             size: Vec2 { x: 1.0, y: 1.0 },
             texture_format: TextureFormat::Rgba8Unorm,
         };
diff --git a/kayak_ui_macros/Cargo.toml b/kayak_ui_macros/Cargo.toml
index 9be77cd..155a45f 100644
--- a/kayak_ui_macros/Cargo.toml
+++ b/kayak_ui_macros/Cargo.toml
@@ -7,7 +7,6 @@ resolver = "2"
 authors = ["John Mitchell"]
 homepage = "https://github.com/StarArawn/kayak_ui"
 repository = "https://github.com/StarArawn/kayak_ui"
-license = "MIT OR Apache-2.0"
 license-file = "../LICENSE"
 
 [lib]
diff --git a/src/camera/camera.rs b/src/camera/camera.rs
index f432ace..c9ca4a8 100644
--- a/src/camera/camera.rs
+++ b/src/camera/camera.rs
@@ -1,9 +1,8 @@
 use bevy::{
     core_pipeline::clear_color::ClearColorConfig,
-    ecs::query::QueryItem,
-    prelude::{Bundle, Component, GlobalTransform, Transform, With},
+    prelude::{Bundle, Component, GlobalTransform, Transform, Vec2},
     render::{
-        camera::{Camera, CameraProjection, CameraRenderGraph, WindowOrigin},
+        camera::{Camera, CameraProjection, CameraRenderGraph},
         extract_component::ExtractComponent,
         primitives::Frustum,
         view::VisibleEntities,
@@ -15,20 +14,11 @@ use crate::{context::KayakRootContext, event_dispatcher::EventDispatcher};
 use super::ortho::UIOrthographicProjection;
 
 /// Kayak UI's default UI camera.
-#[derive(Component, Clone, Default)]
+#[derive(Component, ExtractComponent, Clone, Default)]
 pub struct CameraUIKayak {
     pub clear_color: ClearColorConfig,
 }
 
-impl ExtractComponent for CameraUIKayak {
-    type Query = &'static Self;
-    type Filter = With<Camera>;
-
-    fn extract_component(item: QueryItem<Self::Query>) -> Self {
-        item.clone()
-    }
-}
-
 /// Kayak UI's default UI camera bundle.
 #[derive(Bundle)]
 pub struct UICameraBundle {
@@ -60,7 +50,7 @@ impl UICameraBundle {
 
         let orthographic_projection = UIOrthographicProjection {
             far,
-            window_origin: WindowOrigin::BottomLeft,
+            window_origin: Vec2::new(0.0, 0.0),
             ..Default::default()
         };
 
@@ -68,15 +58,10 @@ impl UICameraBundle {
 
         let view_projection =
             orthographic_projection.get_projection_matrix() * transform.compute_matrix().inverse();
-        let frustum = Frustum::from_view_projection(
-            &view_projection,
-            &transform.translation,
-            &transform.back(),
-            orthographic_projection.far(),
-        );
+        let frustum = Frustum::from_view_projection(&view_projection);
         UICameraBundle {
             camera: Camera {
-                priority: isize::MAX - 1,
+                order: isize::MAX - 1,
                 ..Default::default()
             },
             camera_render_graph: CameraRenderGraph::new(bevy::core_pipeline::core_2d::graph::NAME),
diff --git a/src/camera/mod.rs b/src/camera/mod.rs
index 60e86c3..9751b18 100644
--- a/src/camera/mod.rs
+++ b/src/camera/mod.rs
@@ -1,5 +1,5 @@
 use bevy::{
-    prelude::{CoreStage, Plugin},
+    prelude::{CoreSet, IntoSystemConfig, Plugin},
     render::{camera::CameraProjectionPlugin, extract_component::ExtractComponentPlugin},
 };
 
@@ -13,9 +13,9 @@ pub struct KayakUICameraPlugin;
 
 impl Plugin for KayakUICameraPlugin {
     fn build(&self, app: &mut bevy::prelude::App) {
-        app.add_system_to_stage(
-            CoreStage::PostUpdate,
-            bevy::render::camera::camera_system::<UIOrthographicProjection>,
+        app.add_system(
+            bevy::render::camera::camera_system::<UIOrthographicProjection>
+                .in_base_set(CoreSet::PostUpdate),
         )
         .add_plugin(CameraProjectionPlugin::<UIOrthographicProjection>::default())
         .add_plugin(ExtractComponentPlugin::<CameraUIKayak>::default());
diff --git a/src/camera/ortho.rs b/src/camera/ortho.rs
index bb7a800..cd6d024 100644
--- a/src/camera/ortho.rs
+++ b/src/camera/ortho.rs
@@ -1,9 +1,9 @@
 use bevy::ecs::reflect::ReflectComponent;
-use bevy::prelude::Component;
+use bevy::prelude::{Component, Vec2};
 use bevy::{
     math::Mat4,
     reflect::Reflect,
-    render::camera::{CameraProjection, ScalingMode, WindowOrigin},
+    render::camera::{CameraProjection, ScalingMode},
 };
 
 /// Kayak UI's default orthographic projection matrix
@@ -19,7 +19,7 @@ pub struct UIOrthographicProjection {
     pub top: f32,
     pub near: f32,
     pub far: f32,
-    pub window_origin: WindowOrigin,
+    pub window_origin: Vec2,
     pub scaling_mode: ScalingMode,
     pub scale: f32,
 }
@@ -39,8 +39,11 @@ impl CameraProjection for UIOrthographicProjection {
     }
 
     fn update(&mut self, width: f32, height: f32) {
-        match (&self.scaling_mode, &self.window_origin) {
-            (ScalingMode::WindowSize, WindowOrigin::BottomLeft) => {
+        match &self.scaling_mode {
+            ScalingMode::WindowSize(scale) => {
+                if *scale != 1.0 || self.window_origin != Vec2::ZERO {
+                    return;
+                }
                 self.left = 0.0;
                 self.right = width;
                 self.top = 0.0;
@@ -64,8 +67,8 @@ impl Default for UIOrthographicProjection {
             top: 1.0,
             near: 0.0,
             far: 1000.0,
-            window_origin: WindowOrigin::Center,
-            scaling_mode: ScalingMode::WindowSize,
+            window_origin: Vec2::new(0.5, 0.5),
+            scaling_mode: ScalingMode::WindowSize(1.0),
             scale: 1.0,
         }
     }
diff --git a/src/context.rs b/src/context.rs
index ac9b8b8..1622952 100644
--- a/src/context.rs
+++ b/src/context.rs
@@ -4,6 +4,7 @@ use bevy::{
     ecs::{event::ManualEventReader, system::CommandQueue},
     prelude::*,
     utils::{HashMap, HashSet},
+    window::PrimaryWindow,
 };
 use morphorm::Hierarchy;
 
@@ -18,7 +19,7 @@ use crate::{
     input::query_world,
     layout::{LayoutCache, Rect},
     layout_dispatcher::LayoutEventDispatcher,
-    node::{DirtyNode, WrappedIndex},
+    node::{DirtyNode, Node, WrappedIndex},
     prelude::KayakWidgetContext,
     render_primitive::RenderPrimitive,
     styles::{
@@ -990,9 +991,13 @@ impl Plugin for KayakContextPlugin {
             .add_plugin(crate::camera::KayakUICameraPlugin)
             .add_plugin(crate::render::BevyKayakUIRenderPlugin)
             .register_type::<Node>()
-            .add_system_to_stage(CoreStage::Update, crate::input::process_events)
-            .add_system_to_stage(CoreStage::PostUpdate, update_widgets_sys.at_start())
-            .add_system_to_stage(CoreStage::PostUpdate, calculate_ui.at_end())
+            .add_system(crate::input::process_events.in_base_set(CoreSet::Update))
+            .add_system(update_widgets_sys.in_base_set(CoreSet::PostUpdate))
+            .add_system(
+                calculate_ui
+                    .after(update_widgets_sys)
+                    .in_base_set(CoreSet::PostUpdate),
+            )
             .add_system(crate::window_size::update_window_size);
 
         // Register reflection types.
@@ -1061,10 +1066,11 @@ fn calculate_ui(world: &mut World) {
                 }
             }
 
-            if let Some(ref mut windows) = world.get_resource_mut::<Windows>() {
-                if let Some(window) = windows.get_primary_mut() {
-                    window.set_cursor_icon(context.current_cursor);
-                }
+            if let Ok(mut window) = world
+                .query_filtered::<&mut Window, With<PrimaryWindow>>()
+                .get_single_mut(world)
+            {
+                window.cursor.icon = context.current_cursor;
             }
         }
 
diff --git a/src/event.rs b/src/event.rs
index 7d24367..f8bf74e 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -8,7 +8,7 @@ use crate::{
 
 /// An event type sent to widgets
 #[derive(Clone)]
-pub struct Event {
+pub struct KEvent {
     /// The node targeted by this event
     pub target: Entity,
     /// The current target of this event
@@ -23,7 +23,7 @@ pub struct Event {
     pub(crate) on_change_systems: Vec<OnChange>,
 }
 
-impl PartialEq for Event {
+impl PartialEq for KEvent {
     fn eq(&self, other: &Self) -> bool {
         self.target == other.target
             && self.current_target == other.current_target
@@ -33,7 +33,7 @@ impl PartialEq for Event {
     }
 }
 
-impl Default for Event {
+impl Default for KEvent {
     fn default() -> Self {
         Self {
             target: Entity::from_raw(0),
@@ -46,7 +46,7 @@ impl Default for Event {
     }
 }
 
-impl Event {
+impl KEvent {
     /// Create a new event
     ///
     /// This is the preferred method for creating an event as it automatically sets up
diff --git a/src/event_dispatcher.rs b/src/event_dispatcher.rs
index e0750a8..fe7dc52 100644
--- a/src/event_dispatcher.rs
+++ b/src/event_dispatcher.rs
@@ -6,7 +6,7 @@ use bevy::{
 use crate::{
     context::KayakRootContext,
     cursor::{CursorEvent, PointerEvents, ScrollEvent, ScrollUnit},
-    event::{Event, EventType},
+    event::{EventType, KEvent},
     focus_tree::FocusTree,
     input_event::{InputEvent, InputEventCategory},
     keyboard_event::{KeyboardEvent, KeyboardModifiers},
@@ -185,21 +185,21 @@ impl EventDispatcher {
         self.dispatch_events(events, context, world);
     }
 
-    /// Dispatch an [Event](crate::Event)
+    /// Dispatch an [KEvent](crate::KEvent)
     #[allow(dead_code)]
     pub fn dispatch_event(
         &mut self,
-        event: Event,
+        event: KEvent,
         context: &mut KayakRootContext,
         world: &mut World,
     ) {
         self.dispatch_events(vec![event], context, world);
     }
 
-    /// Dispatch a set of [Events](crate::Event)
+    /// Dispatch a set of [KEvents](crate::KEvent)
     pub fn dispatch_events(
         &mut self,
-        events: Vec<Event>,
+        events: Vec<KEvent>,
         context: &mut KayakRootContext,
         world: &mut World,
     ) {
@@ -211,7 +211,7 @@ impl EventDispatcher {
                 // Create a copy of the event, specific for this node
                 // This is to make sure unauthorized changes to the event are not propagated
                 // (e.g., changing the event type, removing the target, etc.)
-                let mut node_event = Event {
+                let mut node_event = KEvent {
                     current_target: index.0,
                     ..event.clone()
                 };
@@ -221,7 +221,7 @@ impl EventDispatcher {
 
                 // --- Call Event --- //
                 if let Some(mut entity) = world.get_entity_mut(index.0) {
-                    if let Some(mut on_event) = entity.remove::<OnEvent>() {
+                    if let Some(mut on_event) = entity.take::<OnEvent>() {
                         let mut event_dispatcher_context = EventDispatcherContext {
                             cursor_capture: self.cursor_capture,
                         };
@@ -304,14 +304,14 @@ impl EventDispatcher {
         self.previous_events = next_events;
     }
 
-    /// Generates a stream of [Events](crate::Event) from a set of [InputEvents](crate::InputEvent)
+    /// Generates a stream of [KEvents](crate::KEvent) from a set of [InputEvents](crate::InputEvent)
     fn build_event_stream(
         &mut self,
         input_events: &[InputEvent],
         context: &mut KayakRootContext,
         world: &mut World,
-    ) -> Vec<Event> {
-        let mut event_stream = Vec::<Event>::new();
+    ) -> Vec<KEvent> {
+        let mut event_stream = Vec::<KEvent>::new();
         let mut states: HashMap<EventType, EventState> = HashMap::new();
 
         if let Ok(node_tree) = context.tree.try_read() {
@@ -451,7 +451,7 @@ impl EventDispatcher {
                 // These events are ones that require a specific target and need the tree to be evaluated before selecting the best match
                 for (event_type, state) in states {
                     if let Some(node) = state.best_match {
-                        event_stream.push(Event::new(node.0, event_type));
+                        event_stream.push(KEvent::new(node.0, event_type));
 
                         match event_type {
                             EventType::Focus => {
@@ -459,7 +459,7 @@ impl EventDispatcher {
                                 if let Some(current_focus) = focus_tree.current() {
                                     if current_focus != node {
                                         event_stream
-                                            .push(Event::new(current_focus.0, EventType::Blur));
+                                            .push(KEvent::new(current_focus.0, EventType::Blur));
                                     }
                                 }
                                 focus_tree.focus(node);
@@ -476,7 +476,7 @@ impl EventDispatcher {
                 if !had_focus_event && input_events.contains(&InputEvent::MouseLeftPress) {
                     // A mouse press didn't contain a focus event -> blur
                     if let Some(current_focus) = focus_tree.current() {
-                        event_stream.push(Event::new(current_focus.0, EventType::Blur));
+                        event_stream.push(KEvent::new(current_focus.0, EventType::Blur));
                         focus_tree.blur();
                     }
                 }
@@ -513,7 +513,7 @@ impl EventDispatcher {
     /// * `widget_manager`: The widget manager
     /// * `ignore_layout`: Whether to ignore layout (useful for handling captured events)
     ///
-    /// returns: Vec<Event>
+    /// returns: Vec<KEvent>
     fn process_pointer_events(
         &mut self,
         input_event: &InputEvent,
@@ -522,8 +522,8 @@ impl EventDispatcher {
         world: &mut World,
         context: &KayakRootContext,
         ignore_layout: bool,
-    ) -> Vec<Event> {
-        let mut event_stream = Vec::<Event>::new();
+    ) -> Vec<KEvent> {
+        let mut event_stream = Vec::<KEvent>::new();
         let (node, depth) = tree_node;
 
         // let widget_name = world.entity(node.0).get::<WidgetName>();
@@ -539,7 +539,7 @@ impl EventDispatcher {
                         if was_contained {
                             // Mouse out should fire even when
                             event_stream
-                                .push(Event::new(node.0, EventType::MouseOut(cursor_event)));
+                                .push(KEvent::new(node.0, EventType::MouseOut(cursor_event)));
                             // Self::update_state(
                             //     states,
                             //     (node, depth),
@@ -688,12 +688,12 @@ impl EventDispatcher {
         input_event: &InputEvent,
         _states: &mut HashMap<EventType, EventState>,
         focus_tree: &FocusTree,
-    ) -> Vec<Event> {
+    ) -> Vec<KEvent> {
         let mut event_stream = Vec::new();
         if let Some(current_focus) = focus_tree.current() {
             match input_event {
                 InputEvent::CharEvent { c } => {
-                    event_stream.push(Event::new(current_focus.0, EventType::CharInput { c: *c }))
+                    event_stream.push(KEvent::new(current_focus.0, EventType::CharInput { c: *c }))
                 }
                 InputEvent::Keyboard { key, is_pressed } => {
                     // === Modifers === //
@@ -715,12 +715,12 @@ impl EventDispatcher {
 
                     // === Event === //
                     if *is_pressed {
-                        event_stream.push(Event::new(
+                        event_stream.push(KEvent::new(
                             current_focus.0,
                             EventType::KeyDown(KeyboardEvent::new(*key, self.keyboard_modifiers)),
                         ))
                     } else {
-                        event_stream.push(Event::new(
+                        event_stream.push(KEvent::new(
                             current_focus.0,
                             EventType::KeyUp(KeyboardEvent::new(*key, self.keyboard_modifiers)),
                         ))
@@ -789,7 +789,12 @@ impl EventDispatcher {
     }
 
     /// Executes default actions for events
-    fn execute_default(&mut self, event: Event, context: &mut KayakRootContext, world: &mut World) {
+    fn execute_default(
+        &mut self,
+        event: KEvent,
+        context: &mut KayakRootContext,
+        world: &mut World,
+    ) {
         match event.event_type {
             EventType::KeyDown(evt) => match evt.key() {
                 KeyCode::Tab => {
@@ -808,10 +813,10 @@ impl EventDispatcher {
                         };
 
                     if let Some(index) = index {
-                        let mut events = vec![Event::new(index.0, EventType::Focus)];
+                        let mut events = vec![KEvent::new(index.0, EventType::Focus)];
                         if let Some(current_focus) = current_focus {
                             if current_focus != index {
-                                events.push(Event::new(current_focus.0, EventType::Blur));
+                                events.push(KEvent::new(current_focus.0, EventType::Blur));
                             }
                         }
                         if let Ok(mut focus_tree) = context.focus_tree.try_write() {
diff --git a/src/input.rs b/src/input.rs
index c798500..d7adc3e 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -5,6 +5,7 @@ use bevy::{
         ButtonState,
     },
     prelude::*,
+    window::PrimaryWindow,
 };
 
 use crate::{
@@ -14,13 +15,11 @@ use crate::{
 };
 
 pub(crate) fn process_events(world: &mut World) {
-    let window_size = if let Some(windows) = world.get_resource::<Windows>() {
-        if let Some(window) = windows.get_primary() {
-            Vec2::new(window.width(), window.height())
-        } else {
-            log::warn!("Couldn't find primiary window!");
-            return;
-        }
+    let window_size = if let Ok(window) = world
+        .query_filtered::<&Window, With<PrimaryWindow>>()
+        .get_single(&world)
+    {
+        Vec2::new(window.width(), window.height())
     } else {
         log::warn!("Couldn't find primiary window!");
         return;
@@ -133,7 +132,7 @@ pub(crate) fn query_world<T: bevy::ecs::system::SystemParam + 'static, F, R>(
     world: &mut World,
 ) -> R
 where
-    F: FnOnce(<T::Fetch as bevy::ecs::system::SystemParamFetch<'_, '_>>::Item) -> R,
+    F: FnOnce(<T as bevy::ecs::system::SystemParam>::Item<'_, '_>) -> R,
 {
     let mut system_state = bevy::ecs::system::SystemState::<T>::new(world);
     let r = {
diff --git a/src/layout_dispatcher.rs b/src/layout_dispatcher.rs
index 913c7ea..fc4571b 100644
--- a/src/layout_dispatcher.rs
+++ b/src/layout_dispatcher.rs
@@ -67,7 +67,7 @@ impl LayoutEventDispatcher {
         // We should be able to just get layout from WidgetManager here
         // since the layouts will be calculated by this point
         if let Some(mut entity) = world.get_entity_mut(index.0) {
-            if let Some(mut on_layout) = entity.remove::<OnLayout>() {
+            if let Some(mut on_layout) = entity.take::<OnLayout>() {
                 if let Some(rect) = layout_cache.rect.get(&index) {
                     // dbg!(format!("Processing event for: {:?}", entity.id()));
                     let layout_event = LayoutEvent::new(*rect, flags, index.0);
diff --git a/src/on_event.rs b/src/on_event.rs
index efe92c5..0f6ca06 100644
--- a/src/on_event.rs
+++ b/src/on_event.rs
@@ -2,7 +2,7 @@ use bevy::prelude::{Component, Entity, In, IntoSystem, System, World};
 use std::fmt::{Debug, Formatter};
 use std::sync::{Arc, RwLock};
 
-use crate::event::Event;
+use crate::event::KEvent;
 use crate::event_dispatcher::EventDispatcherContext;
 use crate::widget_state::WidgetState;
 
@@ -17,8 +17,8 @@ pub struct OnEvent {
     system: Arc<
         RwLock<
             dyn System<
-                In = (EventDispatcherContext, WidgetState, Event, Entity),
-                Out = (EventDispatcherContext, Event),
+                In = (EventDispatcherContext, WidgetState, KEvent, Entity),
+                Out = (EventDispatcherContext, KEvent),
             >,
         >,
     >,
@@ -42,8 +42,8 @@ impl OnEvent {
     /// 2. The event
     pub fn new<Params>(
         system: impl IntoSystem<
-            (EventDispatcherContext, WidgetState, Event, Entity),
-            (EventDispatcherContext, Event),
+            (EventDispatcherContext, WidgetState, KEvent, Entity),
+            (EventDispatcherContext, KEvent),
             Params,
         >,
     ) -> OnEvent {
@@ -61,9 +61,9 @@ impl OnEvent {
         mut event_dispatcher_context: EventDispatcherContext,
         widget_state: WidgetState,
         entity: Entity,
-        mut event: Event,
+        mut event: KEvent,
         world: &mut World,
-    ) -> (EventDispatcherContext, Event) {
+    ) -> (EventDispatcherContext, KEvent) {
         if let Ok(mut system) = self.system.try_write() {
             if !self.has_initialized {
                 system.initialize(world);
diff --git a/src/render/extract.rs b/src/render/extract.rs
index e0a4ded..0990189 100644
--- a/src/render/extract.rs
+++ b/src/render/extract.rs
@@ -5,9 +5,12 @@ use crate::{
     styles::Corner,
 };
 use bevy::{
-    prelude::{Assets, Camera, Color, Commands, Entity, Image, Plugin, Query, Rect, Res, Vec2},
-    render::{Extract, RenderApp, RenderStage},
-    window::Windows,
+    prelude::{
+        Assets, Camera, Color, Commands, Entity, Image, IntoSystemAppConfig, Plugin, Query, Rect,
+        Res, Vec2, With,
+    },
+    render::{Extract, ExtractSchedule, RenderApp},
+    window::{PrimaryWindow, Window, WindowRef},
 };
 use kayak_font::KayakFont;
 
@@ -25,7 +28,7 @@ pub struct BevyKayakUIExtractPlugin;
 impl Plugin for BevyKayakUIExtractPlugin {
     fn build(&self, app: &mut bevy::prelude::App) {
         let render_app = app.sub_app_mut(RenderApp);
-        render_app.add_system_to_stage(RenderStage::Extract, extract);
+        render_app.add_system(extract.in_schedule(ExtractSchedule));
     }
 }
 
@@ -37,18 +40,28 @@ pub fn extract(
     node_query: Extract<Query<&Node>>,
     widget_names: Extract<Query<&WidgetName>>,
     images: Extract<Res<Assets<Image>>>,
-    windows: Extract<Res<Windows>>,
+    primary_window: Extract<Query<&Window, With<PrimaryWindow>>>,
+    windows: Extract<Query<&Window>>,
 ) {
     let mut render_primitives = Vec::new();
     for (entity, context, camera) in context_query.iter() {
         let dpi = match &camera.target {
-            bevy::render::camera::RenderTarget::Window(window_id) => {
-                if let Some(window) = windows.get(*window_id) {
-                    window.scale_factor() as f32
-                } else {
-                    1.0
+            bevy::render::camera::RenderTarget::Window(window_ref) => match window_ref {
+                WindowRef::Primary => {
+                    if let Ok(window) = primary_window.get_single() {
+                        window.scale_factor() as f32
+                    } else {
+                        1.0
+                    }
                 }
-            }
+                WindowRef::Entity(window_entity) => {
+                    if let Ok(window) = windows.get(*window_entity) {
+                        window.scale_factor() as f32
+                    } else {
+                        1.0
+                    }
+                }
+            },
             _ => 1.0,
         };
         let mut new_render_primitives = context.build_render_primitives(&node_query, &widget_names);
diff --git a/src/render/mod.rs b/src/render/mod.rs
index 67dbf1c..c6b1e80 100644
--- a/src/render/mod.rs
+++ b/src/render/mod.rs
@@ -1,9 +1,9 @@
 use bevy::{
-    prelude::{App, Camera, Commands, Entity, Plugin, Query, With},
+    prelude::{App, Camera, Commands, Entity, IntoSystemAppConfig, Plugin, Query, With},
     render::{
         render_graph::{RenderGraph, RunGraphOnViewNode, SlotInfo, SlotType},
         render_phase::{DrawFunctions, RenderPhase},
-        Extract, RenderApp, RenderStage,
+        Extract, ExtractSchedule, RenderApp,
     },
 };
 
@@ -43,7 +43,7 @@ impl Plugin for BevyKayakUIRenderPlugin {
         let render_app = app.sub_app_mut(RenderApp);
         render_app
             .init_resource::<DrawFunctions<TransparentUI>>()
-            .add_system_to_stage(RenderStage::Extract, extract_core_pipeline_camera_phases);
+            .add_system(extract_core_pipeline_camera_phases.in_schedule(ExtractSchedule));
         // .add_system_to_stage(RenderStage::PhaseSort, sort_phase_system::<TransparentUI>);
 
         // let pass_node_ui = MainPassUINode::new(&mut render_app.world);
@@ -78,32 +78,24 @@ impl Plugin for BevyKayakUIRenderPlugin {
                 draw_ui_graph::node::MAIN_PASS,
                 RunGraphOnViewNode::new(draw_ui_graph::NAME),
             );
-            graph_2d
-                .add_node_edge(
-                    bevy::core_pipeline::core_2d::graph::node::MAIN_PASS,
-                    draw_ui_graph::node::MAIN_PASS,
-                )
-                .unwrap();
-            graph_2d
-                .add_slot_edge(
-                    graph_2d.input_node().unwrap().id,
-                    bevy::core_pipeline::core_2d::graph::input::VIEW_ENTITY,
-                    draw_ui_graph::node::MAIN_PASS,
-                    RunGraphOnViewNode::IN_VIEW,
-                )
-                .unwrap();
-            graph_2d
-                .add_node_edge(
-                    bevy::core_pipeline::core_2d::graph::node::TONEMAPPING,
-                    draw_ui_graph::node::MAIN_PASS,
-                )
-                .unwrap();
-            graph_2d
-                .add_node_edge(
-                    draw_ui_graph::node::MAIN_PASS,
-                    bevy::core_pipeline::core_2d::graph::node::UPSCALING,
-                )
-                .unwrap();
+            graph_2d.add_node_edge(
+                bevy::core_pipeline::core_2d::graph::node::MAIN_PASS,
+                draw_ui_graph::node::MAIN_PASS,
+            );
+            graph_2d.add_slot_edge(
+                graph_2d.input_node().id,
+                bevy::core_pipeline::core_2d::graph::input::VIEW_ENTITY,
+                draw_ui_graph::node::MAIN_PASS,
+                RunGraphOnViewNode::IN_VIEW,
+            );
+            graph_2d.add_node_edge(
+                bevy::core_pipeline::core_2d::graph::node::TONEMAPPING,
+                draw_ui_graph::node::MAIN_PASS,
+            );
+            graph_2d.add_node_edge(
+                draw_ui_graph::node::MAIN_PASS,
+                bevy::core_pipeline::core_2d::graph::node::UPSCALING,
+            );
         }
 
         if let Some(graph_3d) = graph.get_sub_graph_mut(bevy::core_pipeline::core_3d::graph::NAME) {
@@ -112,32 +104,24 @@ impl Plugin for BevyKayakUIRenderPlugin {
                 draw_ui_graph::node::MAIN_PASS,
                 RunGraphOnViewNode::new(draw_ui_graph::NAME),
             );
-            graph_3d
-                .add_node_edge(
-                    bevy::core_pipeline::core_3d::graph::node::MAIN_PASS,
-                    draw_ui_graph::node::MAIN_PASS,
-                )
-                .unwrap();
-            graph_3d
-                .add_node_edge(
-                    bevy::core_pipeline::core_3d::graph::node::TONEMAPPING,
-                    draw_ui_graph::node::MAIN_PASS,
-                )
-                .unwrap();
-            graph_3d
-                .add_node_edge(
-                    draw_ui_graph::node::MAIN_PASS,
-                    bevy::core_pipeline::core_3d::graph::node::UPSCALING,
-                )
-                .unwrap();
-            graph_3d
-                .add_slot_edge(
-                    graph_3d.input_node().unwrap().id,
-                    bevy::core_pipeline::core_3d::graph::input::VIEW_ENTITY,
-                    draw_ui_graph::node::MAIN_PASS,
-                    RunGraphOnViewNode::IN_VIEW,
-                )
-                .unwrap();
+            graph_3d.add_node_edge(
+                bevy::core_pipeline::core_3d::graph::node::MAIN_PASS,
+                draw_ui_graph::node::MAIN_PASS,
+            );
+            graph_3d.add_node_edge(
+                bevy::core_pipeline::core_3d::graph::node::TONEMAPPING,
+                draw_ui_graph::node::MAIN_PASS,
+            );
+            graph_3d.add_node_edge(
+                draw_ui_graph::node::MAIN_PASS,
+                bevy::core_pipeline::core_3d::graph::node::UPSCALING,
+            );
+            graph_3d.add_slot_edge(
+                graph_3d.input_node().id,
+                bevy::core_pipeline::core_3d::graph::input::VIEW_ENTITY,
+                draw_ui_graph::node::MAIN_PASS,
+                RunGraphOnViewNode::IN_VIEW,
+            );
         }
 
         app.add_plugin(font::TextRendererPlugin)
@@ -154,14 +138,12 @@ fn get_ui_graph(render_app: &mut App) -> RenderGraph {
         draw_ui_graph::input::VIEW_ENTITY,
         SlotType::Entity,
     )]);
-    ui_graph
-        .add_slot_edge(
-            input_node_id,
-            draw_ui_graph::input::VIEW_ENTITY,
-            draw_ui_graph::node::MAIN_PASS,
-            MainPassUINode::IN_VIEW,
-        )
-        .unwrap();
+    ui_graph.add_slot_edge(
+        input_node_id,
+        draw_ui_graph::input::VIEW_ENTITY,
+        draw_ui_graph::node::MAIN_PASS,
+        MainPassUINode::IN_VIEW,
+    );
     ui_graph
 }
 
diff --git a/src/render/ui_pass.rs b/src/render/ui_pass.rs
index 70ed333..89c510f 100644
--- a/src/render/ui_pass.rs
+++ b/src/render/ui_pass.rs
@@ -5,7 +5,7 @@ use bevy::render::render_phase::{DrawFunctionId, PhaseItem};
 use bevy::render::render_resource::CachedRenderPipelineId;
 use bevy::render::{
     render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
-    render_phase::{DrawFunctions, RenderPhase, TrackedRenderPass},
+    render_phase::{DrawFunctions, RenderPhase},
     render_resource::{LoadOp, Operations, RenderPassDescriptor},
     renderer::RenderContext,
     view::{ExtractedView, ViewTarget},
@@ -33,6 +33,10 @@ impl PhaseItem for TransparentUI {
     fn draw_function(&self) -> DrawFunctionId {
         self.draw_function
     }
+
+    fn entity(&self) -> Entity {
+        self.entity
+    }
 }
 
 pub struct MainPassUINode {
@@ -100,11 +104,8 @@ impl Node for MainPassUINode {
                 .get_resource::<DrawFunctions<TransparentUI>>()
                 .unwrap();
 
-            let render_pass = render_context
-                .command_encoder
-                .begin_render_pass(&pass_descriptor);
+            let mut tracked_pass = render_context.begin_tracked_render_pass(pass_descriptor);
             let mut draw_functions = draw_functions.write();
-            let mut tracked_pass = TrackedRenderPass::new(render_pass);
             for item in transparent_phase.items.iter() {
                 let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
                 draw_function.draw(world, &mut tracked_pass, view_entity, item);
diff --git a/src/render/unified/mod.rs b/src/render/unified/mod.rs
index 7efdec3..53a801a 100644
--- a/src/render/unified/mod.rs
+++ b/src/render/unified/mod.rs
@@ -1,12 +1,15 @@
 use bevy::{
-    prelude::{Assets, Commands, HandleUntyped, Plugin, Res, Resource},
+    prelude::{
+        Assets, Commands, HandleUntyped, IntoSystemAppConfig, IntoSystemConfig, Plugin, Query, Res,
+        Resource, With,
+    },
     reflect::TypeUuid,
     render::{
         render_phase::DrawFunctions,
         render_resource::{Shader, SpecializedRenderPipelines},
-        Extract, RenderApp, RenderStage,
+        Extract, ExtractSchedule, RenderApp, RenderSet,
     },
-    window::Windows,
+    window::{PrimaryWindow, Window},
 };
 
 use crate::{
@@ -41,9 +44,9 @@ impl Plugin for UnifiedRenderPlugin {
             .init_resource::<UnifiedPipeline>()
             .init_resource::<SpecializedRenderPipelines<UnifiedPipeline>>()
             .init_resource::<QuadMeta>()
-            .add_system_to_stage(RenderStage::Extract, extract_baseline)
-            .add_system_to_stage(RenderStage::Prepare, pipeline::prepare_quads)
-            .add_system_to_stage(RenderStage::Queue, pipeline::queue_quads);
+            .add_system(extract_baseline.in_schedule(ExtractSchedule))
+            .add_system(pipeline::prepare_quads.in_set(RenderSet::Prepare))
+            .add_system(pipeline::queue_quads.in_set(RenderSet::Queue));
 
         let draw_quad = DrawUI::new(&mut render_app.world);
 
@@ -61,10 +64,10 @@ pub struct Dpi(f32);
 
 pub fn extract_baseline(
     mut commands: Commands,
-    windows: Extract<Res<Windows>>,
+    windows: Extract<Query<&Window, With<PrimaryWindow>>>,
     window_size: Extract<Res<WindowSize>>,
 ) {
-    let dpi = if let Some(window) = windows.get_primary() {
+    let dpi = if let Ok(window) = windows.get_single() {
         window.scale_factor() as f32
     } else {
         1.0
diff --git a/src/render/unified/pipeline.rs b/src/render/unified/pipeline.rs
index 4d5aa33..adc75a1 100644
--- a/src/render/unified/pipeline.rs
+++ b/src/render/unified/pipeline.rs
@@ -185,6 +185,7 @@ impl FromWorld for UnifiedPipeline {
             mip_level_count: 1,
             sample_count: 1,
             dimension: TextureDimension::D2,
+            view_formats: &[TextureFormat::Rgba8UnormSrgb],
             format: TextureFormat::Rgba8UnormSrgb,
             usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
         };
@@ -209,6 +210,7 @@ impl FromWorld for UnifiedPipeline {
             texture,
             sampler,
             texture_view,
+            mip_level_count: 1,
             size: Vec2::new(1.0, 1.0),
             texture_format: TextureFormat::Rgba8UnormSrgb,
         };
@@ -298,12 +300,12 @@ impl SpecializedRenderPipeline for UnifiedPipeline {
                     write_mask: ColorWrites::ALL,
                 })],
             }),
-            layout: Some(vec![
+            layout: vec![
                 self.view_layout.clone(),
                 self.font_image_layout.clone(),
                 self.types_layout.clone(),
                 self.image_layout.clone(),
-            ]),
+            ],
             primitive: PrimitiveState {
                 front_face: FrontFace::Ccw,
                 cull_mode: None,
@@ -320,6 +322,7 @@ impl SpecializedRenderPipeline for UnifiedPipeline {
                 alpha_to_coverage_enabled: false,
             },
             label: Some("unified_pipeline".into()),
+            push_constant_ranges: vec![],
         }
     }
 }
@@ -562,7 +565,7 @@ pub fn queue_quads(
             layout: &quad_pipeline.view_layout,
         }));
 
-        let key = UnifiedPipelineKey::from_msaa_samples(msaa.samples);
+        let key = UnifiedPipelineKey::from_msaa_samples(msaa.samples());
         let spec_pipeline = pipelines.specialize(&mut pipeline_cache, &quad_pipeline, key);
 
         let draw_quad = draw_functions.read().get_id::<DrawUI>().unwrap();
diff --git a/src/render/unified/shader.wgsl b/src/render/unified/shader.wgsl
index cc6061d..4341b7e 100644
--- a/src/render/unified/shader.wgsl
+++ b/src/render/unified/shader.wgsl
@@ -53,7 +53,7 @@ var image_texture: texture_2d<f32>;
 @group(3) @binding(1)
 var image_sampler: sampler;
 
-let RADIUS: f32 = 0.1;
+const RADIUS: f32 = 0.1;
 
 // Where P is the position in pixel space, B is the size of the box adn R is the radius of the current corner.
 fn sdRoundBox(p: vec2<f32>, b: vec2<f32>, r: f32) -> f32 {
diff --git a/src/render/unified/text.rs b/src/render/unified/text.rs
index 400917b..c9fdb93 100644
--- a/src/render/unified/text.rs
+++ b/src/render/unified/text.rs
@@ -1,10 +1,10 @@
 use bevy::{
-    prelude::{Plugin, Res, ResMut},
+    prelude::{IntoSystemConfig, Plugin, Res, ResMut},
     render::{
         render_asset::RenderAssets,
         renderer::{RenderDevice, RenderQueue},
         texture::Image,
-        RenderApp, RenderStage,
+        RenderApp, RenderSet,
     },
 };
 use kayak_font::bevy::{FontTextureCache, KayakFontPlugin};
@@ -19,7 +19,7 @@ impl Plugin for TextRendererPlugin {
         app.add_plugin(KayakFontPlugin);
 
         let render_app = app.sub_app_mut(RenderApp);
-        render_app.add_system_to_stage(RenderStage::Queue, create_and_update_font_cache_texture);
+        render_app.add_system(create_and_update_font_cache_texture.in_set(RenderSet::Queue));
     }
 }
 fn create_and_update_font_cache_texture(
diff --git a/src/widgets/app.rs b/src/widgets/app.rs
index 6a0ba11..4b4aa96 100644
--- a/src/widgets/app.rs
+++ b/src/widgets/app.rs
@@ -1,4 +1,4 @@
-use bevy::prelude::*;
+use bevy::{prelude::*, window::PrimaryWindow};
 use kayak_ui_macros::rsx;
 
 use crate::{
@@ -45,7 +45,7 @@ pub fn app_update(
     In((widget_context, entity, previous_props_entity)): In<(KayakWidgetContext, Entity, Entity)>,
     widget_param: WidgetParam<KayakApp, EmptyState>,
     camera: Query<&Camera, With<CameraUIKayak>>,
-    windows: Res<Windows>,
+    windows: Query<&Window, With<PrimaryWindow>>,
 ) -> bool {
     let mut window_change = false;
 
@@ -60,7 +60,7 @@ pub fn app_update(
                         window_change = true;
                     }
                 } else {
-                    let primary_window = windows.get_primary().unwrap();
+                    let primary_window = windows.single();
                     if app_style.0.width != StyleProp::Value(Units::Pixels(primary_window.width()))
                     {
                         window_change = true;
@@ -84,8 +84,6 @@ pub fn app_render(
     mut commands: Commands,
     mut query: Query<(&KStyle, &mut ComputedStyles, &KChildren)>,
     camera: Query<&Camera, With<CameraUIKayak>>,
-    windows: Res<Windows>,
-    images: Res<Assets<Image>>,
 ) -> bool {
     let (mut width, mut height) = (0.0, 0.0);
 
@@ -94,17 +92,9 @@ pub fn app_render(
             if let Some(size) = camera.logical_viewport_size() {
                 width = size.x;
                 height = size.y;
-            } else if let Some(viewport) = camera
-                .target
-                .get_render_target_info(&windows, &images)
-                .as_ref()
-                .map(|target_info| {
-                    let scale = target_info.scale_factor;
-                    (target_info.physical_size.as_dvec2() / scale).as_vec2()
-                })
-            {
-                width = viewport.x;
-                height = viewport.y;
+            } else if let Some(viewport) = &camera.viewport {
+                width = viewport.physical_size.x as f32;
+                height = viewport.physical_size.y as f32;
             }
         }
     }
diff --git a/src/widgets/button.rs b/src/widgets/button.rs
index 96dee97..571e74d 100644
--- a/src/widgets/button.rs
+++ b/src/widgets/button.rs
@@ -7,7 +7,7 @@ use kayak_ui_macros::rsx;
 
 use crate::{
     context::WidgetName,
-    event::{Event, EventType},
+    event::{EventType, KEvent},
     event_dispatcher::EventDispatcherContext,
     on_event::OnEvent,
     prelude::{KChildren, KayakWidgetContext, Units},
@@ -92,7 +92,7 @@ pub fn button_render(
                 move |In((event_dispatcher_context, _, mut event, _entity)): In<(
                     EventDispatcherContext,
                     WidgetState,
-                    Event,
+                    KEvent,
                     Entity,
                 )>,
                       mut query: Query<&mut ButtonState>| {
diff --git a/src/widgets/scroll/scroll_bar.rs b/src/widgets/scroll/scroll_bar.rs
index e45f3a1..f554548 100644
--- a/src/widgets/scroll/scroll_bar.rs
+++ b/src/widgets/scroll/scroll_bar.rs
@@ -3,7 +3,7 @@ use kayak_ui_macros::rsx;
 
 use crate::{
     context::WidgetName,
-    event::{Event, EventType},
+    event::{EventType, KEvent},
     event_dispatcher::EventDispatcherContext,
     on_event::OnEvent,
     prelude::{KChildren, KayakWidgetContext},
@@ -206,7 +206,7 @@ pub fn scroll_bar_render(
                     move |In((mut event_dispatcher_context, _, mut event, _entity)): In<(
                         EventDispatcherContext,
                         WidgetState,
-                        Event,
+                        KEvent,
                         Entity,
                     )>,
                           mut query: Query<&mut ScrollContext>| {
diff --git a/src/widgets/scroll/scroll_box.rs b/src/widgets/scroll/scroll_box.rs
index 5d4643c..c59d7c2 100644
--- a/src/widgets/scroll/scroll_box.rs
+++ b/src/widgets/scroll/scroll_box.rs
@@ -4,7 +4,7 @@ use crate::{
     children::KChildren,
     context::WidgetName,
     cursor::ScrollUnit,
-    event::{Event, EventType},
+    event::{EventType, KEvent},
     event_dispatcher::EventDispatcherContext,
     layout::{GeometryChanged, LayoutEvent},
     on_event::OnEvent,
@@ -185,7 +185,7 @@ pub fn scroll_box_render(
                     move |In((event_dispatcher_context, _, mut event, _entity)): In<(
                         EventDispatcherContext,
                         WidgetState,
-                        Event,
+                        KEvent,
                         Entity,
                     )>,
                           mut query: Query<&mut ScrollContext>| {
diff --git a/src/widgets/text_box.rs b/src/widgets/text_box.rs
index c0426e4..67cf244 100644
--- a/src/widgets/text_box.rs
+++ b/src/widgets/text_box.rs
@@ -6,7 +6,7 @@ use kayak_ui_macros::{constructor, rsx};
 
 use crate::{
     context::WidgetName,
-    event::{Event, EventType},
+    event::{EventType, KEvent},
     event_dispatcher::EventDispatcherContext,
     on_event::OnEvent,
     on_layout::OnLayout,
@@ -185,7 +185,7 @@ pub fn text_box_render(
                 move |In((event_dispatcher_context, _, mut event, _entity)): In<(
                     EventDispatcherContext,
                     WidgetState,
-                    Event,
+                    KEvent,
                     Entity,
                 )>,
                       font_assets: Res<Assets<KayakFont>>,
diff --git a/src/widgets/window.rs b/src/widgets/window.rs
index dd00fd4..b362deb 100644
--- a/src/widgets/window.rs
+++ b/src/widgets/window.rs
@@ -7,7 +7,7 @@ use kayak_ui_macros::rsx;
 use crate::{
     children::KChildren,
     context::WidgetName,
-    event::{Event, EventType},
+    event::{EventType, KEvent},
     event_dispatcher::EventDispatcherContext,
     on_event::OnEvent,
     prelude::KayakWidgetContext,
@@ -132,7 +132,7 @@ pub fn window_render(
                 move |In((event_dispatcher_context, _, mut event, _entity)): In<(
                     EventDispatcherContext,
                     WidgetState,
-                    Event,
+                    KEvent,
                     Entity,
                 )>,
                       mut query: Query<&mut KWindowState>,
@@ -226,7 +226,7 @@ pub fn window_render(
                                     move |In((mut event_dispatcher_context, _, mut event, entity)): In<(
                                         EventDispatcherContext,
                                         WidgetState,
-                                        Event,
+                                        KEvent,
                                         Entity,
                                     )>,
                                         mut query: Query<&mut KWindowState>| {
diff --git a/src/window_size.rs b/src/window_size.rs
index 4b17d24..dd274d5 100644
--- a/src/window_size.rs
+++ b/src/window_size.rs
@@ -10,32 +10,42 @@ pub struct WindowSize(pub f32, pub f32);
 pub fn update_window_size(
     mut window_resized_events: EventReader<WindowResized>,
     mut window_created_events: EventReader<WindowCreated>,
-    windows: Res<Windows>,
+    windows: Query<&Window>,
     mut window_size: ResMut<WindowSize>,
 ) {
-    let mut changed_window_ids = Vec::new();
+    let mut changed_windows = Vec::new();
     // handle resize events. latest events are handled first because we only want to resize each
     // window once
-    for event in window_resized_events.iter().rev() {
-        if changed_window_ids.contains(&event.id) {
+    for event in window_resized_events
+        .iter()
+        .collect::<Vec<_>>()
+        .iter()
+        .rev()
+    {
+        if changed_windows.contains(&event.window) {
             continue;
         }
 
-        changed_window_ids.push(event.id);
+        changed_windows.push(event.window);
     }
 
     // handle resize events. latest events are handled first because we only want to resize each
     // window once
-    for event in window_created_events.iter().rev() {
-        if changed_window_ids.contains(&event.id) {
+    for event in window_created_events
+        .iter()
+        .collect::<Vec<_>>()
+        .iter()
+        .rev()
+    {
+        if changed_windows.contains(&event.window) {
             continue;
         }
 
-        changed_window_ids.push(event.id);
+        changed_windows.push(event.window);
     }
 
-    for window_id in changed_window_ids {
-        if let Some(window) = windows.get(window_id) {
+    for window_entity in changed_windows {
+        if let Ok(window) = windows.get(window_entity) {
             let width = window.width();
             let height = window.height();
             *window_size = WindowSize(width, height);
-- 
GitLab