@@ 22,7 22,335 @@ pub struct GameUIPlugin;
impl Plugin for GameUIPlugin {
fn build(&self, app: &mut App) {
- app.add_system(dev_details_ui.run_if(in_state(AppState::InGame)));
+ app.add_system(dev_details_ui.run_if(in_state(AppState::InGame)))
+ .add_system(setup_details.in_schedule(OnEnter(AppState::InGame)))
+ .add_systems(
+ (
+ update_game_state_text,
+ update_currency_text,
+ update_deck_text,
+ update_discard_text,
+ update_plays_text,
+ update_buys_text,
+ update_vp_text,
+ )
+ );
+ }
+}
+
+#[derive(Component)]
+struct GameStateText;
+
+#[derive(Component)]
+struct CurrencyText;
+
+#[derive(Component)]
+struct DeckText;
+
+#[derive(Component)]
+struct DiscardText;
+
+#[derive(Component)]
+struct PlaysText;
+
+#[derive(Component)]
+struct BuysText;
+
+#[derive(Component)]
+struct VPText;
+
+fn setup_details(
+ mut commands: Commands,
+ asset_server: Res<AssetServer>,
+) {
+ let font = asset_server.load("fonts/FiraMono-Bold.ttf");
+ let font_size = 40.;
+ let text_style = TextStyle {
+ font: font.clone(),
+ font_size,
+ color: Color::WHITE,
+ };
+
+ // game state
+ commands.spawn((
+ TextBundle::from_sections([
+ TextSection::new(
+ "State: ",
+ text_style.clone(),
+ ),
+ TextSection::from_style(text_style.clone()),
+ ])
+ .with_text_alignment(TextAlignment::Center)
+ .with_style(Style {
+ position_type: PositionType::Absolute,
+ position: UiRect {
+ top: Val::Px(20.),
+ left: Val::Px(20.),
+ ..Default::default()
+ },
+ ..Default::default()
+ }),
+ GameStateText,
+ ));
+
+ // plays
+ commands.spawn((
+ TextBundle::from_sections([
+ TextSection::new(
+ "Plays: ",
+ text_style.clone(),
+ ),
+ TextSection::from_style(text_style.clone()),
+ ])
+ .with_text_alignment(TextAlignment::Center)
+ .with_style(Style {
+ position_type: PositionType::Absolute,
+ position: UiRect {
+ bottom: Val::Px(220.),
+ left: Val::Px(20.),
+ ..Default::default()
+ },
+ ..Default::default()
+ }),
+ PlaysText,
+ ));
+
+ // buys
+ commands.spawn((
+ TextBundle::from_sections([
+ TextSection::new(
+ "Buys: ",
+ text_style.clone(),
+ ),
+ TextSection::from_style(text_style.clone()),
+ ])
+ .with_text_alignment(TextAlignment::Center)
+ .with_style(Style {
+ position_type: PositionType::Absolute,
+ position: UiRect {
+ bottom: Val::Px(180.),
+ left: Val::Px(20.),
+ ..Default::default()
+ },
+ ..Default::default()
+ }),
+ BuysText,
+ ));
+
+ // currency
+ commands.spawn((
+ TextBundle::from_sections([
+ TextSection::new(
+ "Currency: ",
+ text_style.clone(),
+ ),
+ TextSection::from_style(TextStyle {
+ color: Color::GOLD,
+ ..text_style.clone()
+ }),
+ ])
+ .with_text_alignment(TextAlignment::Center)
+ .with_style(Style {
+ position_type: PositionType::Absolute,
+ position: UiRect {
+ bottom: Val::Px(140.),
+ left: Val::Px(20.),
+ ..Default::default()
+ },
+ ..Default::default()
+ }),
+ CurrencyText,
+ ));
+
+ // deck
+ commands.spawn((
+ TextBundle::from_sections([
+ TextSection::new(
+ "Deck: ",
+ text_style.clone(),
+ ),
+ TextSection::from_style(text_style.clone()),
+ ])
+ .with_text_alignment(TextAlignment::Center)
+ .with_style(Style {
+ position_type: PositionType::Absolute,
+ position: UiRect {
+ bottom: Val::Px(100.),
+ left: Val::Px(20.),
+ ..Default::default()
+ },
+ ..Default::default()
+ }),
+ DeckText,
+ ));
+
+ // discard
+ commands.spawn((
+ TextBundle::from_sections([
+ TextSection::new(
+ "Discard: ",
+ text_style.clone(),
+ ),
+ TextSection::from_style(text_style.clone()),
+ ])
+ .with_text_alignment(TextAlignment::Center)
+ .with_style(Style {
+ position_type: PositionType::Absolute,
+ position: UiRect {
+ bottom: Val::Px(60.),
+ left: Val::Px(20.),
+ ..Default::default()
+ },
+ ..Default::default()
+ }),
+ DiscardText,
+ ));
+
+ // vp
+ commands.spawn((
+ TextBundle::from_sections([
+ TextSection::new(
+ "VP: ",
+ text_style.clone(),
+ ),
+ TextSection::from_style(text_style.clone()),
+ ])
+ .with_text_alignment(TextAlignment::Center)
+ .with_style(Style {
+ position_type: PositionType::Absolute,
+ position: UiRect {
+ bottom: Val::Px(20.),
+ left: Val::Px(20.),
+ ..Default::default()
+ },
+ ..Default::default()
+ }),
+ VPText,
+ ));
+}
+
+fn update_game_state_text(
+ mut text_query: Query<&mut Text, With<GameStateText>>,
+ game_data: Res<GameData>,
+) {
+ for mut text in &mut text_query {
+ let Some(status) = &game_data.game_status else {
+ return;
+ };
+ let Some(player) = status.players.values().filter(|p| p.state != PlayerState::Idle).next() else {
+ return;
+ };
+ text.sections[1].value = format!("{} - {:?}", player.display_name, player.state);
+ }
+}
+
+fn update_currency_text(
+ mut text_query: Query<&mut Text, With<CurrencyText>>,
+ game_data: Res<GameData>,
+ global: Res<Global>,
+) {
+ for mut text in &mut text_query {
+ let Some(status) = &game_data.game_status else {
+ return;
+ };
+ let Some(player) = status.players.get(&global.user.as_ref().unwrap().id) else {
+ return;
+ };
+ text.sections[1].value = player.currency.to_string();
+ }
+}
+
+fn update_deck_text(
+ mut text_query: Query<&mut Text, With<DeckText>>,
+ game_data: Res<GameData>,
+ global: Res<Global>,
+) {
+ for mut text in &mut text_query {
+ let Some(status) = &game_data.game_status else {
+ return;
+ };
+ let Some(player) = status.players.get(&global.user.as_ref().unwrap().id) else {
+ return;
+ };
+ text.sections[1].value = player.deck.len().to_string();
+ }
+}
+
+fn update_discard_text(
+ mut text_query: Query<&mut Text, With<DiscardText>>,
+ game_data: Res<GameData>,
+ global: Res<Global>,
+) {
+ for mut text in &mut text_query {
+ let Some(status) = &game_data.game_status else {
+ return;
+ };
+ let Some(player) = status.players.get(&global.user.as_ref().unwrap().id) else {
+ return;
+ };
+ text.sections[1].value = player.discard.len().to_string();
+ }
+}
+
+fn update_plays_text(
+ mut text_query: Query<&mut Text, With<PlaysText>>,
+ game_data: Res<GameData>,
+ global: Res<Global>,
+) {
+ for mut text in &mut text_query {
+ let Some(status) = &game_data.game_status else {
+ return;
+ };
+ let Some(player) = status.players.get(&global.user.as_ref().unwrap().id) else {
+ return;
+ };
+
+ if player.plays == 0 {
+ text.sections[1].style.color = Color::RED;
+ } else {
+ text.sections[1].style.color = Color::GREEN;
+ }
+
+ text.sections[1].value = player.plays.to_string();
+ }
+}
+
+fn update_buys_text(
+ mut text_query: Query<&mut Text, With<BuysText>>,
+ game_data: Res<GameData>,
+ global: Res<Global>,
+) {
+ for mut text in &mut text_query {
+ let Some(status) = &game_data.game_status else {
+ return;
+ };
+ let Some(player) = status.players.get(&global.user.as_ref().unwrap().id) else {
+ return;
+ };
+
+ if player.buys == 0 {
+ text.sections[1].style.color = Color::RED;
+ } else {
+ text.sections[1].style.color = Color::GREEN;
+ }
+
+ text.sections[1].value = player.buys.to_string();
+ }
+}
+
+fn update_vp_text(
+ mut text_query: Query<&mut Text, With<VPText>>,
+ game_data: Res<GameData>,
+ global: Res<Global>,
+) {
+ for mut text in &mut text_query {
+ let Some(status) = &game_data.game_status else {
+ return;
+ };
+ let Some(player) = status.players.get(&global.user.as_ref().unwrap().id) else {
+ return;
+ };
+ text.sections[1].value = player.vp.to_string();
}
}