diff --git a/bevy_editor_panes/bevy_3d_viewport/src/lib.rs b/bevy_editor_panes/bevy_3d_viewport/src/lib.rs index 702df596..b3cad3f1 100644 --- a/bevy_editor_panes/bevy_3d_viewport/src/lib.rs +++ b/bevy_editor_panes/bevy_3d_viewport/src/lib.rs @@ -17,11 +17,10 @@ use bevy_editor_cam::prelude::{DefaultEditorCamPlugins, EditorCam}; use bevy_editor_styles::Theme; use bevy_infinite_grid::{InfiniteGrid, InfiniteGridPlugin, InfiniteGridSettings}; use bevy_pane_layout::prelude::*; -use bevy_transform_gizmos::{TransformGizmo, prelude::*}; +use bevy_transform_gizmos::{TransformGizmo, messages::ViewportResized, prelude::*}; use view_gizmo::ViewGizmoPlugin; use crate::{selection_box::SelectionBoxPlugin, view_gizmo::view_gizmo_node}; - mod selection_box; mod view_gizmo; @@ -50,6 +49,7 @@ impl Plugin for Viewport3dPanePlugin { } app.add_plugins((DefaultEditorCamPlugins, ViewGizmoPlugin, SelectionBoxPlugin)) + .add_message::() .add_systems(Startup, setup) .add_systems( First, @@ -231,6 +231,7 @@ fn update_render_target_size( bodies: Query<&PaneContentNode>, children_query: Query<&Children>, computed_node_query: Query<&ComputedNode, Changed>, + mut messages: MessageWriter, mut images: ResMut>, ) { for (pane_root, viewport) in &query { @@ -246,7 +247,11 @@ fn update_render_target_size( }; // TODO Convert to physical pixels let content_node_size = computed_node.size(); - + let size_array = [content_node_size.x, content_node_size.y]; + messages.write(ViewportResized { + pane_entity: pane_root, + size: size_array, + }); let camera = camera_query.get_mut(viewport.camera_id).unwrap(); let image_handle = camera.target.as_image().unwrap(); diff --git a/crates/bevy_events/Cargo.toml b/crates/bevy_events/Cargo.toml new file mode 100644 index 00000000..72ff73d6 --- /dev/null +++ b/crates/bevy_events/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "bevy_events" +version = "0.1.0" +edition = "2024" + +[dependencies] +bevy.workspace = true +bevy_editor_core.workspace = true + +[lints] +workspace = true diff --git a/crates/bevy_events/src/lib.rs b/crates/bevy_events/src/lib.rs new file mode 100644 index 00000000..35db2516 --- /dev/null +++ b/crates/bevy_events/src/lib.rs @@ -0,0 +1,16 @@ +//! This module contains events and messages used throughout the Bevy editor +use bevy::prelude::Entity; +use bevy::prelude::Message; + +/// Viewport size in pixels as a 2D vector. +pub type ViewportSize = [f32; 2]; + +/// Event emitted when a viewport (pane/editor panel) resizes. +/// Used for dynamic gizmo scaling +#[derive(Message, Clone)] +pub struct ViewportResized { + /// Entity of the pane/viewport that resized (for multi-pane editors). + pub pane_entity: Entity, + /// New viewport size in pixels. + pub size: ViewportSize, +} diff --git a/crates/bevy_transform_gizmos/src/lib.rs b/crates/bevy_transform_gizmos/src/lib.rs index ba7d66e0..80006d72 100644 --- a/crates/bevy_transform_gizmos/src/lib.rs +++ b/crates/bevy_transform_gizmos/src/lib.rs @@ -17,9 +17,11 @@ use bevy::{prelude::*, transform::TransformSystems}; use bevy_editor_core::selection::EditorSelection; use mesh::{RotationGizmo, ViewTranslateGizmo}; +use messages::ViewportResized; use normalization::*; mod mesh; +pub mod messages; pub mod normalization; /// Crate prelude. @@ -103,6 +105,8 @@ pub struct TransformGizmoSettings { pub snap_enabled: bool, /// Current gizmo mode. pub mode: GizmoMode, + /// Current gizmo scale. + pub viewport_scale: f32, } impl Default for TransformGizmoSettings { @@ -115,6 +119,7 @@ impl Default for TransformGizmoSettings { angle_snap: 15.0, // 15 degree angle snapping scale_snap: 0.1, // 0.1 scale increment snapping snap_enabled: true, // Enable snapping by default + viewport_scale: 1.0, mode: GizmoMode::default(), } } @@ -129,6 +134,8 @@ impl Plugin for TransformGizmoPlugin { if !app.is_plugin_added::() { app.add_plugins(MeshPickingPlugin); } + app.add_message::(); + app.init_resource::() .add_plugins(Ui3dNormalizationPlugin) .add_message::() @@ -164,6 +171,7 @@ impl Plugin for TransformGizmoPlugin { (adjust_view_translate_gizmo, gizmo_cam_copy_settings) .chain() .in_set(TransformGizmoSystems::Drag), + transform_gizmo_viewport_handler, ) .chain() .in_set(TransformGizmoSystems::Main) @@ -661,6 +669,7 @@ fn place_gizmo( fn propagate_gizmo_elements( gizmo: Query<(&GlobalTransform, &Children), With>, + settings: Res, mut gizmo_parts_query: Query<(&Transform, &mut GlobalTransform), Without>, ) { if let Ok((gizmo_pos, gizmo_parts)) = gizmo.single() { @@ -669,7 +678,12 @@ fn propagate_gizmo_elements( error!("Malformed transform gizmo"); continue; }; - *g_transform = gizmo_pos.mul_transform(*transform); + let scaled_transform = Transform { + translation: transform.translation * settings.viewport_scale, + rotation: transform.rotation, + scale: Vec3::splat(settings.viewport_scale), + }; + *g_transform = gizmo_pos.mul_transform(scaled_transform); } } } @@ -866,3 +880,14 @@ fn update_gizmo_visibility( } } } + +fn transform_gizmo_viewport_handler( + mut messages: MessageReader, + mut settings: ResMut, +) { + for msg in messages.read() { + let viewport_height = msg.size[1]; + let scale = (viewport_height / 600.0).clamp(0.3, 3.0); + settings.viewport_scale = scale; + } +} diff --git a/crates/bevy_transform_gizmos/src/messages.rs b/crates/bevy_transform_gizmos/src/messages.rs new file mode 100644 index 00000000..5a76478f --- /dev/null +++ b/crates/bevy_transform_gizmos/src/messages.rs @@ -0,0 +1,16 @@ +//! This module contains events/messages used to communicate with the transform gizmo plugin. +use bevy::prelude::Entity; +use bevy::prelude::Message; + +/// Viewport size in pixels as a 2D vector. +pub type ViewportSize = [f32; 2]; + +/// Event emitted when a viewport (pane/editor panel) resizes. +/// Used for dynamic gizmo scaling +#[derive(Message, Clone)] +pub struct ViewportResized { + /// Entity of the pane/viewport that resized (for multi-pane editors). + pub pane_entity: Entity, + /// New viewport size in pixels. + pub size: ViewportSize, +}