use crate::editor::prelude::*; use bevy::{ asset::{AssetLoader, LoadContext, LoadedAsset}, reflect::{TypePath, TypeUuid}, ui::FocusPolicy, utils::BoxedFuture, }; use serde::Deserialize; #[derive(Debug, Component, Default)] pub struct MonologueWidget; #[derive(Debug, Deserialize, TypeUuid, TypePath, PartialEq)] #[uuid = "216a570b-d142-4026-baed-d7feb0250458"] pub struct Monologue { text: String, } #[derive(Debug, Event)] pub enum ControlMonologue { Show(Handle), Hide, } #[derive(Debug, Component)] pub struct MonologueModal; #[derive(Debug, Component)] pub struct MonologueContainer; #[derive(Default)] pub struct MonologueLoader; impl AssetLoader for MonologueLoader { fn load<'a>( &'a self, bytes: &'a [u8], load_context: &'a mut LoadContext, ) -> BoxedFuture<'a, Result<(), bevy::asset::Error>> { Box::pin(async move { let asset = Monologue { text: String::from_utf8(bytes.to_vec())?, }; load_context.set_default_asset(LoadedAsset::new(asset)); Ok(()) }) } fn extensions(&self) -> &[&str] { &["monologue.txt"] } } pub fn init_texts_ui(mut commands: Commands) { commands.spawn(( NodeBundle { style: Style { width: Val::Percent(100.0), align_items: AlignItems::Center, justify_content: JustifyContent::Center, ..default() }, focus_policy: FocusPolicy::Pass, ..default() }, MonologueContainer, )); } pub fn texts_ui( mut events: EventReader>, mut commands: Commands, widget: Query>, current: Query<(Entity, &ui::TargetAsset)>, server: Res, ) { events.iter().for_each(|event| match event { AssetEvent::Created { handle } => { info!("Monologue created! {:?}", event); create_asset_button( &widget, &mut commands, ui::TargetAsset { handle: handle.clone(), }, get_asset_name(&server, handle.clone()), None, ); } AssetEvent::Removed { handle } => { info!("Monologue removed! {:?}", event); destroy_asset_button( ¤t, &mut commands, &ui::TargetAsset { handle: handle.clone(), }, ); } AssetEvent::Modified { handle } => { info!("Monologue modified! {:?}", event); destroy_asset_button( ¤t, &mut commands, &ui::TargetAsset { handle: handle.clone(), }, ); create_asset_button( &widget, &mut commands, ui::TargetAsset { handle: handle.clone(), }, get_asset_name(&server, handle.clone()), None, ); } }); } pub fn control_monologue( mut events: EventReader, monologues: Res>, container: Query>, mut commands: Commands, font: Res, // Not convinced we need this... ) { events.iter().for_each(|event| match event { ControlMonologue::Hide => { commands.entity(container.single()).despawn_descendants(); } ControlMonologue::Show(handle) => { monologues.get(handle).iter().for_each(|&monologue| { commands .entity(container.single()) .despawn_descendants() .with_children(|parent| { parent .spawn(NodeBundle { style: Style { max_width: Val::Percent(50.0), padding: UiRect::all(Val::Px(1.0)), margin: UiRect::all(Val::Px(1.0)), border: UiRect::all(Val::Px(1.0)), flex_direction: FlexDirection::Column, ..default() }, background_color: Color::WHITE.into(), border_color: Color::BLACK.into(), ..default() }) .with_children(|parent| { parent.spawn(( ui::TitleBarBase::new(Color::VIOLET).bundle(), ui::Title { text: "Monologue".into(), ..default() }, ui::Close { target: parent.parent_entity(), }, ui::Sorting(0), )); let style = match &font.default { Some(handle) => TextStyle { color: Color::BLACK.into(), font_size: 16.0, font: handle.clone(), ..default() }, None => TextStyle { color: Color::BLACK.into(), font_size: 16.0, ..default() }, }; parent.spawn(( TextBundle::from_section(monologue.text.clone(), style), handle.clone(), )); }); }); }); } }); } pub fn ui_control_monologue( events: Query< ( &Interaction, &ui::TargetAsset, Option<&ui::Active>, ), (With