use bevy::input_focus::InputFocus;
use crate::client::colors;
use bevy::prelude::*;
use bevy::ui::FocusPolicy;
use bevy::ui::widget::ImageNodeSize;
use crate::shared::config::part::PartConfig;
use crate::shared::config::recipe::RecipesConfig;
use crate::shared::config::ship_editor::ShipEditorConfig;
pub fn ui_plugin(app: &mut App) {
app
.insert_resource(ShipEditorConfigHolder::default())
.add_systems(Startup, (setup_ui, load_ship_editor_config))
.add_systems(PreUpdate, (fill_part_list, fill_parts));
}
#[derive(Component)]
pub struct PendingPartList;
#[derive(Component)]
pub struct PendingPart(pub Handle<PartConfig>);
#[derive(Component)]
pub struct PartList;
#[derive(Component)]
pub struct PartEntry(pub PartConfig);
#[derive(Resource, Default)]
struct ShipEditorConfigHolder {
handle: Option<Handle<ShipEditorConfig>>,
}
fn load_ship_editor_config(
mut config: ResMut<ShipEditorConfigHolder>,
asset_server: Res<AssetServer>,
) {
config.handle = Some(asset_server.load("config/ship_editor.se.toml"));
}
fn setup_ui(mut commands: Commands) {
commands.spawn((
Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
..Default::default()
},
children![
(
Node {
position_type: PositionType::Absolute,
margin: UiRect::AUTO.with_bottom(Val::Px(0.0)),
width: Val::Percent(50.0),
height: Val::Px(128.0),
..Default::default()
},
BackgroundColor(colors::MANTLE),
children![()]
),
(
Node {
position_type: PositionType::Absolute,
margin: UiRect::AUTO.with_left(Val::Px(0.0)),
width: Val::Px(200.0),
height: Val::Percent(100.0),
..Default::default()
},
BackgroundColor(colors::MANTLE),
children![
(
Node {
display: Display::Grid,
width: Val::Percent(100.0),
height: Val::Percent(100.0),
grid_template_columns: RepeatedGridTrack::auto(2),
grid_template_rows: RepeatedGridTrack::px(2, 100.0),
justify_items: JustifyItems::Center,
align_items: AlignItems::Center,
..Default::default()
},
PendingPartList,
)
]
)
],
));
}
fn fill_part_list(
pending_part_list: Query<Entity, With<PendingPartList>>,
mut commands: Commands,
ship_editor_config_holder: Res<ShipEditorConfigHolder>,
ship_editor_config: Res<Assets<ShipEditorConfig>>,
asset_server: Res<AssetServer>,
) {
let Some(handle) = ship_editor_config_holder.handle.clone() else { return };
if let Some(strong_ship_editor_config) = ship_editor_config.get(&handle) {
for pending_part_list in pending_part_list.iter() {
let mut pending_part_list = commands.entity(pending_part_list);
pending_part_list
.insert(PartList)
.remove::<PendingPartList>();
pending_part_list.with_children(|parent| {
let mut part_list = Vec::with_capacity(strong_ship_editor_config.part_list.len());
for (i, (part_name, icon)) in strong_ship_editor_config.part_list.iter().enumerate() {
part_list.push((
icon.order,
(Node {
width: Val::Px(50.0),
height: Val::Px(50.0),
margin: UiRect::axes(Val::Px(10.0), Val::Px(0.0)),
..Default::default()
},
Button,
PendingPart(asset_server.load(format!("config/parts/{}.part.toml", part_name.to_lowercase())))),
));
}
part_list.sort_by(|a, b| a.0.cmp(&b.0));
for (_, part) in part_list {
parent.spawn(part);
}
});
}
}
}
fn fill_parts(
pending_parts: Query<(Entity, &PendingPart)>,
mut commands: Commands,
assets: Res<Assets<PartConfig>>,
asset_server: Res<AssetServer>,
) {
for (entity, pending_part) in pending_parts.iter() {
if let Some(strong_part_config) = assets.get(&pending_part.0) {
commands.entity(entity)
.insert(PartEntry(strong_part_config.clone()))
.insert(ImageNode::new(asset_server.load(strong_part_config.part.sprite_disconnected.clone())))
.remove::<PendingPart>();
}
}
}