app.rs 4.08 KiB
use bevy::{prelude::*, window::PrimaryWindow};
use kayak_ui_macros::rsx;
use crate::{
children::KChildren,
context::WidgetName,
prelude::KayakWidgetContext,
styles::{ComputedStyles, KStyle, RenderCommand, StyleProp, Units},
widget::{EmptyState, Widget, WidgetParam},
CameraUIKayak,
};
use super::ClipBundle;
#[derive(Component, Default, Clone, PartialEq, Eq)]
pub struct KayakApp;
impl Widget for KayakApp {}
/// Kayak's default root widget
/// This widget provides a width/height that matches the camera's width and height.
/// It will auto update if bevy's camera changes.
#[derive(Bundle)]
pub struct KayakAppBundle {
pub app: KayakApp,
pub styles: KStyle,
pub computed_styles: ComputedStyles,
pub children: KChildren,
pub widget_name: WidgetName,
}
impl Default for KayakAppBundle {
fn default() -> Self {
Self {
app: Default::default(),
styles: Default::default(),
computed_styles: ComputedStyles::default(),
children: Default::default(),
widget_name: KayakApp.get_name(),
}
}
}
pub fn app_update(
In((entity, previous_props_entity)): In<(Entity, Entity)>,
widget_context: Res<KayakWidgetContext>,
widget_param: WidgetParam<KayakApp, EmptyState>,
camera: Query<&Camera, With<CameraUIKayak>>,
windows: Query<&Window, With<PrimaryWindow>>,
) -> bool {
let mut window_change = false;
if let Ok(app_style) = widget_param.computed_style_query.get(entity) {
if let Some(camera_entity) = widget_context.camera_entity {
if let Ok(camera) = camera.get(camera_entity) {
if let Some(size) = camera.logical_viewport_size() {
if app_style.0.width != StyleProp::Value(Units::Pixels(size.x)) {
window_change = true;
}
if app_style.0.height != StyleProp::Value(Units::Pixels(size.y)) {
window_change = true;
}
} else {
let primary_window = windows.single();
if app_style.0.width != StyleProp::Value(Units::Pixels(primary_window.width()))
{
window_change = true;
}
if app_style.0.height
!= StyleProp::Value(Units::Pixels(primary_window.height()))
{
window_change = true;
}
}
}
}
}
widget_param.has_changed(&widget_context, entity, previous_props_entity) || window_change
}
/// TODO: USE CAMERA INSTEAD OF WINDOW!!
pub fn app_render(
In(entity): In<Entity>,
widget_context: Res<KayakWidgetContext>,
mut commands: Commands,
mut query: Query<(&KStyle, &mut ComputedStyles, &KChildren)>,
camera: Query<&Camera, With<CameraUIKayak>>,
) -> bool {
let (mut width, mut height) = (0.0, 0.0);
if let Some(camera_entity) = widget_context.camera_entity {
if let Ok(camera) = camera.get(camera_entity) {
if let Some(size) = camera.logical_viewport_size() {
width = size.x;
height = size.y;
} else if let Some(viewport) = &camera.viewport {
width = viewport.physical_size.x as f32;
height = viewport.physical_size.y as f32;
}
}
}
if let Ok((app_style, mut computed_styles, children)) = query.get_mut(entity) {
*computed_styles = KStyle::default()
.with_style(KStyle {
render_command: RenderCommand::Layout.into(),
width: Units::Pixels(width).into(),
height: Units::Pixels(height).into(),
..Default::default()
})
.with_style(app_style)
.into();
let parent_id = Some(entity);
rsx! {
<ClipBundle
children={children.clone()}
/>
};
}
true
}