~starkingdoms/starkingdoms

b2961310f531bdca97488e097aa49ecbe6c76f4f — ghostly_zsh a day ago 562e5c4
feat: recipe list button-ified
1 files changed, 54 insertions(+), 16 deletions(-)

M crates/unified/src/client/crafting/ui.rs
M crates/unified/src/client/crafting/ui.rs => crates/unified/src/client/crafting/ui.rs +54 -16
@@ 1,3 1,5 @@
use std::collections::HashMap;

use bevy::{input_focus::{AutoFocus, InputFocus}, ui::RelativeCursorPosition};

use crate::{attachment::PartInShip, client::colors, config::recipe::RecipesConfig, ecs::{CanCraft, CraftingUi, Drill, MainCamera, Me, Part, SingleStorage, ToggleDrillEvent}, prelude::*};


@@ 6,25 8,29 @@ pub fn crafting_ui_plugin(app: &mut App) {
    app.init_resource::<RecipeCollection>();
    app.add_systems(Startup, load_recipes);
    app.add_systems(PreUpdate, (initial_create_recipe_list, update_recipe_list));
    app.add_systems(Update, (close_button, drill_button, drill_state_change, single_storage_display));
    app.add_systems(Update, (close_button, drill_button, drill_state_change,
            single_storage_display, recipe_buttons));
}

#[derive(Component)]
struct CloseButton(Entity); // stores corresponding menu entity
#[derive(Component)]
#[derive(Component, Clone)]
struct PreviousInteraction(Interaction);
#[derive(Component)]
struct DrillButton(Entity); // stores corresponding part
#[derive(Component)]
struct SingleStorageDisplay(Entity); // stores corresponding part
#[derive(Component)]
struct RecipesHolder;
struct RecipesHolder(Entity); // stores corresponding part
#[derive(Component)]
struct PendingRecipesHolder;
struct PendingRecipesHolder(Entity); // stores corresponding part
#[derive(Resource, Default)]
struct RecipeCollection {
    handle: Option<Handle<RecipesConfig>>,
}
// TODO: use recipe inputs for client-side validation?
#[derive(Component, Clone)]
struct RecipeElement(Entity, String, HashMap<String, u32>); // stores corresponding part and recipe's part name and inputs

fn load_recipes(asset_server: Res<AssetServer>, mut recipe_collection: ResMut<RecipeCollection>) {
    recipe_collection.handle = Some(asset_server.load("config/recipes.rc.toml"));


@@ 147,23 153,23 @@ fn setup_ui(
                flex_direction: FlexDirection::Column,
                ..Default::default()
            },
            PendingRecipesHolder,
            PendingRecipesHolder(parent_part),
        ));
    });
}

fn initial_create_recipe_list(
    mut commands: Commands,
    added_recipes_holders: Query<Entity, With<PendingRecipesHolder>>,
    added_recipes_holders: Query<(Entity, &PendingRecipesHolder)>,
    recipe_collection: ResMut<RecipeCollection>,
    recipes_config: Res<Assets<RecipesConfig>>,
) {
    if let Some(strong_recipes_config) = recipes_config.get(&recipe_collection.handle.clone().unwrap()) {
        for recipe_holder in &added_recipes_holders {
        for (recipe_holder, pending_recipes_holder) in &added_recipes_holders {
            let mut recipe_holder = commands.get_entity(recipe_holder).unwrap();
            create_recipe_list(&mut recipe_holder, strong_recipes_config);
            create_recipe_list(pending_recipes_holder.0, &mut recipe_holder, strong_recipes_config);
            recipe_holder
                .insert(RecipesHolder)
                .insert(RecipesHolder(pending_recipes_holder.0))
                .remove::<PendingRecipesHolder>();
        }
    }


@@ 173,7 179,7 @@ fn update_recipe_list(
    recipe_collection: ResMut<RecipeCollection>,
    assets: ResMut<Assets<RecipesConfig>>,
    mut commands: Commands,
    recipes_holders: Query<Entity, With<RecipesHolder>>,
    recipes_holders: Query<(Entity, &RecipesHolder)>,
) {
    let Some(handle) = recipe_collection.handle.as_ref() else {
        return


@@ 184,16 190,17 @@ fn update_recipe_list(
            if *id == handle.id() {
                debug!("recipe list config modified - reloading lists");
                let strong_recipes_config = assets.get(*id).unwrap();
                for recipe_holder in &recipes_holders {
                    let mut recipe_holder = commands.get_entity(recipe_holder).unwrap();
                for (recipe_holder_entity, recipes_holder) in &recipes_holders {
                    let mut recipe_holder = commands.get_entity(recipe_holder_entity).unwrap();
                    recipe_holder.despawn_children();
                    create_recipe_list(&mut recipe_holder, strong_recipes_config);
                    create_recipe_list(recipes_holder.0, &mut recipe_holder, strong_recipes_config);
                }
            }
        }
    }
}
fn create_recipe_list(
    parent_entity: Entity,
    recipe_holder: &mut EntityCommands,
    strong_recipes_config: &RecipesConfig,
) {


@@ 206,25 213,56 @@ fn create_recipe_list(
            ui_recipes.push((
                recipe.order,
                (Node {
                    width: Val::Auto,
                    ..Default::default()
                },
                RecipeElement(parent_entity, module_name.clone(), recipe.inputs.clone()),
                BackgroundColor(colors::MANTLE),
                PreviousInteraction(Interaction::None),
                Button),
                (Node {
                    ..Default::default()
                },
                TextFont {
                    font_size: 10.0,
                    ..Default::default()
                },
                Text::new(format!("{}: {}", module_name, resource_list)))
                Text::new(format!("{}: {}", module_name, resource_list))),
            ));
        }
    }
    // ordering stuff
    ui_recipes.sort_by(|a, b| a.0.cmp(&b.0));
    let ui_recipes = ui_recipes.iter().map(|recipe| &recipe.1).collect::<Vec<_>>();
    recipe_holder.with_children(move |parent| {
        for recipe in ui_recipes {
            parent.spawn(recipe.clone());
            parent.spawn(recipe.1.clone())
                .with_child(recipe.2);
        }
    });
}
fn recipe_buttons(
    mut interaction_query: Query<(&Interaction, &mut PreviousInteraction, &mut BackgroundColor, &RecipeElement),
        Changed<Interaction>>,
) {
    for (interaction, mut previous_interaction, mut color, recipe) in &mut interaction_query {
        match *interaction {
            Interaction::Pressed => {
                *color = colors::SURFACE_1.into();
            }
            Interaction::Hovered => {
                *color = colors::SURFACE_0.into();
                if previous_interaction.0 == Interaction::Pressed {
                    // released
                    debug!("{:?} {} {:?}", recipe.0, recipe.1, recipe.2);
                }
            }
            Interaction::None => {
                *color = colors::MANTLE.into();
            }
        }
        previous_interaction.0 = *interaction;
    }
}

fn drill_button(
    mut interaction_query: Query<