diff --git a/game_core/src/ui/screens/in_game.rs b/game_core/src/ui/screens/in_game.rs index 1fca8bed518ebe1b663854425add43f758383508..29258ac01e07ca707d9ef10957e69d4379d59e34 100644 --- a/game_core/src/ui/screens/in_game.rs +++ b/game_core/src/ui/screens/in_game.rs @@ -2,12 +2,16 @@ use bevy::prelude::*; use kayak_ui::prelude::*; use kayak_ui::widgets::{ElementBundle, KayakAppBundle, TextProps, TextWidgetBundle}; +use crate::ui::components::*; use crate::ui::prelude::{px, stretch, value}; use crate::ui::sync::UITravelInfo; use crate::ui::utilities::context::create_root_context; use crate::ui::utilities::StateUIRoot; use crate::ui::widgets::*; -use crate::{empty_props, parent_widget, register_widget_with_resource}; +use crate::world::EncounterState; +use crate::{ + empty_props, parent_widget, register_widget_with_many_resources, register_widget_with_resource, +}; empty_props!(InGameProps); parent_widget!(InGameProps => InGameLayout); @@ -16,6 +20,7 @@ pub fn render_game_panels( In((widget_context, entity)): In<(KayakWidgetContext, Entity)>, mut commands: Commands, ui_data: Res<UITravelInfo>, + encounter_state: Res<EncounterState>, ) -> bool { let parent_id = Some(entity); @@ -25,21 +30,29 @@ pub fn render_game_panels( left: stretch(1.0), right: stretch(1.0), bottom: px(50.0), + height: px(60.0), + width: stretch(0.6), + padding: value(Edge::all(Units::Stretch(1.0))), ..Default::default() }; rsx! { <ElementBundle> - { if ui_data.distance_remaining > 0.1 { + { if !encounter_state.is_in_encounter() && ui_data.distance_remaining > 0.1 { constructor! { - <TextWidgetBundle - text={TextProps { - content: format!("{:.2}KM", ui_data.distance_remaining), - size: 48.0, - ..Default::default() - }} - styles={distance_style} - /> + <PanelWidget styles={distance_style}> + <TextWidgetBundle + text={TextProps { + content: format!("{:.2}KM", ui_data.distance_remaining), + size: 48.0, + ..Default::default() + }} + styles={KStyle { + bottom: px(7.5), + ..Default::default() + }} + /> + </PanelWidget> } }} @@ -49,7 +62,12 @@ pub fn render_game_panels( } }} - <EncounterPanel /> + {if encounter_state.is_in_encounter() { + constructor! { + <EncounterPanel /> + } + }} + </ElementBundle> } @@ -72,12 +90,13 @@ pub fn render_in_game_ui(mut commands: Commands) { fn create_ingame_context() -> KayakRootContext { let mut widget_context = create_root_context(); - register_widget_with_resource!( + register_widget_with_many_resources!( widget_context, InGameProps, EmptyState, - UITravelInfo, - render_game_panels + render_game_panels, + uitravelinfo: UITravelInfo, + encounterstate: EncounterState ); widget_context diff --git a/game_core/src/ui/utilities.rs b/game_core/src/ui/utilities.rs index 2b590fde823f6fa84846e3fb4be0c66aa9090e6b..8c5613ec7760594850ebcf15b96ef46c7d80f6e0 100644 --- a/game_core/src/ui/utilities.rs +++ b/game_core/src/ui/utilities.rs @@ -107,6 +107,25 @@ macro_rules! register_widget_with_resource { }}; } +#[macro_export] +macro_rules! register_widget_with_many_resources { + ($ctx: expr, $props: ident, $state: ident, $system: ident, $($name: ident: $resource: ident),+) => {{ + $ctx.add_widget_data::<$props, $state>(); + $ctx.add_widget_system( + ::kayak_ui::prelude::Widget::get_name(&$props::default()), + | + In((widget_context, entity, previous_entity)): In<(KayakWidgetContext, Entity, Entity)>, + $( $name: bevy::prelude::Res<$resource> ),+, + widget_param: WidgetParam<$props, $state>, + | { + widget_param.has_changed(&widget_context, entity, previous_entity) + $( || $name.is_changed() )+ + }, + $system, + ); + }}; +} + pub fn widget_update_with_resource< Props: PartialEq + Component + Clone, State: PartialEq + Component + Clone, diff --git a/game_core/src/ui/widgets/encounter_panel.rs b/game_core/src/ui/widgets/encounter_panel.rs index 938df93aae3bb3675138ba7be5cce5d69b28d614..b1b5e1f3d49fad07a6ad6d9ab259bc49ab478dfe 100644 --- a/game_core/src/ui/widgets/encounter_panel.rs +++ b/game_core/src/ui/widgets/encounter_panel.rs @@ -21,24 +21,9 @@ pub fn render_encounter_panel( In((widget_context, entity)): In<(KayakWidgetContext, Entity)>, mut commands: Commands, ui_data: Res<EncounterState>, - mut self_style: Query<&mut ComputedStyles>, ) -> bool { let parent_id = Some(entity); - if let Ok(mut styles) = self_style.get_mut(entity) { - if ui_data.is_in_encounter() { - *styles = ComputedStyles::default(); - } else { - *styles = KStyle { - width: px(0.0), - height: px(0.0), - padding: value(Edge::all(Units::Stretch(0.0))), - ..Default::default() - } - .into(); - } - } - let distance_style = KStyle { position_type: value(KPositionType::SelfDirected), top: stretch(1.0), @@ -68,46 +53,44 @@ pub fn render_encounter_panel( match &*ui_data { EncounterState::Choice(encounter) => { rsx! { - <PanelWidget - styles={panel_style} - > - <TextWidgetBundle - text={TextProps { - font: Some(String::from("header")), - content: format!("Trepidation! {}", encounter.title), - size: 36.0, - ..Default::default() - }} - styles={KStyle { - color: value(Color::BLACK), - padding: edge_px(20.0), - left: stretch(1.0), - right: stretch(1.0), - ..Default::default() - }} - /> - - <VDividerWidget props={VDividerWidgetProps { height: 4.0, padding: 5.0, color: Color::rgb(0.52, 0.369, 0.18)}} /> - <ScrollContextProviderBundle> - <ScrollBoxBundle> - <TextWidgetBundle - text={TextProps { - content: encounter.description.to_string(), - size: 32.0, - ..Default::default() - }} - styles={KStyle { - color: value(Color::BLACK), - padding: edge_px(20.0), - bottom: px(15.0), - left: stretch(1.0), - right: stretch(1.0), - ..Default::default() - }} - /> - </ScrollBoxBundle> - </ScrollContextProviderBundle> - <VDividerWidget props={VDividerWidgetProps { height: 4.0, padding: 5.0, color: Color::rgb(0.52, 0.369, 0.18)}} /> + <ElementBundle styles={panel_style}> + <PanelWidget> + <TextWidgetBundle + text={TextProps { + font: Some(String::from("header")), + content: format!("Trepidation! {}", encounter.title), + size: 36.0, + ..Default::default() + }} + styles={KStyle { + color: value(Color::BLACK), + padding: edge_px(40.0), + left: stretch(1.0), + right: stretch(1.0), + ..Default::default() + }} + /> + <VDividerWidget props={VDividerWidgetProps { height: 4.0, padding: 10.0, color: Color::rgb(0.52, 0.369, 0.18)}} /> + <ScrollContextProviderBundle> + <ScrollBoxBundle> + <TextWidgetBundle + text={TextProps { + content: encounter.description.to_string(), + size: 32.0, + ..Default::default() + }} + styles={KStyle { + color: value(Color::BLACK), + padding: edge_px(20.0), + bottom: px(15.0), + left: stretch(1.0), + right: stretch(1.0), + ..Default::default() + }} + /> + </ScrollBoxBundle> + </ScrollContextProviderBundle> + </PanelWidget> <ElementBundle styles={KStyle { layout_type: value(LayoutType::Row), @@ -135,7 +118,7 @@ pub fn render_encounter_panel( } } </ElementBundle> - </PanelWidget> + </ElementBundle> } } EncounterState::Consequence(..) => {} diff --git a/game_core/src/ui/widgets/shop_panel.rs b/game_core/src/ui/widgets/shop_panel.rs index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ebb857552a23caa0eab80745df206ee283dc6d40 100644 --- a/game_core/src/ui/widgets/shop_panel.rs +++ b/game_core/src/ui/widgets/shop_panel.rs @@ -0,0 +1,113 @@ +use bevy::prelude::*; +use kayak_ui::prelude::*; +use kayak_ui::widgets::{ + ElementBundle, ScrollBoxBundle, ScrollBoxProps, ScrollContextProviderBundle, TextProps, + TextWidgetBundle, +}; + +use crate::assets::AssetHandles; +use crate::states::Player; +use crate::ui::components::*; +use crate::ui::prelude::*; +use crate::ui::sync::UITravelInfo; +use crate::ui::widgets::*; +use crate::world::{CurrentResidence, MapQuery, TownPaths}; +use crate::{basic_widget, empty_props, on_button_click}; + +empty_props!(TransitPanelProps); +basic_widget!(TransitPanelProps => TransitPanel); + +pub fn buysell_button_factory(target: String) -> OnEvent { + let target = target.clone(); + on_button_click!( + ParamSet<( + Commands, + Res<TownPaths>, + Query<(Entity, &CurrentResidence), With<Player>>, + MapQuery, + )>, + |mut params: ParamSet<( + Commands, + Res<TownPaths>, + Query<(Entity, &CurrentResidence), With<Player>>, + MapQuery, + )>| { + let target = target.clone(); + let (entity, current) = { + match params.p2().get_single() { + Ok((entity, current)) => (entity.clone(), (current.get_location()).clone()), + _ => return, + } + }; + + let places = match params.p1().routes.get(¤t) { + Some(places) => places.clone(), + None => return, + }; + + let bundle = match params.p3().get_active_level() { + Some(level) => places.create_route_bundle_for(target, level).unwrap(), + None => return, + }; + + params.p0().entity(entity).insert(bundle); + } + ) +} + +pub fn render_transit_panel( + In((widget_context, entity)): In<(KayakWidgetContext, Entity)>, + mut commands: Commands, + ui_data: Res<UITravelInfo>, +) -> bool { + let parent_id = Some(entity); + + rsx! { + <ElementBundle> + <TextWidgetBundle + text={TextProps { + content: format!("Set off for:"), + size: 32.0, + ..Default::default() + }} + styles={KStyle { + color: value(Color::BLACK), + padding: edge_px(20.0), + bottom: px(15.0), + left: stretch(1.0), + right: stretch(1.0), + ..Default::default() + }} + /> + <ScrollContextProviderBundle> + <ScrollBoxBundle> + { + for (place, distance) in ui_data.travel_options.iter() { + constructor! { + <ButtonWidget + styles={ + KStyle { + left: stretch(1.0), + right: stretch(1.0), + width: pct(70.0), + min_width: px(300.0), + max_width: px(600.0), + bottom: px(10.0), + padding_left: px(20.0), + padding_right: px(20.0), + ..Default::default() + } + } + props={ButtonWidgetProps::text(format!("{}: {:.2}KM", &place, distance), 28.0)} + on_event={buysell_button_factory(place.clone())} + /> + } + } + } + </ScrollBoxBundle> + </ScrollContextProviderBundle> + </ElementBundle> + } + + true +} diff --git a/game_core/src/world/encounters.rs b/game_core/src/world/encounters.rs index 595b56d1025f6cf428951e2000e25fb789a91b53..ac3e67dfb24815c4c6924447161801d609573977 100644 --- a/game_core/src/world/encounters.rs +++ b/game_core/src/world/encounters.rs @@ -221,6 +221,8 @@ pub fn notify_new_zone( *encounter_state = EncounterState::Choice(gen_encounter()); } } + } else if last_zone.is_some() { + *last_zone = None; } } }