use bevy::prelude::*; use bevy_ratatui::RatatuiContext; use jong::game::hand::DrawnTile; use jong::game::player::{MainPlayer, Player}; use jong::tile::Tile; use rand::rand_core::block::BlockRngCore; use ratatui::style::Styled; use ratatui::widgets::{Block, Borders, Widget}; use crate::tui::render::tile::draw_tile; use crate::tui::{ input::mouse::PickRegion, render::{Hovered, hand, tile::RenderedTile}, }; pub(crate) fn draw_ingame( mut commands: Commands, mut tui_ctx: ResMut, tiles: Query<&Tile>, hovered_entity: Query>, main_player: Single, With)>, rendered_tiles: Populated<&RenderedTile>, rendered_hand: Res, drawn_tile: Option>>, ) -> Result { use ratatui::layout::Flex; use ratatui::prelude::*; tui_ctx.draw(|frame| { // debug!("{}", frame.area()); let term_area = frame.area(); // TODO this is gross let constraints = [Constraint::Fill(3), Constraint::Fill(18)]; let horizontal_slicer_right = Layout::horizontal(constraints); let vertical_slicer_bottom = Layout::vertical(constraints); let horizontal_slicer_left = Layout::horizontal(constraints.iter().rev()); let vertical_slicer_top = Layout::vertical(constraints.iter().rev()); let [left_hand, this_hand] = horizontal_slicer_right.areas::<2>(term_area); let [_, mut left_hand] = vertical_slicer_bottom.areas::<2>(left_hand); let [_, mut this_hand] = vertical_slicer_top.areas::<2>(this_hand); let [cross_hand, right_hand] = horizontal_slicer_left.areas::<2>(term_area); let [mut right_hand, _] = vertical_slicer_top.areas::<2>(right_hand); let [mut cross_hand, _] = vertical_slicer_bottom.areas::<2>(cross_hand); let margin = Margin::new( (left_hand.width + right_hand.width) / 2, (cross_hand.height + this_hand.height) / 2, ); let pond_area = term_area.inner(margin); let all_pond = Layout::horizontal([Constraint::Fill(1); 3]); let cross_pond = Layout::vertical([Constraint::Fill(1), Constraint::Max(1), Constraint::Fill(1)]); let [mut left_pond, center, mut right_pond] = all_pond.areas::<3>(pond_area); let [cross_pond, compass, this_pond] = cross_pond.areas::<3>(center); // let shift = left_pond.height - cross_pond.height; left_pond.height = cross_pond.height; left_pond.y += cross_pond.height / 2; right_pond.height = cross_pond.height; right_pond.y += cross_pond.height / 2; let debug_block = Block::new().borders(Borders::ALL); frame.render_widget(debug_block.clone(), this_hand); frame.render_widget(debug_block.clone(), left_hand); frame.render_widget(debug_block.clone(), cross_hand); frame.render_widget(debug_block.clone(), right_hand); frame.render_widget(debug_block.clone(), this_pond); frame.render_widget(debug_block.clone(), left_pond); frame.render_widget(debug_block.clone(), cross_pond); frame.render_widget(debug_block.clone(), right_pond); // TODO attempt to merge blocks on smol term? if let Some(hand) = rendered_hand.0.get(&*main_player) { let hand_area_layout = Layout::horizontal([ Constraint::Max(hand.len() as u16 * 5), Constraint::Max(if drawn_tile.is_some() { 7 } else { 0 }), Constraint::Fill(1), ]) .flex(Flex::SpaceBetween); let this_clamped = this_hand.height.abs_diff(5); if let Some(val) = this_hand.height.checked_sub(this_clamped) { this_hand.height = 4 } else { // FIXME show error panic!("terminal too small!"); } this_hand.y += this_clamped + 1; let [this_hand, mut this_drawn, this_meld] = hand_area_layout.areas::<3>(this_hand); // this_hand let mut constraints = vec![Constraint::Max(5); hand.len()]; constraints.push(Constraint::Fill(1)); let layout = Layout::horizontal(constraints).flex(Flex::Start); let hand_areas = layout.split(this_hand); for (tile, mut tile_area) in hand.iter().zip(hand_areas.iter().cloned()) { // tile_area.height = 4; let mut widget = rendered_tiles.get(*tile).unwrap().0.clone(); if hovered_entity.contains(*tile) { widget = widget.add_modifier(Modifier::BOLD); if let Some(val) = tile_area.y.checked_sub(1) { tile_area.y = val } else { // FIXME show error panic!("terminal too small!"); } } commands .entity(*tile) .insert(PickRegion { area: tile_area }); frame.render_widget(widget, tile_area); } // this_drawn if let Some(tile) = drawn_tile { // this_drawn.height = 4; this_drawn.width = 5; this_drawn.x += 2; let mut widget = draw_tile(tiles.get(tile.0).unwrap()); if hovered_entity.contains(tile.0) { widget = widget.add_modifier(Modifier::BOLD); if let Some(val) = this_drawn.y.checked_sub(1) { this_drawn.y = val } else { // FIXME show error panic!("terminal too small!"); } } commands .entity(tile.0) .insert(PickRegion { area: this_drawn }); frame.render_widget(widget, this_drawn); } } })?; Ok(()) }