diff --git a/src/gui.rs b/src/gui.rs index 84b0e46..2e373ca 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -185,17 +185,65 @@ fn draw_attribute(name: &str, attribute: &Attribute, y: i32, ctx: &mut Rltk) { } } +struct Tooltip { + lines: Vec, +} + +impl Tooltip { + fn new() -> Tooltip { + Tooltip { lines: Vec::new() } + } + + fn add(&mut self, line: S) { + self.lines.push(line.to_string()); + } + + fn width(&self) -> i32 { + let mut max = 0; + for s in self.lines.iter() { + if s.len() > max { + max = s.len(); + } + } + + max as i32 + 2 + } + + fn height(&self) -> i32 { + self.lines.len() as i32 + 2 + } + + fn render(&self, ctx: &mut Rltk, x: i32, y: i32) { + let box_gray = RGB::from_hex("#999999").expect("Oops"); + let light_gray = RGB::from_hex("#DDDDDD").expect("Oops"); + let white = RGB::named(rltk::WHITE); + let black = RGB::named(rltk::BLACK); + + ctx.draw_box(x, y, self.width() - 1, self.height() - 1, white, box_gray); + + for (i, s) in self.lines.iter().enumerate() { + let col = if i == 0 { white } else { light_gray }; + ctx.print_color(x + 1, y + i as i32 + 1, col, black, &s); + } + } +} + fn draw_tooltips(ecs: &World, ctx: &mut Rltk) { + use rltk::to_cp437; + let (min_x, _max_x, min_y, _max_y) = camera::get_screen_bounds(ecs, ctx); let map = ecs.fetch::(); let names = ecs.read_storage::(); let positions = ecs.read_storage::(); let hidden = ecs.read_storage::(); - + let attributes = ecs.read_storage::(); + let pools = ecs.read_storage::(); + let entities = ecs.entities(); let mouse_pos = ctx.mouse_pos(); - let mut mouse_map_pos = mouse_pos; + let mut mouse_map_pos = mouse_pos.clone(); mouse_map_pos.0 += min_x - 1; mouse_map_pos.1 += min_y - 1; + if mouse_map_pos.0 >= map.width - 1 || mouse_map_pos.1 >= map.height - 1 || mouse_map_pos.0 < 1 @@ -208,92 +256,94 @@ fn draw_tooltips(ecs: &World, ctx: &mut Rltk) { return; } - let mut tooltip: Vec = Vec::new(); - - for (name, position, _hidden) in (&names, &positions, !&hidden).join() { + let mut tip_boxes: Vec = Vec::new(); + for (entity, name, position, _hidden) in (&entities, &names, &positions, !&hidden).join() { if position.x == mouse_map_pos.0 && position.y == mouse_map_pos.1 { - tooltip.push(name.name.to_string()); + let mut tip = Tooltip::new(); + tip.add(name.name.to_string()); + + // Comment on attributes + if let Some(attr) = attributes.get(entity) { + let mut s = String::new(); + if attr.might.bonus < 0 { + s += "Weak. " + } else if attr.might.bonus > 0 { + s += "String. " + } + + if attr.quickness.bonus < 0 { + s += "Clumsy. " + } else if attr.quickness.bonus > 0 { + s += "Agile. " + } + + if attr.fitness.bonus < 0 { + s += "Unhealthy. " + } else if attr.fitness.bonus > 0 { + s += "Healthy. " + } + + if attr.intelligence.bonus < 0 { + s += "Unintelligent. " + } else if attr.intelligence.bonus > 0 { + s += "Smart. " + } + + if s.is_empty() { + s = "Quite Average".to_string(); + } + + tip.add(s); + } + + // Comment on pools + if let Some(stat) = pools.get(entity) { + tip.add(format!("Level: {}", stat.level)); + } + + tip_boxes.push(tip); } } - if !tooltip.is_empty() { - let mut width: i32 = 0; - for s in tooltip.iter() { - if width < s.len() as i32 { - width = s.len() as i32; - } - } - width += 3; + if tip_boxes.is_empty() { + return; + } - if mouse_pos.0 > 40 { - let arrow_pos = Point::new(mouse_pos.0 - 2, mouse_pos.1); - let left_x = mouse_pos.0 - width; - let mut y = mouse_pos.1; + let box_gray = RGB::from_hex("#999999").expect("Oops"); + let white = RGB::named(rltk::WHITE); - for s in tooltip.iter() { - ctx.print_color( - left_x, - y, - RGB::named(rltk::WHITE), - RGB::named(rltk::GREY), - s, - ); - let padding = (width - s.len() as i32) - 1; - for i in 0..padding { - ctx.print_color( - arrow_pos.x - i, - y, - RGB::named(rltk::WHITE), - RGB::named(rltk::GREY), - &" ".to_string(), - ); - } + let arrow; + let arrow_x; + let arrow_y = mouse_pos.1; + if mouse_pos.0 < 40 { + // Render to the left + arrow = to_cp437('→'); + arrow_x = mouse_pos.0 - 1; + } else { + // Render to the right + arrow = to_cp437('←'); + arrow_x = mouse_pos.0 + 1; + } + ctx.set(arrow_x, arrow_y, white, box_gray, arrow); - y += 1; - } + let mut total_height = 0; + for tt in tip_boxes.iter() { + total_height += tt.height(); + } - ctx.print_color( - arrow_pos.x, - arrow_pos.y, - RGB::named(rltk::WHITE), - RGB::named(rltk::GREY), - &"->".to_string(), - ); + let mut y = mouse_pos.1 - (total_height / 2); + while y + (total_height / 2) > 50 { + y -= 1; + } + + for tt in tip_boxes.iter() { + let x = if mouse_pos.0 < 40 { + mouse_pos.0 - (1 + tt.width()) } else { - let arrow_pos = Point::new(mouse_pos.0 + 1, mouse_pos.1); - let left_x = mouse_pos.0 + 3; - let mut y = mouse_pos.1; - - for s in tooltip.iter() { - ctx.print_color( - left_x + 1, - y, - RGB::named(rltk::WHITE), - RGB::named(rltk::GREY), - s, - ); - - let padding = (width - s.len() as i32) - 1; - for i in 0..padding { - ctx.print_color( - arrow_pos.x + 1 + i, - y, - RGB::named(rltk::WHITE), - RGB::named(rltk::GREY), - &" ".to_string(), - ); - } - y += 1; - } - - ctx.print_color( - arrow_pos.x, - arrow_pos.y, - RGB::named(rltk::WHITE), - RGB::named(rltk::GREY), - &"<-".to_string(), - ); - } + mouse_pos.0 + (1 + tt.width()) + }; + tt.render(ctx, x, y); + y += tt.height(); } }