/* * This file is part of laurelin_client * Copyright (C) 2023 Jonni Liljamo * * Licensed under GPL-3.0-only. * See LICENSE for licensing information. */ use bevy::prelude::*; use crate::{AppState, plugins::{GameData, GameActionCreateCallEvent}, Global, game_status::PlayerState, api::game::{Action, Command}, seed_gen}; pub struct StateButtonPlugin; impl Plugin for StateButtonPlugin { fn build(&self, app: &mut App) { app.add_system(setup_state_button.in_schedule(OnEnter(AppState::InGame))) .add_system(update_state_button); } } const NORMAL_BUTTON: Color = Color::rgb(0.15, 0.15, 0.15); const HOVERED_BUTTON: Color = Color::rgb(0.25, 0.25, 0.25); const PRESSED_BUTTON: Color = Color::rgb(0.35, 0.75, 0.35); #[derive(Component)] struct StateButton; #[derive(Component)] struct StateButtonText; fn setup_state_button( mut commands: Commands, asset_server: Res, ) { commands.spawn(( NodeBundle { style: Style { position_type: PositionType::Absolute, position: UiRect { bottom: Val::Px(20.), right: Val::Px(20.), ..Default::default() }, ..Default::default() }, ..Default::default() }, )) .with_children(|parent| { parent .spawn((ButtonBundle { style: Style { size: Size::new(Val::Px(150.), Val::Px(65.)), // center child text justify_content: JustifyContent::Center, align_items: AlignItems::Center, ..Default::default() }, background_color: NORMAL_BUTTON.into(), ..Default::default() }, StateButton )) .with_children(|parent| { parent.spawn(( TextBundle::from_section( "Pass", TextStyle { font: asset_server.load("fonts/FiraMono-Bold.ttf"), font_size: 40., color: Color::WHITE, }, ), StateButtonText, )); }); }); } fn update_state_button( mut interaction_query: Query< (&Interaction, &mut BackgroundColor, &mut Visibility, &Children), (Changed, With) >, mut text_query: Query<&mut Text>, mut game_data: ResMut, global: Res, mut gac_ev_w: EventWriter, ) { for (interaction, mut color, mut visibility, children) in &mut interaction_query { // NOTE: horrible clones because of borrow funnies let Some(game) = game_data.clone().game else { return; }; let Some(status) = game_data.clone().game_status else { return; }; let Some(user) = &global.user else { return; }; let player = status.players.get(&user.id).unwrap(); let mut text = text_query.get_mut(children[0]).unwrap(); match player.state { PlayerState::Idle => { *visibility = Visibility::Hidden; return; } PlayerState::PlayPhase => { text.sections[0].value = "Skip Play".to_string(); } PlayerState::BuyPhase => { text.sections[0].value = "End Turn".to_string(); } } *visibility = Visibility::Inherited; if game_data.locked { // input locked rn, so don't show any signs of interactivity return; } match interaction { Interaction::Clicked => { *color = PRESSED_BUTTON.into(); game_data.locked = true; match player.state { PlayerState::PlayPhase => { gac_ev_w.send(GameActionCreateCallEvent { action: Action::new( &game.id, &user.id, &user.id, &Command::ChangePlayerState { state: PlayerState::BuyPhase, }, seed_gen!(), ), }); } PlayerState::BuyPhase => { gac_ev_w.send(GameActionCreateCallEvent { action: Action::new( &game.id, &user.id, &user.id, &Command::EndTurn { }, seed_gen!(), ), }); } _ => {} } } Interaction::Hovered => { *color = HOVERED_BUTTON.into(); } Interaction::None => { *color = NORMAL_BUTTON.into(); } } } }