diff --git a/Cargo.toml b/Cargo.toml index 8752c13..74b631e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,15 +10,22 @@ repository = "https://github.com/jakobhellermann/bevy_editor_pls" description = "In-App editor tools for bevy apps" readme = "README.md" +[patch.crates-io] +bevy_egui = { git = "https://github.com/zhaop/bevy_egui.git", branch = "bevy-0.14" } +bevy-inspector-egui = { git = "https://github.com/kristoff3r/bevy-inspector-egui.git", branch = "main", package = "bevy-inspector-egui" } +bevy_mod_debugdump = { git = "https://github.com/Vrixyz/bevy_mod_debugdump.git", branch = "bevy_0.14" } +transform-gizmo-bevy = { git = "https://github.com/zhaop/transform-gizmo.git", branch = "bevy-0.14.0-rc", package = "transform-gizmo-bevy" } + [workspace.dependencies] -bevy_editor_pls = { version = "0.8.0", path = "crates/bevy_editor_pls" } -bevy_editor_pls_core = { version = "0.8.0", path = "crates/bevy_editor_pls_core" } -bevy_editor_pls_default_windows = { version = "0.8.0", path = "crates/bevy_editor_pls_default_windows" } +bevy_editor_pls = { version = "0.8.1", path = "crates/bevy_editor_pls" } +bevy_editor_pls_core = { version = "0.8.1", path = "crates/bevy_editor_pls_core" } +bevy_editor_pls_default_windows = { version = "0.8.1", path = "crates/bevy_editor_pls_default_windows" } -bevy-inspector-egui = "0.23.0" -egui = "0.26" -egui_dock = "0.11" -egui-gizmo = "0.16" +bevy-inspector-egui = "0.24.0" +egui = "0.27" +egui_dock = "0.12" +# used to be egui-gizmo 0.16 +transform-gizmo-bevy = "0.2" [profile.dev.package."*"] opt-level = 2 diff --git a/crates/bevy_editor_pls/Cargo.toml b/crates/bevy_editor_pls/Cargo.toml index 3655b2e..bb3b625 100644 --- a/crates/bevy_editor_pls/Cargo.toml +++ b/crates/bevy_editor_pls/Cargo.toml @@ -22,13 +22,13 @@ default = ["default_windows"] [dependencies] bevy_editor_pls_core.workspace = true bevy_editor_pls_default_windows = { workspace = true, optional = true } -bevy = { version = "0.13", default-features = false, features = ["x11"] } +bevy = { version = "0.14.0-rc", default-features = false, features = ["x11"] } egui.workspace = true -egui-gizmo.workspace = true +transform-gizmo-bevy.workspace = true # bevy_framepace = { version = "0.12", default-features = false } [dev-dependencies] -bevy = { version = "0.13", default-features = false, features = [ +bevy = { version = "0.14.0-rc", default-features = false, features = [ "bevy_winit", "bevy_core_pipeline", "x11", diff --git a/crates/bevy_editor_pls/examples/ui.rs b/crates/bevy_editor_pls/examples/ui.rs index 70e9aa0..2b55009 100644 --- a/crates/bevy_editor_pls/examples/ui.rs +++ b/crates/bevy_editor_pls/examples/ui.rs @@ -43,7 +43,7 @@ fn setup(mut commands: Commands, asset_server: Res) { border: UiRect::all(Val::Px(2.0)), ..default() }, - background_color: Color::rgb(0.65, 0.65, 0.65).into(), + background_color: Color::srgb(0.65, 0.65, 0.65).into(), ..default() }) .with_children(|parent| { @@ -55,7 +55,7 @@ fn setup(mut commands: Commands, asset_server: Res) { height: Val::Percent(100.0), ..default() }, - background_color: Color::rgb(0.15, 0.15, 0.15).into(), + background_color: Color::srgb(0.15, 0.15, 0.15).into(), ..default() }) .with_children(|parent| { @@ -86,7 +86,7 @@ fn setup(mut commands: Commands, asset_server: Res) { height: Val::Percent(100.0), ..default() }, - background_color: Color::rgb(0.15, 0.15, 0.15).into(), + background_color: Color::srgb(0.15, 0.15, 0.15).into(), ..default() }) .with_children(|parent| { @@ -122,7 +122,7 @@ fn setup(mut commands: Commands, asset_server: Res) { overflow: Overflow::clip(), ..default() }, - background_color: Color::rgb(0.10, 0.10, 0.10).into(), + background_color: Color::srgb(0.10, 0.10, 0.10).into(), ..default() }) .with_children(|parent| { @@ -178,7 +178,7 @@ fn setup(mut commands: Commands, asset_server: Res) { border: UiRect::all(Val::Px(20.0)), ..default() }, - background_color: Color::rgb(0.4, 0.4, 1.0).into(), + background_color: Color::srgb(0.4, 0.4, 1.0).into(), ..default() }) .with_children(|parent| { @@ -188,7 +188,7 @@ fn setup(mut commands: Commands, asset_server: Res) { height: Val::Percent(100.0), ..default() }, - background_color: Color::rgb(0.8, 0.8, 1.0).into(), + background_color: Color::srgb(0.8, 0.8, 1.0).into(), ..default() }); }); @@ -213,7 +213,7 @@ fn setup(mut commands: Commands, asset_server: Res) { height: Val::Px(100.0), ..default() }, - background_color: Color::rgb(1.0, 0.0, 0.0).into(), + background_color: Color::srgb(1.0, 0.0, 0.0).into(), ..default() }) .with_children(|parent| { @@ -226,7 +226,7 @@ fn setup(mut commands: Commands, asset_server: Res) { bottom: Val::Px(20.0), ..default() }, - background_color: Color::rgb(1.0, 0.3, 0.3).into(), + background_color: Color::srgb(1.0, 0.3, 0.3).into(), ..default() }); parent.spawn(NodeBundle { @@ -238,7 +238,7 @@ fn setup(mut commands: Commands, asset_server: Res) { bottom: Val::Px(40.0), ..default() }, - background_color: Color::rgb(1.0, 0.5, 0.5).into(), + background_color: Color::srgb(1.0, 0.5, 0.5).into(), ..default() }); parent.spawn(NodeBundle { @@ -250,7 +250,7 @@ fn setup(mut commands: Commands, asset_server: Res) { bottom: Val::Px(60.0), ..default() }, - background_color: Color::rgb(1.0, 0.7, 0.7).into(), + background_color: Color::srgb(1.0, 0.7, 0.7).into(), ..default() }); // alpha test @@ -263,7 +263,7 @@ fn setup(mut commands: Commands, asset_server: Res) { bottom: Val::Px(80.0), ..default() }, - background_color: Color::rgba(1.0, 0.9, 0.9, 0.4).into(), + background_color: Color::srgba(1.0, 0.9, 0.9, 0.4).into(), ..default() }); }); diff --git a/crates/bevy_editor_pls/src/controls.rs b/crates/bevy_editor_pls/src/controls.rs index 78e0f74..01f9429 100644 --- a/crates/bevy_editor_pls/src/controls.rs +++ b/crates/bevy_editor_pls/src/controls.rs @@ -136,6 +136,8 @@ pub enum Action { PauseUnpauseTime, FocusSelected, + // maybe investigate [GizmoOptions].hotkeys + // https://docs.rs/transform-gizmo-bevy/latest/transform_gizmo_bevy/struct.GizmoHotkeys.html #[cfg(feature = "default_windows")] SetGizmoModeTranslate, #[cfg(feature = "default_windows")] @@ -240,7 +242,7 @@ pub fn editor_controls_system( editor .window_state_mut::() .unwrap() - .gizmo_mode = egui_gizmo::GizmoMode::Translate; + .gizmo_modes = transform_gizmo_bevy::GizmoMode::all_translate(); } if controls.just_pressed( Action::SetGizmoModeRotate, @@ -251,7 +253,7 @@ pub fn editor_controls_system( editor .window_state_mut::() .unwrap() - .gizmo_mode = egui_gizmo::GizmoMode::Rotate; + .gizmo_modes = transform_gizmo_bevy::GizmoMode::all_rotate(); } if controls.just_pressed( Action::SetGizmoModeScale, @@ -262,7 +264,7 @@ pub fn editor_controls_system( editor .window_state_mut::() .unwrap() - .gizmo_mode = egui_gizmo::GizmoMode::Scale; + .gizmo_modes = transform_gizmo_bevy::GizmoMode::all_scale(); } } } diff --git a/crates/bevy_editor_pls/src/lib.rs b/crates/bevy_editor_pls/src/lib.rs index f479693..aeaddb9 100644 --- a/crates/bevy_editor_pls/src/lib.rs +++ b/crates/bevy_editor_pls/src/lib.rs @@ -85,7 +85,7 @@ impl Plugin for EditorPlugin { if window.title == "Bevy App" { window.title = "bevy_editor_pls".into(); } - let entity = app.world.spawn(window); + let entity = app.world_mut().spawn(window); WindowRef::Entity(entity.id()) } EditorWindowPlacement::Window(entity) => WindowRef::Entity(entity), @@ -128,10 +128,15 @@ impl Plugin for EditorPlugin { app.add_plugins(bevy::pbr::wireframe::WireframePlugin); + // required for the GizmoWindow + if !app.is_plugin_added::() { + app.add_plugins(transform_gizmo_bevy::TransformGizmoPlugin); + } + app.insert_resource(controls::EditorControls::default_bindings()) .add_systems(Update, controls::editor_controls_system); - let mut internal_state = app.world.resource_mut::(); + let mut internal_state = app.world_mut().resource_mut::(); let [game, _inspector] = internal_state.split_right::(egui_dock::NodeIndex::root(), 0.75); diff --git a/crates/bevy_editor_pls_core/Cargo.toml b/crates/bevy_editor_pls_core/Cargo.toml index a39a774..88c845c 100644 --- a/crates/bevy_editor_pls_core/Cargo.toml +++ b/crates/bevy_editor_pls_core/Cargo.toml @@ -8,7 +8,7 @@ description.workspace = true readme.workspace = true [dependencies] -bevy = { version = "0.13", default-features = false } +bevy = { version = "0.14.0-rc", default-features = false } bevy-inspector-egui.workspace = true indexmap = "2" egui_dock.workspace = true diff --git a/crates/bevy_editor_pls_core/src/editor_window.rs b/crates/bevy_editor_pls_core/src/editor_window.rs index 89dde47..aac990e 100644 --- a/crates/bevy_editor_pls_core/src/editor_window.rs +++ b/crates/bevy_editor_pls_core/src/editor_window.rs @@ -13,6 +13,7 @@ pub trait EditorWindow: 'static { const DEFAULT_SIZE: (f32, f32) = (0.0, 0.0); fn ui(world: &mut World, cx: EditorWindowContext, ui: &mut egui::Ui); + /// Ui shown in the `Open Window` menu item. By default opens the window as a floating window. fn menu_ui(world: &mut World, mut cx: EditorWindowContext, ui: &mut egui::Ui) { let _ = world; diff --git a/crates/bevy_editor_pls_core/src/lib.rs b/crates/bevy_editor_pls_core/src/lib.rs index 4b91e5a..755026c 100644 --- a/crates/bevy_editor_pls_core/src/lib.rs +++ b/crates/bevy_editor_pls_core/src/lib.rs @@ -39,7 +39,7 @@ impl Plugin for WindowSetupPlugin { impl AddEditorWindow for App { fn add_editor_window(&mut self) -> &mut Self { - let mut editor = self.world.get_resource_mut::().expect("Editor resource missing. Make sure to add the `EditorPlugin` before calling `app.add_editor_window`."); + let mut editor = self.world_mut().get_resource_mut::().expect("Editor resource missing. Make sure to add the `EditorPlugin` before calling `app.add_editor_window`."); editor.add_window::(); self.add_plugins(WindowSetupPlugin::(PhantomData)); @@ -69,9 +69,9 @@ impl Plugin for EditorPlugin { let (window_entity, always_active) = match self.window { WindowRef::Primary => { let entity = app - .world + .world_mut() .query_filtered::>() - .single(&app.world); + .single(&app.world()); (entity, false) } WindowRef::Entity(entity) => (entity, true), diff --git a/crates/bevy_editor_pls_default_windows/Cargo.toml b/crates/bevy_editor_pls_default_windows/Cargo.toml index 203cb72..c32b1f2 100644 --- a/crates/bevy_editor_pls_default_windows/Cargo.toml +++ b/crates/bevy_editor_pls_default_windows/Cargo.toml @@ -11,7 +11,7 @@ readme.workspace = true highlight_changes = ["bevy-inspector-egui/highlight_changes"] [dependencies] -bevy = { version = "0.13", default-features = false, features = [ +bevy = { version = "0.14.0-rc", default-features = false, features = [ "bevy_scene", "bevy_text", "bevy_ui", @@ -31,4 +31,4 @@ indexmap = "2" pretty-type-name = "1.0" bevy_mod_debugdump = "0.10" opener = "0.6.0" -egui-gizmo.workspace = true +transform-gizmo-bevy.workspace = true diff --git a/crates/bevy_editor_pls_default_windows/src/cameras/mod.rs b/crates/bevy_editor_pls_default_windows/src/cameras/mod.rs index 56894ec..42601d5 100644 --- a/crates/bevy_editor_pls_default_windows/src/cameras/mod.rs +++ b/crates/bevy_editor_pls_default_windows/src/cameras/mod.rs @@ -13,13 +13,14 @@ use bevy_editor_pls_core::{ Editor, EditorEvent, }; use bevy_inspector_egui::egui; +use transform_gizmo_bevy::GizmoCamera; // use bevy_mod_picking::prelude::PickRaycastSource; use crate::hierarchy::{HideInEditor, HierarchyWindow}; use self::camera_3d_panorbit::PanOrbitCamera; -pub const EDITOR_RENDER_LAYER: u8 = 19; +pub const EDITOR_RENDER_LAYER: usize = 19; // Present on all editor cameras #[derive(Component)] @@ -232,7 +233,8 @@ fn spawn_editor_cameras(mut commands: Commands, editor: Res) { HideInEditor, Name::new("Editor Camera 3D Free"), NotInScene, - render_layers, + GizmoCamera, + render_layers.clone(), )); commands.spawn(( @@ -254,7 +256,8 @@ fn spawn_editor_cameras(mut commands: Commands, editor: Res) { HideInEditor, Name::new("Editor Camera 3D Pan/Orbit"), NotInScene, - render_layers, + GizmoCamera, + render_layers.clone(), )); commands.spawn(( @@ -275,6 +278,7 @@ fn spawn_editor_cameras(mut commands: Commands, editor: Res) { HideInEditor, Name::new("Editor Camera 2D Pan/Zoom"), NotInScene, + GizmoCamera, render_layers, )); } @@ -600,7 +604,7 @@ fn set_main_pass_viewport( } }); - cameras.iter_mut().for_each(|mut cam| { - cam.viewport = viewport.clone(); - }); + cameras + .iter_mut() + .for_each(|mut cam| cam.viewport.clone_from(&viewport)); } diff --git a/crates/bevy_editor_pls_default_windows/src/debug_settings/debugdump.rs b/crates/bevy_editor_pls_default_windows/src/debug_settings/debugdump.rs index 509999d..05b31bc 100644 --- a/crates/bevy_editor_pls_default_windows/src/debug_settings/debugdump.rs +++ b/crates/bevy_editor_pls_default_windows/src/debug_settings/debugdump.rs @@ -19,12 +19,12 @@ pub struct DotGraphs { pub fn setup(app: &mut App) { let render_app = match app.get_sub_app(RenderApp) { - Ok(render_app) => render_app, - Err(_label) => { + Some(render_app) => render_app, + None => { return; } }; - let render_graph = render_app.world.get_resource::().unwrap(); + let render_graph = render_app.world().get_resource::().unwrap(); let schedule_settings = schedule_graph::settings::Settings { include_system: Some(Box::new(|system| { @@ -35,18 +35,18 @@ pub fn setup(app: &mut App) { let rendergraph_settings = render_graph::settings::Settings::default(); let update_schedule = app.get_schedule(Update).map(|schedule| { - schedule_graph::schedule_graph_dot(schedule, &app.world, &schedule_settings) + schedule_graph::schedule_graph_dot(schedule, &app.world(), &schedule_settings) }); let fixed_update_schedule = app.get_schedule(FixedUpdate).map(|schedule| { - schedule_graph::schedule_graph_dot(schedule, &app.world, &schedule_settings) + schedule_graph::schedule_graph_dot(schedule, &app.world(), &schedule_settings) }); let render_main_schedule = render_app.get_schedule(Render).map(|schedule| { - schedule_graph::schedule_graph_dot(schedule, &app.world, &schedule_settings) + schedule_graph::schedule_graph_dot(schedule, &app.world(), &schedule_settings) }); let render_extract_schedule = render_app.get_schedule(ExtractSchedule).map(|schedule| { - schedule_graph::schedule_graph_dot(schedule, &app.world, &schedule_settings) + schedule_graph::schedule_graph_dot(schedule, &app.world(), &schedule_settings) }); let render_graph = render_graph::render_graph_dot(render_graph, &rendergraph_settings); diff --git a/crates/bevy_editor_pls_default_windows/src/gizmos.rs b/crates/bevy_editor_pls_default_windows/src/gizmos.rs index 1f5482f..46dfa02 100644 --- a/crates/bevy_editor_pls_default_windows/src/gizmos.rs +++ b/crates/bevy_editor_pls_default_windows/src/gizmos.rs @@ -1,28 +1,31 @@ use bevy::{ - ecs::query::QueryFilter, + ecs::{query::QueryFilter, system::RunSystemOnce}, prelude::*, - render::{camera::CameraProjection, view::RenderLayers}, + render::view::RenderLayers, }; use bevy_editor_pls_core::editor_window::{EditorWindow, EditorWindowContext}; -use bevy_inspector_egui::{bevy_inspector::hierarchy::SelectedEntities, egui}; -use egui_gizmo::GizmoMode; +use bevy_inspector_egui::egui; +use transform_gizmo_bevy::GizmoTarget; +use transform_gizmo_bevy::{EnumSet, GizmoMode}; use crate::{ - cameras::{ActiveEditorCamera, CameraWindow, EditorCamera, EDITOR_RENDER_LAYER}, + cameras::{EditorCamera, EDITOR_RENDER_LAYER}, hierarchy::HierarchyWindow, }; pub struct GizmoState { + /// If [false], doesn't show any gizmos pub camera_gizmo_active: bool, - pub gizmo_mode: GizmoMode, + /// Synced with the [transform_gizmo_bevy::GizmoOptions] resource + pub gizmo_modes: EnumSet, } impl Default for GizmoState { fn default() -> Self { Self { camera_gizmo_active: true, - gizmo_mode: GizmoMode::Translate, + gizmo_modes: GizmoMode::all_translate(), } } } @@ -36,41 +39,104 @@ impl EditorWindow for GizmoWindow { fn ui(_world: &mut World, _cx: EditorWindowContext, ui: &mut egui::Ui) { ui.label("Gizmos can currently not be configured"); + // could definitely change some settings here in the future } - fn viewport_toolbar_ui(world: &mut World, cx: EditorWindowContext, ui: &mut egui::Ui) { + /// Called every frame (hopefully), could this invariant (namely being called every frame) be documented, + /// ideally in the [EditorWindow] trait? + fn viewport_toolbar_ui(world: &mut World, cx: EditorWindowContext, _ui: &mut egui::Ui) { let gizmo_state = cx.state::().unwrap(); + // syncs the [GizmoOptions] resource with the current state of the gizmo window + let mut gizmo_options = world.resource_mut::(); + gizmo_options.gizmo_modes = gizmo_state.gizmo_modes; + if gizmo_state.camera_gizmo_active { - if let (Some(hierarchy_state), Some(_camera_state)) = - (cx.state::(), cx.state::()) - { - draw_gizmo(ui, world, &hierarchy_state.selected, gizmo_state.gizmo_mode); + /// Before [hydrate_gizmos] and [deconstruct_gizmos] are run, this system resets the state of all entities that have a [EntityShouldShowGizmo] component. + /// Then, according to selection logic some entities are marked as focussed, and [hydrate_gizmos] and [deconstruct_gizmos] is run to sync the gizmo state with the selection state. + fn reset_gizmos_selected_state( + mut commands: Commands, + entities: Query>, + ) { + for entity in entities.iter() { + commands.entity(entity).remove::(); + } + } + + /// Takes all entities marked with [EntityShouldShowGizmo] and adds the [GizmoTarget] component to them. + fn hydrate_gizmos( + mut commands: Commands, + entities: Query, Without)>, + ) { + for entity in entities.iter() { + if let Some(mut entity) = commands.get_entity(entity) { + trace!( + "Hydrating a gizmo on entity {:?} because it is selected", + entity.id() + ); + // implicitly assumes it is the only gizmo target in the world, + // otherwise setting [GizmoTarget].is_focussed may be necessary + entity.insert(GizmoTarget::default()); + } + } + } + + /// Takes all entities that should have their [GizmoTarget] removed because they are no longer selected. + fn deconstruct_gizmos( + mut commands: Commands, + entities: Query, Without)>, + ) { + for entity in entities.iter() { + if let Some(mut entity) = commands.get_entity(entity) { + entity.remove::(); + debug!( + "Removing GizmoTarget from entity {:?} because it has lost focus", + entity.id() + ); + } + } + } + + if let Some(hierarchy_state) = cx.state::() { + // here should assign the `EntityShouldShowGizmo` component, which is later synced + // with the actual gizmo ui system + + world.run_system_once(reset_gizmos_selected_state); + + let selected_entities = hierarchy_state.selected.iter(); + for entity in selected_entities { + if let Some(mut entity) = world.get_entity_mut(entity) { + entity.insert(EntityShouldShowGizmo); + } + } + + world.run_system_once(hydrate_gizmos); + world.run_system_once(deconstruct_gizmos); } } } fn app_setup(app: &mut App) { - let mut materials = app.world.resource_mut::>(); + let mut materials = app.world_mut().resource_mut::>(); let material_light = materials.add(StandardMaterial { - base_color: Color::rgba_u8(222, 208, 103, 255), + base_color: Color::srgba_u8(222, 208, 103, 255), unlit: true, fog_enabled: false, alpha_mode: AlphaMode::Add, ..default() }); let material_camera = materials.add(StandardMaterial { - base_color: Color::rgb(1.0, 1.0, 1.0), + base_color: Color::srgb(1.0, 1.0, 1.0), unlit: true, fog_enabled: false, alpha_mode: AlphaMode::Multiply, ..default() }); - let mut meshes = app.world.resource_mut::>(); + let mut meshes = app.world_mut().resource_mut::>(); let sphere = meshes.add(Sphere { radius: 0.3 }); - app.world.insert_resource(GizmoMarkerConfig { + app.world_mut().insert_resource(GizmoMarkerConfig { point_light_mesh: sphere.clone(), point_light_material: material_light.clone(), directional_light_mesh: sphere.clone(), @@ -93,9 +159,15 @@ struct GizmoMarkerConfig { camera_material: Handle, } +/// can somebody document what this does? is it a duplicate of [EntityShouldShowGizmo]? #[derive(Component)] struct HasGizmoMarker; +/// When on an entity, this entity should be controllable using some sort of user gizmo. +/// Currently uses [transform_gizmo_bevy], and puts the [GizmoTarget] on the entity. +#[derive(Component)] +struct EntityShouldShowGizmo; + type GizmoMarkerQuery<'w, 's, T, F = ()> = Query<'w, 's, Entity, (With, Without, F)>; @@ -119,7 +191,7 @@ fn add_gizmo_markers( .entity(entity) .insert(HasGizmoMarker) .with_children(|commands| { - commands.spawn((f(), render_layers, Name::new(name))); + commands.spawn((f(), render_layers.clone(), Name::new(name))); }); } } @@ -159,62 +231,9 @@ fn add_gizmo_markers( material: gizmo_marker_meshes.camera_material.clone_weak(), ..default() }, - render_layers, + render_layers.clone(), Name::new("Camera Gizmo"), )); }); } } - -fn draw_gizmo( - ui: &mut egui::Ui, - world: &mut World, - selected_entities: &SelectedEntities, - gizmo_mode: GizmoMode, -) { - let Ok((cam_transform, projection)) = world - .query_filtered::<(&GlobalTransform, &Projection), With>() - .get_single(world) - else { - return; - }; - let view_matrix = Mat4::from(cam_transform.affine().inverse()); - let projection_matrix = projection.get_projection_matrix(); - - if selected_entities.len() != 1 { - return; - } - - for selected in selected_entities.iter() { - let Some(global_transform) = world.get::(selected) else { - continue; - }; - let model_matrix = global_transform.compute_matrix(); - - let Some(result) = egui_gizmo::Gizmo::new(selected) - .model_matrix(model_matrix.into()) - .view_matrix(view_matrix.into()) - .projection_matrix(projection_matrix.into()) - .orientation(egui_gizmo::GizmoOrientation::Local) - .mode(gizmo_mode) - .interact(ui) - else { - continue; - }; - - let global_affine = global_transform.affine(); - - let mut transform = world.get_mut::(selected).unwrap(); - - let parent_affine = global_affine * transform.compute_affine().inverse(); - let inverse_parent_transform = GlobalTransform::from(parent_affine.inverse()); - - let global_transform = Transform { - translation: result.translation.into(), - rotation: result.rotation.into(), - scale: result.scale.into(), - }; - - *transform = (inverse_parent_transform * global_transform).into(); - } -} diff --git a/crates/bevy_editor_pls_default_windows/src/scenes.rs b/crates/bevy_editor_pls_default_windows/src/scenes.rs index bba31ea..faabbda 100644 --- a/crates/bevy_editor_pls_default_windows/src/scenes.rs +++ b/crates/bevy_editor_pls_default_windows/src/scenes.rs @@ -64,12 +64,13 @@ fn save_world( name: &str, entities: std::collections::HashSet, ) -> Result<(), Box> { - let type_registry = world.get_resource::().unwrap(); + let type_registry_arc = world.get_resource::().unwrap(); + let type_registry = type_registry_arc.read(); let mut scene_builder = DynamicSceneBuilder::from_world(world); scene_builder = scene_builder.extract_entities(entities.into_iter()); let scene = scene_builder.build(); - let ron = scene.serialize_ron(type_registry)?; + let ron = scene.serialize(&type_registry)?; std::fs::write(name, ron)?; Ok(()) }