diff --git a/client/src/lib.rs b/client/src/lib.rs index ac164702d6..161caab118 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -352,8 +352,9 @@ impl Client { let MapConfig { gain, is_contours, - is_hill_shaded, + is_height_map, is_political, + is_roads, .. } = *map_config; let mut is_contour_line = false; @@ -365,7 +366,8 @@ impl Client { let alti = alt[pos]; // Compute contours (chunks are assigned in the river code below) let altj = rescale_height(scale_height_big(alti)); - let chunk_contour = (altj * gain / 150.0) as u32; + let contour_interval = 150.0; + let chunk_contour = (altj * gain / contour_interval) as u32; // Compute downhill. let downhill = { @@ -374,7 +376,7 @@ impl Client { for nposi in neighbors(*map_size_lg, posi) { let nbh = alt.raw()[nposi]; let nalt = rescale_height(scale_height_big(nbh)); - let nchunk_contour = (nalt * gain / 150.0) as u32; + let nchunk_contour = (nalt * gain / contour_interval) as u32; if !is_contour_line && chunk_contour > nchunk_contour { is_contour_line = true; } @@ -412,7 +414,7 @@ impl Client { .unwrap_or(wpos + TerrainChunkSize::RECT_SIZE.map(|e| e as i32)); let is_path = rgba.r == 0x37 && rgba.g == 0x29 && rgba.b == 0x23; let rgba = rgba.map(|e: u8| e as f64 / 255.0); - let rgba = if is_hill_shaded { + let rgba = if is_height_map { if is_path { // Path color is Rgb::new(0x37, 0x29, 0x23) Rgba::new(0.9, 0.9, 0.63, 1.0) @@ -427,9 +429,8 @@ impl Client { let lightness = (alt + 0.2).min(1.0) as f64; Rgba::new(lightness, 0.9 * lightness, 0.5 * lightness, 0.5) } - } else if is_contours && is_contour_line { - // Color contour lines - Rgba::new(0.15, 0.15, 0.15, 0.9) + } else if is_roads && is_path { + Rgba::new(0.9, 0.9, 0.63, 1.0) } else if is_political { if is_path { Rgba::new(0.3, 0.3, 0.3, 1.0) @@ -438,6 +439,8 @@ impl Client { } else { Rgba::new(1.0, 0.9, 0.6, 1.0) } + } else if is_contours && is_contour_line { + Rgba::new(0.15, 0.15, 0.15, 0.9) } else { Rgba::new(rgba.r, rgba.g, rgba.b, 0.5) }.map(|e| (e * 255.0) as u8); @@ -485,8 +488,8 @@ impl Client { }, ); // Generate topographic map - //map_config.is_hill_shaded = true; map_config.is_contours = true; + map_config.is_roads = true; map_config.generate( |pos| sample_pos(&map_config, pos, &alt, &rgba, &map_size, &map_size_lg, max_height), |wpos| { diff --git a/common/src/terrain/map.rs b/common/src/terrain/map.rs index f62075182e..74313a9bc5 100644 --- a/common/src/terrain/map.rs +++ b/common/src/terrain/map.rs @@ -321,16 +321,19 @@ pub struct MapConfig<'a> { /// /// Defaults to false. pub is_contours: bool, - /// If true, hill shading is applied to the terrain and all the - /// colors are different. Is incompatible with humidity/temperature/shaded - /// maps. + /// If true, a yellow/terracotta heightmap shading is applied to the + /// terrain and water is a faded blue. /// /// Defaults to false - pub is_hill_shaded: bool, + pub is_height_map: bool, /// If true, terrain is white, rivers, borders, and roads are black. /// /// Defaults to false pub is_political: bool, + /// If true, roads are colored on top of everything else + /// + /// Defaults to false + pub is_roads: bool, } pub const QUADRANTS: usize = 4; @@ -412,8 +415,9 @@ impl<'a> MapConfig<'a> { is_humidity: false, is_debug: false, is_contours: false, - is_hill_shaded: false, + is_height_map: false, is_political: false, + is_roads: false, } } @@ -511,7 +515,7 @@ impl<'a> MapConfig<'a> { let alt = alt as f32; let wposi = pos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32); let rgb = Rgb::new(rgba.r, rgba.g, rgba.b).map(|e| e as f64 / 255.0); - let rgba = rgba.map(|e| e as f64 / 255.0); + let mut rgba = rgba.map(|e| e as f64 / 255.0); // Material properties: // @@ -587,7 +591,7 @@ impl<'a> MapConfig<'a> { if has_river { let water_rgb = Rgb::new(0, ((g_water) * 1.0) as u8, ((b_water) * 1.0) as u8) .map(|e| e as f64 / 255.0); - //rgba = Rgba::new(water_rgb.r, water_rgb.g, water_rgb.b, 1.0); + rgba = Rgba::new(water_rgb.r, water_rgb.g, water_rgb.b, rgba.a); k_s = Rgb::new(1.0, 1.0, 1.0); k_d = water_rgb; k_a = water_rgb; diff --git a/voxygen/src/hud/map.rs b/voxygen/src/hud/map.rs index 172208894c..2205df6b66 100644 --- a/voxygen/src/hud/map.rs +++ b/voxygen/src/hud/map.rs @@ -31,9 +31,7 @@ widget_ids! { location_name, indicator, indicator_overlay, - grid_layer_0, - grid_layer_1, - grid_layer_2, + map_layers[], map_title, qlog_title, zoom_slider, @@ -125,7 +123,6 @@ pub enum Event { ShowDungeons(bool), ShowCaves(bool), ShowTrees(bool), - ShowTopoMap(bool), Close, RequestSiteInfo(SiteId), } @@ -187,7 +184,6 @@ impl<'a> Widget for Map<'a> { let show_castles = self.global_state.settings.interface.map_show_castles; let show_caves = self.global_state.settings.interface.map_show_caves; let show_trees = self.global_state.settings.interface.map_show_trees; - let show_topo_map = self.global_state.settings.interface.map_show_topo_map; let mut events = Vec::new(); let i18n = &self.localized_strings; // Tooltips @@ -269,16 +265,24 @@ impl<'a> Widget for Map<'a> { .color(TEXT_COLOR) .set(state.ids.location_name, ui), }*/ + // Map Layers + // It is assumed that there is at least one layer + if state.ids.map_layers.len() < self.world_map_layers.0.len() { + state.update(|state| { + state + .ids + .map_layers + .resize(self.world_map_layers.0.len(), &mut ui.widget_id_generator()) + }); + } + Image::new(self.imgs.map_frame_art) .mid_top_with_margin_on(state.ids.map_align, 5.0) .w_h(765.0, 765.0) .parent(state.ids.bg) - .set(state.ids.grid_layer_0, ui); - // Map Image - //let (world_map, worldsize) = if !show_topo_map { self.world_map } else { self.world_map_topo }; - let world_map_layer_0 = &self.world_map_layers.0[0]; - let world_map_layer_1 = &self.world_map_layers.0[1]; - let world_map_layer_2 = &self.world_map_layers.0[2]; + .set(state.ids.map_layers[0], ui); + + // Map Size let worldsize = self.world_map_layers.1; // Coordinates @@ -300,7 +304,7 @@ impl<'a> Widget for Map<'a> { // Handle dragging let drag = self.global_state.settings.interface.map_drag; let dragged: Vec2 = ui - .widget_input(state.ids.grid_layer_0) + .widget_input(state.ids.map_layers[0]) .drags() .left() .map(|drag| Vec2::::from(drag.delta_xy)) @@ -328,32 +332,30 @@ impl<'a> Widget for Map<'a> { { events.push(Event::Close); } - // Map layer 0 - Image::new(world_map_layer_0.none) - .mid_top_with_margin_on(state.ids.map_align, 10.0) - .w_h(map_size.x, map_size.y) - .parent(state.ids.bg) - .source_rectangle(rect_src) - .set(state.ids.grid_layer_0, ui); - // Map layer 1 - Image::new(world_map_layer_1.none) - .mid_top_with_margin_on(state.ids.map_align, 10.0) - .w_h(map_size.x, map_size.y) - .parent(state.ids.bg) - .source_rectangle(rect_src) - .graphics_for(state.ids.grid_layer_0) - .set(state.ids.grid_layer_1, ui); - // Map layer 2 - Image::new(world_map_layer_2.none) - .mid_top_with_margin_on(state.ids.map_align, 10.0) - .w_h(map_size.x, map_size.y) - .parent(state.ids.bg) - .source_rectangle(rect_src) - .graphics_for(state.ids.grid_layer_0) - .set(state.ids.grid_layer_2, ui); + + // Map Layer Images + for (index, layer) in self.world_map_layers.0.iter().enumerate() { + if index == 0 { + Image::new(layer.none) + .mid_top_with_margin_on(state.ids.map_align, 10.0) + .w_h(map_size.x, map_size.y) + .parent(state.ids.bg) + .source_rectangle(rect_src) + .set(state.ids.map_layers[index], ui); + } else { + Image::new(layer.none) + .mid_top_with_margin_on(state.ids.map_align, 10.0) + .w_h(map_size.x, map_size.y) + .parent(state.ids.bg) + .source_rectangle(rect_src) + .graphics_for(state.ids.map_layers[0]) + .set(state.ids.map_layers[index], ui); + } + } + // Handle zooming with the mousewheel let scrolled: f64 = ui - .widget_input(state.ids.grid_layer_0) + .widget_input(state.ids.map_layers[0]) .scrolls() .map(|scroll| scroll.y) .sum(); @@ -635,7 +637,7 @@ impl<'a> Widget for Map<'a> { SiteKind::Tree => self.imgs.mmap_site_tree, }) .x_y_position_relative_to( - state.ids.grid_layer_0, + state.ids.map_layers[0], position::Relative::Scalar(rpos.x as f64), position::Relative::Scalar(rpos.y as f64), ) @@ -810,7 +812,7 @@ impl<'a> Widget for Map<'a> { _ => self.imgs.indicator_group, }) .x_y_position_relative_to( - state.ids.grid_layer_0, + state.ids.map_layers[0], position::Relative::Scalar(rpos.x as f64), position::Relative::Scalar(rpos.y as f64), ) @@ -844,7 +846,7 @@ impl<'a> Widget for Map<'a> { { Image::new(self.rot_imgs.indicator_mmap_small.target_north) .x_y_position_relative_to( - state.ids.grid_layer_0, + state.ids.map_layers[0], position::Relative::Scalar(rpos.x as f64), position::Relative::Scalar(rpos.y as f64), ) @@ -863,7 +865,7 @@ impl<'a> Widget for Map<'a> { }; if Button::image(self.imgs.button) .w_h(92.0, icon_size.y) - .mid_bottom_with_margin_on(state.ids.grid_layer_0, -36.0) + .mid_bottom_with_margin_on(state.ids.map_layers[0], -36.0) .hover_image(if recenter { self.imgs.button_hover } else { @@ -895,7 +897,7 @@ impl<'a> Widget for Map<'a> { }; Image::new(self.imgs.m_move_ico) - .bottom_left_with_margins_on(state.ids.grid_layer_0, -36.0, 0.0) + .bottom_left_with_margins_on(state.ids.map_layers[0], -36.0, 0.0) .w_h(icon_size.x, icon_size.y) .color(Some(UI_HIGHLIGHT_0)) .set(state.ids.drag_ico, ui); @@ -903,7 +905,7 @@ impl<'a> Widget for Map<'a> { .right_from(state.ids.drag_ico, 5.0) .font_size(self.fonts.cyri.scale(14)) .font_id(self.fonts.cyri.conrod_id) - .graphics_for(state.ids.grid_layer_0) + .graphics_for(state.ids.map_layers[0]) .color(TEXT_COLOR) .set(state.ids.drag_txt, ui); Image::new(self.imgs.m_scroll_ico) @@ -915,7 +917,7 @@ impl<'a> Widget for Map<'a> { .right_from(state.ids.zoom_ico, 5.0) .font_size(self.fonts.cyri.scale(14)) .font_id(self.fonts.cyri.conrod_id) - .graphics_for(state.ids.grid_layer_0) + .graphics_for(state.ids.map_layers[0]) .color(TEXT_COLOR) .set(state.ids.zoom_txt, ui); diff --git a/voxygen/src/hud/minimap.rs b/voxygen/src/hud/minimap.rs index 36b88b7512..e8c9dc8a70 100644 --- a/voxygen/src/hud/minimap.rs +++ b/voxygen/src/hud/minimap.rs @@ -29,7 +29,7 @@ widget_ids! { mmap_plus, mmap_minus, mmap_north_button, - grid, + map_layers[], indicator, mmap_north, mmap_east, @@ -47,7 +47,7 @@ pub struct MiniMap<'a> { imgs: &'a Imgs, rot_imgs: &'a ImgsRot, - world_map: &'a (&'a img_ids::Rotations, Vec2), + world_map_layers: &'a (Vec, Vec2), fonts: &'a Fonts, #[conrod(common_builder)] common: widget::CommonBuilder, @@ -60,7 +60,7 @@ impl<'a> MiniMap<'a> { client: &'a Client, imgs: &'a Imgs, rot_imgs: &'a ImgsRot, - world_map: &'a (&'a img_ids::Rotations, Vec2), + world_map_layers: &'a (Vec, Vec2), fonts: &'a Fonts, ori: Vec3, global_state: &'a GlobalState, @@ -69,7 +69,7 @@ impl<'a> MiniMap<'a> { client, imgs, rot_imgs, - world_map, + world_map_layers, fonts, common: widget::CommonBuilder::default(), ori, @@ -99,7 +99,7 @@ impl<'a> Widget for MiniMap<'a> { ids: Ids::new(id_gen), zoom: { - let min_world_dim = self.world_map.1.reduce_partial_min() as f64; + let min_world_dim = self.world_map_layers.1.reduce_partial_min() as f64; min_world_dim.min( min_world_dim * (TerrainChunkSize::RECT_SIZE.reduce_partial_max() as f64 / 32.0) @@ -140,9 +140,17 @@ impl<'a> Widget for MiniMap<'a> { .set(state.ids.mmap_frame_bg, ui); // Map size in chunk coords - //let show_topo_map = self.global_state.settings.interface.map_show_topo_map; - //let (world_map, worldsize) = if !show_topo_map { self.world_map } else { self.world_map_topo }; - let (world_map, worldsize) = self.world_map; + let worldsize = self.world_map_layers.1; + // Map Layers + // It is assumed that there is at least one layer + if state.ids.map_layers.len() < self.world_map_layers.0.len() { + state.update(|state| { + state + .ids + .map_layers + .resize(self.world_map_layers.0.len(), &mut ui.widget_id_generator()) + }); + } // Zoom Buttons @@ -250,17 +258,30 @@ impl<'a> Widget for MiniMap<'a> { let map_size = Vec2::new(170.0 * SCALE, 170.0 * SCALE); // Map Image - let world_map_rotation = if is_facing_north { - world_map.none - } else { - world_map.source_north - }; - Image::new(world_map_rotation) - .middle_of(state.ids.mmap_frame_bg) - .w_h(map_size.x, map_size.y) - .parent(state.ids.mmap_frame_bg) - .source_rectangle(rect_src) - .set(state.ids.grid, ui); + // Map Layer Images + for (index, layer) in self.world_map_layers.0.iter().enumerate() { + let world_map_rotation = if is_facing_north { + layer.none + } else { + layer.source_north + }; + if index == 0 { + Image::new(world_map_rotation) + .middle_of(state.ids.mmap_frame_bg) + .w_h(map_size.x, map_size.y) + .parent(state.ids.mmap_frame_bg) + .source_rectangle(rect_src) + .set(state.ids.map_layers[index], ui); + } else { + Image::new(world_map_rotation) + .middle_of(state.ids.mmap_frame_bg) + .w_h(map_size.x, map_size.y) + .parent(state.ids.mmap_frame_bg) + .source_rectangle(rect_src) + .graphics_for(state.ids.map_layers[0]) + .set(state.ids.map_layers[index], ui); + } + } // Map icons if state.ids.mmap_site_icons.len() < self.client.sites().len() { @@ -309,7 +330,7 @@ impl<'a> Widget for MiniMap<'a> { SiteKind::Tree => self.imgs.mmap_site_tree, }) .x_y_position_relative_to( - state.ids.grid, + state.ids.map_layers[0], position::Relative::Scalar(rpos.x as f64), position::Relative::Scalar(rpos.y as f64), ) @@ -329,7 +350,7 @@ impl<'a> Widget for MiniMap<'a> { SiteKind::Cave => Color::Rgba(1.0, 1.0, 1.0, 0.0), SiteKind::Tree => Color::Rgba(1.0, 1.0, 1.0, 0.0), })) - .parent(state.ids.grid) + .parent(state.ids.map_layers[0]) .set(state.ids.mmap_site_icons_bgs[i], ui); Image::new(match &site.kind { SiteKind::Town => self.imgs.mmap_site_town, @@ -400,7 +421,7 @@ impl<'a> Widget for MiniMap<'a> { _ => self.imgs.indicator_group, }) .x_y_position_relative_to( - state.ids.grid, + state.ids.map_layers[0], position::Relative::Scalar(rpos.x as f64), position::Relative::Scalar(rpos.y as f64), ) @@ -418,7 +439,7 @@ impl<'a> Widget for MiniMap<'a> { self.rot_imgs.indicator_mmap_small.none }; Image::new(ind_rotation) - .middle_of(state.ids.grid) + .middle_of(state.ids.map_layers[0]) .w_h(32.0 * ind_scale, 37.0 * ind_scale) .color(Some(UI_HIGHLIGHT_0)) .floating(true) @@ -438,7 +459,7 @@ impl<'a> Widget for MiniMap<'a> { let pos = clamped * (map_size / 2.0 - 10.0); Text::new(name) .x_y_position_relative_to( - state.ids.grid, + state.ids.map_layers[0], position::Relative::Scalar(pos.x), position::Relative::Scalar(pos.y), ) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index b106263d2d..53f64343cf 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -250,7 +250,6 @@ widget_ids! { chat, map, world_map, - world_map_topo, character_window, popup, minimap, @@ -381,7 +380,6 @@ pub enum Event { MapShowCastles(bool), MapShowCaves(bool), MapShowTrees(bool), - MapShowTopo(bool), AdjustWindowSize([u16; 2]), ChangeFullscreenMode(FullScreenSettings), ToggleParticlesEnabled(bool), @@ -2235,7 +2233,7 @@ impl Hud { client, &self.imgs, &self.rot_imgs, - &(&self.world_map_layers.0[1], self.world_map_layers.1), + &self.world_map_layers, &self.fonts, camera.get_orientation(), &global_state, @@ -2827,9 +2825,6 @@ impl Hud { map::Event::ShowTrees(map_show_trees) => { events.push(Event::MapShowTrees(map_show_trees)); }, - map::Event::ShowTopoMap(map_show_topo_map) => { - events.push(Event::MapShowTopo(map_show_topo_map)); - }, map::Event::RequestSiteInfo(id) => { events.push(Event::RequestSiteInfo(id)); }, diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index c6d9a1c924..ff7c946075 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -1356,10 +1356,6 @@ impl PlayState for SessionState { global_state.settings.interface.map_show_trees = map_show_trees; global_state.settings.save_to_file_warn(); }, - HudEvent::MapShowTopo(map_show_topo) => { - global_state.settings.interface.map_show_topo_map = map_show_topo; - global_state.settings.save_to_file_warn(); - }, HudEvent::RequestSiteInfo(id) => { let mut client = self.client.borrow_mut(); client.request_site_economy(id); diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index 311920c5e9..55dcd9851a 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -451,7 +451,6 @@ pub struct InterfaceSettings { pub loading_tips: bool, pub map_show_caves: bool, pub map_show_trees: bool, - pub map_show_topo_map: bool, pub minimap_show: bool, pub minimap_face_north: bool, } @@ -484,7 +483,6 @@ impl Default for InterfaceSettings { loading_tips: true, map_show_caves: true, map_show_trees: true, - map_show_topo_map: false, minimap_show: true, minimap_face_north: false, }