use bevy_ecs::name::Name;
use bevy_ecs::prelude::*;
use tracing::{debug, trace};
use super::super::metrics::Offset;
use super::super::{Arrangement, GlobalArrangement};
use crate::ecs::drag::WindowDragging;
use crate::ecs::graphics::format_entity_name;
use crate::ecs::window::{Window, WindowPos};
pub fn window_pos_sync_system(
mut query: Query<
(
Entity,
&GlobalArrangement,
&mut WindowPos,
Option<&Name>,
Has<WindowDragging>,
),
(With<Window>, Changed<GlobalArrangement>),
>,
frame_count: Res<crate::ecs::world::FrameCount>,
) {
for (entity, global_arr, mut window_pos, name, is_dragging) in query.iter_mut() {
let entity_name = format_entity_name(entity, name);
let width = global_arr.bounds.right - global_arr.bounds.left;
let height = global_arr.bounds.bottom - global_arr.bounds.top;
debug!(
frame = frame_count.0,
entity = %entity_name,
bounds_left = global_arr.bounds.left,
bounds_top = global_arr.bounds.top,
bounds_right = global_arr.bounds.right,
bounds_bottom = global_arr.bounds.bottom,
width = width,
height = height,
is_dragging = is_dragging,
"[window_pos_sync_system] Processing entity"
);
if width <= 0.0 || height <= 0.0 {
debug!(
frame = frame_count.0,
entity = %entity_name,
"[window_pos_sync_system] Skipping: invalid bounds"
);
continue;
}
use crate::ecs::types::{Point, SizeI};
let new_size = SizeI {
width: width.ceil() as i32,
height: height.ceil() as i32,
};
let size_changed = window_pos.size != Some(new_size);
if is_dragging {
if size_changed {
debug!(
frame = frame_count.0,
entity = %entity_name,
old_size = ?window_pos.size,
new_size = format_args!("{}x{}", new_size.width, new_size.height),
"[window_pos_sync] Dragging: size-only update"
);
window_pos.size = Some(new_size);
}
} else {
let new_position = Point {
x: global_arr.bounds.left as i32,
y: global_arr.bounds.top as i32,
};
let position_changed = window_pos.position != Some(new_position);
if position_changed || size_changed {
debug!(
frame = frame_count.0,
entity = %entity_name,
old_pos = ?window_pos.position,
old_size = ?window_pos.size,
new_xy = format_args!("({},{})", new_position.x, new_position.y),
new_size = format_args!("{}x{}", new_size.width, new_size.height),
ga_bounds = format_args!("({:.0},{:.0})-({:.0},{:.0})", global_arr.bounds.left, global_arr.bounds.top, global_arr.bounds.right, global_arr.bounds.bottom),
"[window_pos_sync] Updating WindowPos from GA"
);
window_pos.position = Some(new_position);
window_pos.size = Some(new_size);
} else {
trace!(
frame = frame_count.0,
entity = %entity_name,
"[window_pos_sync_system] No change needed"
);
}
}
}
}
pub fn sync_window_arrangement_from_window_pos(
mut query: Query<
(Entity, &WindowPos, &mut Arrangement, Option<&Name>),
(With<Window>, Changed<WindowPos>, Without<WindowDragging>),
>,
) {
use crate::ecs::graphics::format_entity_name;
for (entity, window_pos, mut arrangement, name) in query.iter_mut() {
let Some(position) = window_pos.position else {
continue;
};
if position.x == windows::Win32::UI::WindowsAndMessaging::CW_USEDEFAULT {
continue;
}
let new_offset = Offset {
x: position.x as f32,
y: position.y as f32,
};
if arrangement.offset != new_offset {
let entity_name = format_entity_name(entity, name);
debug!(
entity = %entity_name,
old = format_args!("({:.0},{:.0})", arrangement.offset.x, arrangement.offset.y),
new = format_args!("({:.0},{:.0})", new_offset.x, new_offset.y),
"[sync_window_arr] offset changed"
);
arrangement.offset = new_offset;
}
}
}