Inventory UI & system combined. Dropping works, pickup works, work on UI
This commit is contained in:
parent
8c30ba6d9f
commit
6c243e5f4d
@ -52,6 +52,7 @@ impl PlayerInventory {
|
||||
let mut inventory_slot = match slot {
|
||||
PlayerInventorySlotType::Primary => &mut self.primary,
|
||||
PlayerInventorySlotType::Secondary => &mut self.secondary,
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
let Some(firearm) = item.get_firearm() else { return; };
|
||||
inventory_slot.item = Some(firearm.get_item_box());
|
||||
@ -60,6 +61,7 @@ impl PlayerInventory {
|
||||
match slot {
|
||||
PlayerInventorySlotType::Primary => self.primary.item = None,
|
||||
PlayerInventorySlotType::Secondary => self.secondary.item = None,
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -91,6 +93,7 @@ pub fn drop_slot_in_game_world(
|
||||
PlayerInventorySlotType::Secondary => {
|
||||
player_inventory.get_secondary_mut()
|
||||
},
|
||||
_ => { unimplemented!() }
|
||||
};
|
||||
|
||||
match &item_inventory_slot.item {
|
||||
@ -111,7 +114,7 @@ pub fn drop_slot_in_game_world(
|
||||
);
|
||||
}
|
||||
player_inventory.drop_item(PlayerInventorySlotType::Primary);
|
||||
inventory_changed_events.send(PlayerInventoryChangedEvent { item: Some(firearm.get_item_arc()), slot_type: PlayerInventorySlotType::Primary });
|
||||
inventory_changed_events.send(PlayerInventoryChangedEvent { item: None, slot_type: PlayerInventorySlotType::Primary });
|
||||
}
|
||||
FirearmType::Secondary => {
|
||||
if let Some(secondary) = player_inventory.get_secondary() {
|
||||
@ -124,7 +127,7 @@ pub fn drop_slot_in_game_world(
|
||||
);
|
||||
}
|
||||
player_inventory.drop_item(PlayerInventorySlotType::Secondary);
|
||||
inventory_changed_events.send(PlayerInventoryChangedEvent { item: Some(firearm.get_item_arc()), slot_type: PlayerInventorySlotType::Secondary });
|
||||
inventory_changed_events.send(PlayerInventoryChangedEvent { item: None, slot_type: PlayerInventorySlotType::Secondary });
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2,10 +2,23 @@ use bevy::reflect::Reflect;
|
||||
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Reflect, Default)]
|
||||
#[derive(Clone, Copy, Reflect, Default, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum PlayerInventorySlotType {
|
||||
#[default]
|
||||
Primary,
|
||||
Secondary,
|
||||
Backpack,
|
||||
BodyArmor,
|
||||
//Slots, // TODO: Pass which slot
|
||||
}
|
||||
|
||||
impl PlayerInventorySlotType {
|
||||
pub fn to_slot_title(&self) -> String {
|
||||
match self {
|
||||
PlayerInventorySlotType::Primary => String::from("Primary"),
|
||||
PlayerInventorySlotType::Secondary => String::from("Secondary"),
|
||||
PlayerInventorySlotType::Backpack => String::from("Backpack"),
|
||||
PlayerInventorySlotType::BodyArmor => String::from("Body Armor"),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,9 @@
|
||||
use bevy::ecs::component::Component;
|
||||
|
||||
use crate::comps::core::inventory::slot::PlayerInventorySlotType;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct InventoryScreenUiMarker;
|
||||
|
||||
#[derive(Component, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct InventorySlotUiMarker(pub PlayerInventorySlotType);
|
@ -28,8 +28,7 @@ pub fn update_player_inventory_system(
|
||||
|
||||
player_inventory::drop_slot_in_game_world(&mut commands, player_transform, &mut inventory_changed_events, &mut player_inventory, &assets_gltf, &loaded_gltf_assets, event.item.get_item_slot());
|
||||
player_inventory.pickup_item(event.item.as_ref(), event.item.get_item_slot());
|
||||
// TODO: Equip
|
||||
|
||||
inventory_changed_events.send(PlayerInventoryChangedEvent { item: Some(event.item.clone()), slot_type: event.item.get_item_slot() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
22
src/ui/game/inventory/interactables.rs
Normal file
22
src/ui/game/inventory/interactables.rs
Normal file
@ -0,0 +1,22 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::comps::core::markers::inventory_screen::InventorySlotUiMarker;
|
||||
|
||||
pub fn update_interactable_slot(
|
||||
//mut commands: Commands,
|
||||
mut query: Query<(Entity, &Interaction, &mut Style), (Changed<Interaction>, With<InventorySlotUiMarker>)>
|
||||
) {
|
||||
for (_, interaction, mut style) in query.iter_mut() {
|
||||
match *interaction {
|
||||
Interaction::Pressed => {
|
||||
println!("Clicked an Inventory Slot");
|
||||
}
|
||||
Interaction::Hovered => {
|
||||
style.border = UiRect::all(Val::Px(1.5));
|
||||
}
|
||||
Interaction::None => {
|
||||
style.border = UiRect::all(Val::Px(0.5));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
use bevy::{prelude::*, ui::FocusPolicy};
|
||||
|
||||
use crate::{
|
||||
comps::core::markers::inventory_screen::InventoryScreenUiMarker,
|
||||
comps::core::{markers::inventory_screen::{InventoryScreenUiMarker, InventorySlotUiMarker}, inventory::slot::PlayerInventorySlotType, events::inventory_changed::PlayerInventoryChangedEvent},
|
||||
ui::game::game_ui_state::{GameUiState, GameUiWindow},
|
||||
};
|
||||
|
||||
@ -23,7 +23,7 @@ pub fn setup_inventory_screen(mut commands: Commands) {
|
||||
..Default::default()
|
||||
},
|
||||
visibility: Visibility::Hidden,
|
||||
background_color: BackgroundColor(Color::rgba(0.0, 0.0, 0.0, 0.9)),
|
||||
background_color: BackgroundColor(Color::rgba(0.0, 0.0, 0.0, 0.8)),
|
||||
focus_policy: FocusPolicy::Block,
|
||||
..Default::default()
|
||||
},
|
||||
@ -36,28 +36,30 @@ pub fn setup_inventory_screen(mut commands: Commands) {
|
||||
.spawn(NodeBundle {
|
||||
style: Style {
|
||||
display: Display::Flex,
|
||||
width: Val::Percent(50.0),
|
||||
width: Val::Percent(40.0),
|
||||
height: Val::Percent(100.0),
|
||||
align_items: AlignItems::Center,
|
||||
justify_content: JustifyContent::Center,
|
||||
justify_content: JustifyContent::SpaceEvenly,
|
||||
padding: UiRect::all(Val::Percent(5.0)),
|
||||
flex_direction: FlexDirection::Column,
|
||||
border: UiRect::all(Val::Px(0.5)),
|
||||
..Default::default()
|
||||
},
|
||||
background_color: BackgroundColor(Color::RED),
|
||||
background_color: BackgroundColor(Color::Rgba { red: 0.0, green: 0.0, blue: 0.0, alpha: 0.86 }),
|
||||
border_color: BorderColor(Color::WHITE),
|
||||
..Default::default()
|
||||
})
|
||||
.set_parent(background_id)
|
||||
.id();
|
||||
// Right panel
|
||||
let right_panel_id = commands
|
||||
let _right_panel_id = commands
|
||||
.spawn(NodeBundle {
|
||||
style: Style {
|
||||
display: Display::Flex,
|
||||
width: Val::Percent(50.0),
|
||||
height: Val::Percent(100.0),
|
||||
align_items: AlignItems::Center,
|
||||
justify_content: JustifyContent::Center,
|
||||
justify_content: JustifyContent::SpaceEvenly,
|
||||
padding: UiRect::all(Val::Percent(5.0)),
|
||||
flex_direction: FlexDirection::Column,
|
||||
..Default::default()
|
||||
@ -66,6 +68,130 @@ pub fn setup_inventory_screen(mut commands: Commands) {
|
||||
})
|
||||
.set_parent(background_id)
|
||||
.id();
|
||||
// Inventory Equipment title
|
||||
let _ = commands.spawn(
|
||||
TextBundle {
|
||||
text: Text::from_section("Equipment", TextStyle { font_size: 32.0, color: Color::WHITE, ..Default::default() }),
|
||||
..Default::default()
|
||||
}.with_text_alignment(TextAlignment::Center)
|
||||
).set_parent(left_panel_id);
|
||||
|
||||
// First slot (Backpack and knife)
|
||||
let body_slots_container = commands
|
||||
.spawn(NodeBundle {
|
||||
style: Style {
|
||||
display: Display::Flex,
|
||||
width: Val::Percent(90.0),
|
||||
height: Val::Percent(30.0),
|
||||
align_items: AlignItems::Center,
|
||||
justify_content: JustifyContent::SpaceBetween,
|
||||
//padding: UiRect::all(Val::Percent(5.0)),
|
||||
flex_direction: FlexDirection::Row,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}).set_parent(left_panel_id).id();
|
||||
// Body Armor container
|
||||
let body_armor_slot_container = commands
|
||||
.spawn((NodeBundle {
|
||||
style: Style {
|
||||
display: Display::Flex,
|
||||
width: Val::Percent(47.0),
|
||||
height: Val::Percent(100.0),
|
||||
align_items: AlignItems::Center,
|
||||
justify_content: JustifyContent::Center,
|
||||
padding: UiRect::all(Val::Percent(5.0)),
|
||||
flex_direction: FlexDirection::Column,
|
||||
border: UiRect::all(Val::Px(0.5)),
|
||||
..Default::default()
|
||||
},
|
||||
border_color: BorderColor(Color::WHITE),
|
||||
background_color: BackgroundColor(Color::Rgba { red: 0.0, green: 0.0, blue: 0.0, alpha: 0.96 }),
|
||||
..Default::default()
|
||||
}, Interaction::default(), InventorySlotUiMarker(PlayerInventorySlotType::BodyArmor)
|
||||
)).set_parent(body_slots_container).id();
|
||||
// Backpack container
|
||||
let backpack_slot_container = commands
|
||||
.spawn((NodeBundle {
|
||||
style: Style {
|
||||
display: Display::Flex,
|
||||
width: Val::Percent(47.0),
|
||||
height: Val::Percent(100.0),
|
||||
align_items: AlignItems::Center,
|
||||
justify_content: JustifyContent::Center,
|
||||
padding: UiRect::all(Val::Percent(5.0)),
|
||||
flex_direction: FlexDirection::Column,
|
||||
border: UiRect::all(Val::Px(0.5)),
|
||||
..Default::default()
|
||||
},
|
||||
border_color: BorderColor(Color::WHITE),
|
||||
background_color: BackgroundColor(Color::Rgba { red: 0.0, green: 0.0, blue: 0.0, alpha: 0.96 }),
|
||||
..Default::default()
|
||||
}, Interaction::default(), InventorySlotUiMarker(PlayerInventorySlotType::Backpack)
|
||||
)).set_parent(body_slots_container).id();
|
||||
// Body Armor Text
|
||||
commands.spawn(TextBundle {
|
||||
text: Text::from_section("Body Armor", TextStyle { font_size: 28.0, color: Color::WHITE, ..Default::default() }),
|
||||
..Default::default()
|
||||
}.with_text_alignment(TextAlignment::Center))
|
||||
.set_parent(body_armor_slot_container);
|
||||
// Backpack Text
|
||||
commands.spawn(TextBundle {
|
||||
text: Text::from_section("Backpack", TextStyle { font_size: 28.0, color: Color::WHITE, ..Default::default() }),
|
||||
..Default::default()
|
||||
}.with_text_alignment(TextAlignment::Center))
|
||||
.set_parent(backpack_slot_container);
|
||||
|
||||
// Primary Slot
|
||||
let primary_slot = commands
|
||||
.spawn((NodeBundle {
|
||||
style: Style {
|
||||
display: Display::Flex,
|
||||
width: Val::Percent(90.0),
|
||||
height: Val::Percent(20.0),
|
||||
align_items: AlignItems::Center,
|
||||
justify_content: JustifyContent::Center,
|
||||
padding: UiRect::all(Val::Percent(5.0)),
|
||||
flex_direction: FlexDirection::Column,
|
||||
border: UiRect::all(Val::Px(0.5)),
|
||||
..Default::default()
|
||||
},
|
||||
border_color: BorderColor(Color::WHITE),
|
||||
background_color: BackgroundColor(Color::Rgba { red: 0.0, green: 0.0, blue: 0.0, alpha: 0.96 }),
|
||||
..Default::default()
|
||||
}, Interaction::default(), InventorySlotUiMarker(PlayerInventorySlotType::Primary)
|
||||
)).set_parent(left_panel_id).id();
|
||||
// Secondary Slot
|
||||
let secondary_slot = commands
|
||||
.spawn((NodeBundle {
|
||||
style: Style {
|
||||
display: Display::Flex,
|
||||
width: Val::Percent(90.0),
|
||||
height: Val::Percent(20.0),
|
||||
align_items: AlignItems::Center,
|
||||
justify_content: JustifyContent::Center,
|
||||
padding: UiRect::all(Val::Percent(5.0)),
|
||||
flex_direction: FlexDirection::Column,
|
||||
border: UiRect::all(Val::Px(0.5)),
|
||||
..Default::default()
|
||||
},
|
||||
border_color: BorderColor(Color::WHITE),
|
||||
background_color: BackgroundColor(Color::Rgba { red: 0.0, green: 0.0, blue: 0.0, alpha: 0.96 }),
|
||||
..Default::default()
|
||||
}, Interaction::default(), InventorySlotUiMarker(PlayerInventorySlotType::Secondary)
|
||||
)).set_parent(left_panel_id).id();
|
||||
// Primary Slot Text
|
||||
commands.spawn(TextBundle {
|
||||
text: Text::from_section("Primary", TextStyle { font_size: 28.0, color: Color::WHITE, ..Default::default() }),
|
||||
..Default::default()
|
||||
}.with_text_alignment(TextAlignment::Center))
|
||||
.set_parent(primary_slot);
|
||||
// Secondary Slot Text
|
||||
commands.spawn(TextBundle {
|
||||
text: Text::from_section("Secondary", TextStyle { font_size: 28.0, color: Color::WHITE, ..Default::default() }),
|
||||
..Default::default()
|
||||
}.with_text_alignment(TextAlignment::Center))
|
||||
.set_parent(secondary_slot);
|
||||
|
||||
}
|
||||
|
||||
@ -73,6 +199,9 @@ pub fn update_inventory_screen(
|
||||
//mut commands: Commands,
|
||||
game_ui_state: Res<GameUiState>,
|
||||
mut inventory_screen_query: Query<&mut Visibility, With<InventoryScreenUiMarker>>,
|
||||
inventory_slot_query: Query<(&InventorySlotUiMarker, &Children)>,
|
||||
mut inventory_slot_text_query: Query<(&mut Text, Entity)>,
|
||||
mut inventory_changed_events: EventReader<PlayerInventoryChangedEvent>,
|
||||
) {
|
||||
for mut visibility in inventory_screen_query.iter_mut() {
|
||||
if game_ui_state.is_showing_window(GameUiWindow::InventoryMenu) {
|
||||
@ -81,4 +210,23 @@ pub fn update_inventory_screen(
|
||||
*visibility = Visibility::Hidden;
|
||||
}
|
||||
}
|
||||
|
||||
for event in inventory_changed_events.read() {
|
||||
for (inventory_slot_ui_marker, children) in inventory_slot_query.iter() {
|
||||
for (mut text, text_entity) in inventory_slot_text_query.iter_mut() {
|
||||
for child in children {
|
||||
if child == &text_entity && event.slot_type == inventory_slot_ui_marker.0 {
|
||||
// Mutate text
|
||||
if let Some(section) = text.sections.first_mut() {
|
||||
section.value = match &event.item {
|
||||
Some(item) => item.inventory_title(),
|
||||
None => inventory_slot_ui_marker.0.to_slot_title(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,2 +1,3 @@
|
||||
pub mod menu;
|
||||
pub mod plugin;
|
||||
pub mod interactables;
|
@ -1,12 +1,12 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use super::menu::{setup_inventory_screen, update_inventory_screen};
|
||||
use super::{menu::{setup_inventory_screen, update_inventory_screen}, interactables::update_interactable_slot};
|
||||
|
||||
pub struct InventoryMenuPlugin;
|
||||
|
||||
impl Plugin for InventoryMenuPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(Startup, setup_inventory_screen);
|
||||
app.add_systems(Update, update_inventory_screen);
|
||||
app.add_systems(Update, (update_inventory_screen, update_interactable_slot));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user