mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add a minimap overlay based on voxel data.
This commit is contained in:
parent
81bba1393a
commit
d1d7147aa6
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -2415,6 +2415,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inline_tweak"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7033e97b20277cc0d043226d1940fa7719ff08d2305d1fc7421e53066d00eb4b"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inotify"
|
name = "inotify"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@ -5644,7 +5653,6 @@ dependencies = [
|
|||||||
name = "veloren-i18n"
|
name = "veloren-i18n"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
|
||||||
"deunicode",
|
"deunicode",
|
||||||
"git2",
|
"git2",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
@ -5826,6 +5834,7 @@ dependencies = [
|
|||||||
"iced_native",
|
"iced_native",
|
||||||
"iced_winit",
|
"iced_winit",
|
||||||
"image",
|
"image",
|
||||||
|
"inline_tweak",
|
||||||
"itertools 0.10.0",
|
"itertools 0.10.0",
|
||||||
"keyboard-keynames",
|
"keyboard-keynames",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
@ -104,7 +104,7 @@ treeculler = "0.2"
|
|||||||
tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] }
|
tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] }
|
||||||
num_cpus = "1.0"
|
num_cpus = "1.0"
|
||||||
# vec_map = { version = "0.8.2" }
|
# vec_map = { version = "0.8.2" }
|
||||||
# inline_tweak = "1.0.2"
|
inline_tweak = "1.0.2"
|
||||||
itertools = "0.10.0"
|
itertools = "0.10.0"
|
||||||
|
|
||||||
# Tracy
|
# Tracy
|
||||||
|
@ -4,22 +4,113 @@ use super::{
|
|||||||
TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
hud::{Graphic, Ui},
|
||||||
session::settings_change::{Interface as InterfaceChange, Interface::*},
|
session::settings_change::{Interface as InterfaceChange, Interface::*},
|
||||||
ui::{fonts::Fonts, img_ids},
|
ui::{fonts::Fonts, img_ids},
|
||||||
GlobalState,
|
GlobalState,
|
||||||
};
|
};
|
||||||
use client::{self, Client};
|
use client::{self, Client};
|
||||||
use common::{comp, comp::group::Role, terrain::TerrainChunkSize, vol::RectVolSize};
|
use common::{
|
||||||
|
comp,
|
||||||
|
comp::group::Role,
|
||||||
|
grid::Grid,
|
||||||
|
terrain::TerrainChunkSize,
|
||||||
|
vol::{ReadVol, RectVolSize},
|
||||||
|
};
|
||||||
use common_net::msg::world_msg::SiteKind;
|
use common_net::msg::world_msg::SiteKind;
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
color, position,
|
color, position,
|
||||||
widget::{self, Button, Image, Rectangle, Text},
|
widget::{self, Button, Image, Rectangle, Text},
|
||||||
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||||
};
|
};
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
use image::{DynamicImage, RgbaImage};
|
||||||
use specs::{saveload::MarkerAllocator, WorldExt};
|
use specs::{saveload::MarkerAllocator, WorldExt};
|
||||||
|
use std::sync::Arc;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
|
pub struct VoxelMinimap {
|
||||||
|
chunk_minimaps: HashMap<Vec2<i32>, HashMap<i32, Grid<[u8; 4]>>>,
|
||||||
|
composited: RgbaImage,
|
||||||
|
image_id: img_ids::Rotations,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VoxelMinimap {
|
||||||
|
pub fn new(ui: &mut Ui) -> Self {
|
||||||
|
let mut composited = RgbaImage::new(96, 96);
|
||||||
|
for x in 0..96 {
|
||||||
|
for y in 0..96 {
|
||||||
|
composited.put_pixel(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
image::Rgba([255 - 2 * x as u8, 255 - 2 * y as u8, 0, 64]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
chunk_minimaps: HashMap::new(),
|
||||||
|
image_id: ui.add_graphic_with_rotations(Graphic::Image(
|
||||||
|
Arc::new(DynamicImage::ImageRgba8(composited.clone())),
|
||||||
|
Some(Rgba::from([0.0, 0.0, 0.0, 0.0])),
|
||||||
|
)),
|
||||||
|
composited,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn maintain(&mut self, client: &Client, ui: &mut Ui) {
|
||||||
|
let terrain = client.state().terrain();
|
||||||
|
for (key, chunk) in terrain.iter() {
|
||||||
|
if !self.chunk_minimaps.contains_key(&key) {
|
||||||
|
let mut layers = HashMap::new();
|
||||||
|
for z in chunk.get_min_z()..chunk.get_max_z() {
|
||||||
|
let grid = Grid::populate_from(Vec2::new(32, 32), |v| {
|
||||||
|
chunk
|
||||||
|
.get(Vec3::new(v.x, v.y, z))
|
||||||
|
.ok()
|
||||||
|
.and_then(|block| block.get_color())
|
||||||
|
.map(|rgb| [rgb.r, rgb.g, rgb.b, 128])
|
||||||
|
.unwrap_or([0, 0, 0, 0])
|
||||||
|
});
|
||||||
|
layers.insert(z, grid);
|
||||||
|
}
|
||||||
|
self.chunk_minimaps.insert(key, layers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let player = client.entity();
|
||||||
|
if let Some(pos) = client.state().ecs().read_storage::<comp::Pos>().get(player) {
|
||||||
|
let pos = pos.0;
|
||||||
|
let cpos: Vec2<i32> = (pos.xy() / 32.0).as_();
|
||||||
|
for i in -1..=1 {
|
||||||
|
for j in -1..=1 {
|
||||||
|
let coff = Vec2::new(i, j);
|
||||||
|
if let Some(grid) = self
|
||||||
|
.chunk_minimaps
|
||||||
|
.get(&(cpos + coff))
|
||||||
|
.and_then(|l| l.get(&(pos.z as i32)))
|
||||||
|
{
|
||||||
|
for x in 0..32 {
|
||||||
|
for y in 0..32 {
|
||||||
|
self.composited.put_pixel(
|
||||||
|
(i + 1) as u32 * 32 + x,
|
||||||
|
(j + 1) as u32 * 32 + y,
|
||||||
|
grid.get(Vec2::new(x, y).as_())
|
||||||
|
.map(|c| image::Rgba(*c))
|
||||||
|
.unwrap_or(image::Rgba([0, 0, 0, 0])),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: don't leak memory, replace
|
||||||
|
self.image_id = ui.add_graphic_with_rotations(Graphic::Image(
|
||||||
|
Arc::new(DynamicImage::ImageRgba8(self.composited.clone())),
|
||||||
|
Some(Rgba::from([0.0, 0.0, 0.0, 0.0])),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
widget_ids! {
|
widget_ids! {
|
||||||
struct Ids {
|
struct Ids {
|
||||||
mmap_frame,
|
mmap_frame,
|
||||||
@ -40,6 +131,7 @@ widget_ids! {
|
|||||||
mmap_site_icons[],
|
mmap_site_icons[],
|
||||||
member_indicators[],
|
member_indicators[],
|
||||||
location_marker,
|
location_marker,
|
||||||
|
voxel_minimap,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +148,7 @@ pub struct MiniMap<'a> {
|
|||||||
ori: Vec3<f32>,
|
ori: Vec3<f32>,
|
||||||
global_state: &'a GlobalState,
|
global_state: &'a GlobalState,
|
||||||
location_marker: Option<Vec2<f32>>,
|
location_marker: Option<Vec2<f32>>,
|
||||||
|
voxel_minimap: &'a VoxelMinimap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MiniMap<'a> {
|
impl<'a> MiniMap<'a> {
|
||||||
@ -69,6 +162,7 @@ impl<'a> MiniMap<'a> {
|
|||||||
ori: Vec3<f32>,
|
ori: Vec3<f32>,
|
||||||
global_state: &'a GlobalState,
|
global_state: &'a GlobalState,
|
||||||
location_marker: Option<Vec2<f32>>,
|
location_marker: Option<Vec2<f32>>,
|
||||||
|
voxel_minimap: &'a VoxelMinimap,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
show,
|
show,
|
||||||
@ -81,6 +175,7 @@ impl<'a> MiniMap<'a> {
|
|||||||
ori,
|
ori,
|
||||||
global_state,
|
global_state,
|
||||||
location_marker,
|
location_marker,
|
||||||
|
voxel_minimap,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,6 +211,8 @@ impl<'a> Widget for MiniMap<'a> {
|
|||||||
let show_minimap = self.global_state.settings.interface.minimap_show;
|
let show_minimap = self.global_state.settings.interface.minimap_show;
|
||||||
let is_facing_north = self.global_state.settings.interface.minimap_face_north;
|
let is_facing_north = self.global_state.settings.interface.minimap_face_north;
|
||||||
let show_topo_map = self.global_state.settings.interface.map_show_topo_map;
|
let show_topo_map = self.global_state.settings.interface.map_show_topo_map;
|
||||||
|
//let show_voxel_map = self.global_state.settings.interface.map_show_voxel_map;
|
||||||
|
let show_voxel_map = true;
|
||||||
let orientation = if is_facing_north {
|
let orientation = if is_facing_north {
|
||||||
Vec3::new(0.0, 1.0, 0.0)
|
Vec3::new(0.0, 1.0, 0.0)
|
||||||
} else {
|
} else {
|
||||||
@ -277,6 +374,36 @@ impl<'a> Widget for MiniMap<'a> {
|
|||||||
.set(state.ids.map_layers[index], ui);
|
.set(state.ids.map_layers[index], ui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if show_voxel_map {
|
||||||
|
let voxelmap_rotation = if is_facing_north {
|
||||||
|
self.voxel_minimap.image_id.none
|
||||||
|
} else {
|
||||||
|
self.voxel_minimap.image_id.source_north
|
||||||
|
};
|
||||||
|
use inline_tweak::tweak;
|
||||||
|
/*let rect_src = position::Rect::from_xy_dim(
|
||||||
|
[
|
||||||
|
player_pos.x as f64 / TerrainChunkSize::RECT_SIZE.x as f64 + tweak!(0.0),
|
||||||
|
worldsize.y as f64 -
|
||||||
|
(player_pos.y as f64 / TerrainChunkSize::RECT_SIZE.y as f64) + tweak!(0.0),
|
||||||
|
],
|
||||||
|
[w_src / tweak!(32768.0), h_src / tweak!(32768.0)],
|
||||||
|
);*/
|
||||||
|
let rect_src = position::Rect::from_xy_dim([tweak!(48.0), tweak!(48.0)], [
|
||||||
|
tweak!(96.0),
|
||||||
|
tweak!(96.0),
|
||||||
|
]);
|
||||||
|
Image::new(voxelmap_rotation)
|
||||||
|
.middle_of(state.ids.mmap_frame_bg)
|
||||||
|
.w_h(
|
||||||
|
map_size.x * 3.0 * (zoom / max_zoom),
|
||||||
|
map_size.y * 3.0 * zoom / max_zoom,
|
||||||
|
)
|
||||||
|
.parent(state.ids.mmap_frame_bg)
|
||||||
|
.source_rectangle(rect_src)
|
||||||
|
.graphics_for(state.ids.map_layers[0])
|
||||||
|
.set(state.ids.voxel_minimap, ui);
|
||||||
|
}
|
||||||
|
|
||||||
// Map icons
|
// Map icons
|
||||||
if state.ids.mmap_site_icons.len() < self.client.sites().len() {
|
if state.ids.mmap_site_icons.len() < self.client.sites().len() {
|
||||||
|
@ -39,7 +39,7 @@ use group::Group;
|
|||||||
use img_ids::Imgs;
|
use img_ids::Imgs;
|
||||||
use item_imgs::ItemImgs;
|
use item_imgs::ItemImgs;
|
||||||
use map::Map;
|
use map::Map;
|
||||||
use minimap::MiniMap;
|
use minimap::{MiniMap, VoxelMinimap};
|
||||||
use popup::Popup;
|
use popup::Popup;
|
||||||
use prompt_dialog::PromptDialog;
|
use prompt_dialog::PromptDialog;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -785,6 +785,7 @@ pub struct Hud {
|
|||||||
events: Vec<Event>,
|
events: Vec<Event>,
|
||||||
crosshair_opacity: f32,
|
crosshair_opacity: f32,
|
||||||
floaters: Floaters,
|
floaters: Floaters,
|
||||||
|
voxel_minimap: VoxelMinimap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hud {
|
impl Hud {
|
||||||
@ -841,6 +842,7 @@ impl Hud {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
voxel_minimap: VoxelMinimap::new(&mut ui),
|
||||||
ui,
|
ui,
|
||||||
imgs,
|
imgs,
|
||||||
world_map,
|
world_map,
|
||||||
@ -928,6 +930,7 @@ impl Hud {
|
|||||||
) -> Vec<Event> {
|
) -> Vec<Event> {
|
||||||
span!(_guard, "update_layout", "Hud::update_layout");
|
span!(_guard, "update_layout", "Hud::update_layout");
|
||||||
let mut events = std::mem::replace(&mut self.events, Vec::new());
|
let mut events = std::mem::replace(&mut self.events, Vec::new());
|
||||||
|
self.voxel_minimap.maintain(&client, &mut self.ui);
|
||||||
let (ref mut ui_widgets, ref mut item_tooltip_manager, ref mut tooltip_manager) =
|
let (ref mut ui_widgets, ref mut item_tooltip_manager, ref mut tooltip_manager) =
|
||||||
&mut self.ui.set_widgets();
|
&mut self.ui.set_widgets();
|
||||||
// self.ui.set_item_widgets(); pulse time for pulsating elements
|
// self.ui.set_item_widgets(); pulse time for pulsating elements
|
||||||
@ -2316,6 +2319,7 @@ impl Hud {
|
|||||||
camera.get_orientation(),
|
camera.get_orientation(),
|
||||||
&global_state,
|
&global_state,
|
||||||
self.show.location_marker,
|
self.show.location_marker,
|
||||||
|
&self.voxel_minimap,
|
||||||
)
|
)
|
||||||
.set(self.ids.minimap, ui_widgets)
|
.set(self.ids.minimap, ui_widgets)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user