DEVELOPMENT ENVIRONMENT

~liljamo/deck-builder

ce344ce02cbf54e051f507dca2e35cdba146f5af — Jonni Liljamo 1 year, 5 months ago 6ce97fb
wip(client): new refresh, state button thingies
M client/src/plugins/game/mod.rs => client/src/plugins/game/mod.rs +16 -1
@@ 29,7 29,8 @@ impl Plugin for GamePlugin {
            .add_plugin(card::CardPlugin)
            .add_plugin(supply::SupplyPlugin)
            .add_plugin(hand::HandPlugin)
            .add_system(game_setup.in_schedule(OnEnter(AppState::InGame)));
            .add_system(game_setup.in_schedule(OnEnter(AppState::InGame)))
            .add_system(handle_refresh_game_event.run_if(on_event::<RefreshGameEvent>()));
    }
}



@@ 66,3 67,17 @@ fn game_setup(
        .spawn(Collider::cuboid(20., 0.5, 20.))
        .insert(TransformBundle::from(Transform::from_xyz(0., -0.5, 0.)));
}

pub struct RefreshGameEvent;

fn handle_refresh_game_event(
    mut details_ev_w: EventWriter<GameDetailsCallEvent>,
    mut game_data: ResMut<GameData>,
) {
    game_data.game = None;
    game_data.game_status = None;

    details_ev_w.send(GameDetailsCallEvent {
        game_id: game_data.game.as_ref().unwrap().id.clone(),
    });
}

M client/src/plugins/game/ui/mod.rs => client/src/plugins/game/ui/mod.rs +5 -9
@@ 12,17 12,20 @@ use bevy_egui::{egui, EguiContexts};
use crate::{
    api::game::{Action, Command, Game},
    game_status::{Card, PlayerState},
    plugins::{GameActionCreateCallEvent, GameDetailsCallEvent},
    plugins::GameActionCreateCallEvent,
    AppState, Global, seed_gen,
};

use super::{supply::SpawnSupplyPilesEvent, GameData};

mod state_button;

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_plugin(state_button::StateButtonPlugin)
            .add_system(dev_details_ui.run_if(in_state(AppState::InGame)))
            .add_system(setup_details.in_schedule(OnEnter(AppState::InGame)))
            .add_systems(
                (


@@ 358,7 361,6 @@ pub fn dev_details_ui(
    mut contexts: EguiContexts,
    global: Res<Global>,
    game_data: Res<GameData>,
    mut details_ev_w: EventWriter<GameDetailsCallEvent>,
    mut create_action_ev_w: EventWriter<GameActionCreateCallEvent>,
    mut ssp_ev_w: EventWriter<SpawnSupplyPilesEvent>,
) {


@@ 377,12 379,6 @@ pub fn dev_details_ui(
                return;
            };

        if ui.button("Refresh").clicked() {
            details_ev_w.send(GameDetailsCallEvent {
                game_id: game_data.game.as_ref().unwrap().id.clone(),
            });
        }

        if status.actions.is_empty() && game.host_id == global.user.as_ref().unwrap().id {
            if ui.button("Init Game").clicked() {
                // NOTE/FIXME: hardcoded game init

A client/src/plugins/game/ui/state_button.rs => client/src/plugins/game/ui/state_button.rs +159 -0
@@ 0,0 1,159 @@
/*
 * This file is part of laurelin_client
 * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
 *
 * 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<AssetServer>,
) {
    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<Interaction>, With<StateButton>)
    >,
    mut text_query: Query<&mut Text>,
    game_data: Res<GameData>,
    global: Res<Global>,
    mut gac_ev_w: EventWriter<GameActionCreateCallEvent>,
) {
    for (interaction, mut color, mut visibility, children) in &mut interaction_query {
        let Some(game) = &game_data.game else {
            return;
        };
        let Some(status) = &game_data.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;

        match interaction {
            Interaction::Clicked => {
                *color = PRESSED_BUTTON.into();

                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();
            }
        }
    }
}