Merge branch 'pfau/group-map-indicators' into 'master'

Group map indicators

Closes #885

See merge request veloren/veloren!1633
This commit is contained in:
Monty Marz 2020-12-14 23:00:58 +00:00
commit 2d8e9124f3
33 changed files with 210 additions and 62 deletions

View File

@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Campfire resting heal
- Initial support for game plugins, both server-side and client-side
- Reflective LoD water
- Map indicators for group members
### Changed

BIN
assets/voxygen/element/buttons/checkbox/active.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/buttons/checkbox/hover.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/buttons/checkbox/inactive.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/buttons/checkbox/inactive_hover.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/buttons/checkbox/press.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/buttons/radio/active.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/buttons/radio/hover.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/buttons/radio/inactive.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/buttons/radio/inactive_hover.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/buttons/radio/press.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/map/group_indicator.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/map/group_indicator_arrow_down.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/map/group_indicator_arrow_up.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/map/group_indicator_hover.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -1474,7 +1474,7 @@ impl<'a> System<'a> for Sys {
for (_invite, /*alignment,*/ agent, controller) in
(&invites, /*&alignments,*/ &mut agents, &mut controllers).join()
{
let accept = false; // set back to "matches!(alignment, Alignment::Npc)" when we got better NPC recruitment mechanics
let accept = true; // set back to "matches!(alignment, Alignment::Npc)" when we got better NPC recruitment mechanics
if accept {
// Clear agent comp
*agent = Agent::default();

View File

@ -26,18 +26,6 @@ image_ids! {
flower: "voxygen.element.icons.item_flower",
grass: "voxygen.element.icons.item_grass",
// Checkboxes and Radio buttons
check: "voxygen.element.buttons.radio.inactive",
check_mo: "voxygen.element.buttons.radio.inactive_hover",
check_press: "voxygen.element.buttons.radio.press",
check_checked: "voxygen.element.buttons.radio.active",
check_checked_mo: "voxygen.element.buttons.radio.hover",
checkbox: "voxygen.element.buttons.checkbox.inactive",
checkbox_mo: "voxygen.element.buttons.checkbox.inactive_hover",
checkbox_press: "voxygen.element.buttons.checkbox.press",
checkbox_checked: "voxygen.element.buttons.checkbox.active",
checkbox_checked_mo: "voxygen.element.buttons.checkbox.hover",
// Charwindow
xp_charwindow: "voxygen.element.frames.xp_charwindow",
divider: "voxygen.element.frames.divider_charwindow",
@ -53,6 +41,19 @@ image_ids! {
//////////////////////////////////////////////////////////////////////////////////////////////////////
<ImageGraphic>
// Checkboxes and Radio buttons
check: "voxygen.element.buttons.radio.inactive",
check_mo: "voxygen.element.buttons.radio.inactive_hover",
check_press: "voxygen.element.buttons.radio.press",
check_checked: "voxygen.element.buttons.radio.active",
check_checked_mo: "voxygen.element.buttons.radio.hover",
checkbox: "voxygen.element.buttons.checkbox.inactive",
checkbox_mo: "voxygen.element.buttons.checkbox.inactive_hover",
checkbox_press: "voxygen.element.buttons.checkbox.press",
checkbox_checked: "voxygen.element.buttons.checkbox.active",
checkbox_checked_mo: "voxygen.element.buttons.checkbox.hover",
// Selection Frame
selection: "voxygen.element.frames.selection",
selection_hover: "voxygen.element.frames.selection_hover",
@ -179,6 +180,9 @@ image_ids! {
map_frame_art: "voxygen.element.misc_bg.map_frame_art",
indicator_mmap: "voxygen.element.buttons.indicator_mmap",
indicator_map_overlay: "voxygen.element.buttons.indicator_mmap_small",
indicator_group: "voxygen.element.map.group_indicator",
indicator_group_up: "voxygen.element.map.group_indicator_arrow_up",
indicator_group_down: "voxygen.element.map.group_indicator_arrow_down",
// MiniMap
mmap_frame: "voxygen.element.frames.mmap",

View File

@ -9,14 +9,14 @@ use crate::{
GlobalState,
};
use client::{self, Client};
use common::{comp, terrain::TerrainChunkSize, vol::RectVolSize};
use common::{comp, comp::group::Role, terrain::TerrainChunkSize, vol::RectVolSize};
use common_net::msg::world_msg::SiteKind;
use conrod_core::{
color, position,
widget::{self, Button, Image, Rectangle, Text},
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
};
use specs::WorldExt;
use specs::{saveload::MarkerAllocator, WorldExt};
use vek::*;
widget_ids! {
@ -37,6 +37,8 @@ widget_ids! {
zoom_slider,
mmap_site_icons[],
site_difs[],
member_indicators[],
member_height_indicators[],
map_settings_align,
show_towns_img,
show_towns_box,
@ -641,16 +643,83 @@ impl<'a> Widget for Map<'a> {
}
}
}
// Group member indicators
let client_state = self.client.state();
let stats = client_state.ecs().read_storage::<common::comp::Stats>();
let member_pos = client_state.ecs().read_storage::<common::comp::Pos>();
let group_members = self
.client
.group_members()
.iter()
.filter_map(|(u, r)| match r {
Role::Member => Some(u),
Role::Pet => None,
})
.collect::<Vec<_>>();
let group_size = group_members.len();
//let in_group = !group_members.is_empty();
let uid_allocator = client_state
.ecs()
.read_resource::<common_net::sync::UidAllocator>();
if state.ids.member_indicators.len() < group_size {
state.update(|s| {
s.ids
.member_indicators
.resize(group_size, &mut ui.widget_id_generator())
})
};
for (i, &uid) in group_members.iter().copied().enumerate() {
let entity = uid_allocator.retrieve_entity_internal(uid.into());
let member_pos = entity.and_then(|entity| member_pos.get(entity));
let stats = entity.and_then(|entity| stats.get(entity));
let name = if let Some(stats) = stats {
stats.name.to_string()
} else {
"".to_string()
};
if let Some(member_pos) = member_pos {
// Site pos in world coordinates relative to the player
let rwpos = member_pos.0.xy().map(|e| e as f32) - player_pos;
// Convert to chunk coordinates
let rcpos = rwpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e / sz as f32)
// Add map dragging
+ drag.map(|e| e as f32);
// Convert to fractional coordinates relative to the worldsize
let rfpos = rcpos / max_zoom as f32;
// Convert to relative pixel coordinates from the center of the map
// Accounting for zooming
let rpos = rfpos.map2(map_size, |e, sz| e * sz as f32 * zoom as f32);
if rpos
.map2(map_size, |e, sz| e.abs() > sz as f32 / 2.0)
.reduce_or()
{
continue;
}
let factor = 1.2;
let z_comparison = (member_pos.0.z - player_pos.z) as i32;
Button::image(match z_comparison {
10..=i32::MAX => self.imgs.indicator_group_up,
i32::MIN..=-10 => self.imgs.indicator_group_down,
_ => self.imgs.indicator_group,
})
.x_y_position_relative_to(
state.ids.grid,
position::Relative::Scalar(rpos.x as f64),
position::Relative::Scalar(rpos.y as f64),
)
.w_h(20.0 * factor, 20.0 * factor)
.floating(true)
.with_tooltip(self.tooltip_manager, &name, "", &site_tooltip, TEXT_COLOR)
.set(state.ids.member_indicators[i], ui);
}
}
// Cursor pos relative to playerpos and widget size
// Cursor stops moving on an axis as soon as it's position exceeds the maximum
// // size of the widget
/*let rel = Vec2::from(player_pos).map2(worldsize, |e: f32, sz: f64| {
(e as f64 / sz).clamped(0.0, 1.0)
});*/
//let xy = rel * 760.0;
// Offset from map center due to dragging
let rcpos = drag.map(|e| e as f32);
// Convert to fractional coordinates relative to the worldsize

View File

@ -5,7 +5,7 @@ use super::{
};
use crate::ui::{fonts::Fonts, img_ids};
use client::{self, Client};
use common::{comp, terrain::TerrainChunkSize, vol::RectVolSize};
use common::{comp, comp::group::Role, terrain::TerrainChunkSize, vol::RectVolSize};
use common_net::msg::world_msg::SiteKind;
use conrod_core::{
color, position,
@ -13,7 +13,7 @@ use conrod_core::{
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
};
use specs::WorldExt;
use specs::{saveload::MarkerAllocator, WorldExt};
use vek::*;
widget_ids! {
@ -33,6 +33,7 @@ widget_ids! {
mmap_west,
mmap_site_icons_bgs[],
mmap_site_icons[],
member_indicators[],
}
}
@ -295,12 +296,79 @@ impl<'a> Widget for MiniMap<'a> {
.set(state.ids.mmap_site_icons[i], ui);
}
// Group member indicators
let client_state = self.client.state();
let member_pos = client_state.ecs().read_storage::<common::comp::Pos>();
let group_members = self
.client
.group_members()
.iter()
.filter_map(|(u, r)| match r {
Role::Member => Some(u),
Role::Pet => None,
})
.collect::<Vec<_>>();
let group_size = group_members.len();
//let in_group = !group_members.is_empty();
let uid_allocator = client_state
.ecs()
.read_resource::<common_net::sync::UidAllocator>();
if state.ids.member_indicators.len() < group_size {
state.update(|s| {
s.ids
.member_indicators
.resize(group_size, &mut ui.widget_id_generator())
})
};
for (i, &uid) in group_members.iter().copied().enumerate() {
let entity = uid_allocator.retrieve_entity_internal(uid.into());
let member_pos = entity.and_then(|entity| member_pos.get(entity));
if let Some(member_pos) = member_pos {
// Site pos in world coordinates relative to the player
let rwpos = member_pos.0.xy().map(|e| e as f32) - player_pos;
// Convert to chunk coordinates
let rcpos = rwpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e / sz as f32);
// Convert to fractional coordinates relative to the worldsize
let rfpos = rcpos / max_zoom as f32;
// Convert to unrotated pixel coordinates from the player location on the map
// (the center)
// Accounting for zooming
let rpixpos = rfpos.map2(map_size, |e, sz| e * sz as f32 * zoom as f32);
let rpos = Vec2::unit_x().rotated_z(self.ori.x) * rpixpos.x
+ Vec2::unit_y().rotated_z(self.ori.x) * rpixpos.y;
if rpos
.map2(map_size, |e, sz| e.abs() > sz as f32 / 2.0)
.reduce_or()
{
continue;
}
let factor = 1.2;
let z_comparison = (member_pos.0.z - player_pos.z) as i32;
Button::image(match z_comparison {
10..=i32::MAX => self.imgs.indicator_group_up,
i32::MIN..=-10 => self.imgs.indicator_group_down,
_ => self.imgs.indicator_group,
})
.x_y_position_relative_to(
state.ids.grid,
position::Relative::Scalar(rpos.x as f64),
position::Relative::Scalar(rpos.y as f64),
)
.w_h(16.0 * factor, 16.0 * factor)
.image_color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
.set(state.ids.member_indicators[i], ui);
}
}
// Indicator
let ind_scale = 0.4;
Image::new(self.rot_imgs.indicator_mmap_small.none)
.middle_of(state.ids.grid)
.w_h(32.0 * ind_scale, 37.0 * ind_scale)
.color(Some(UI_HIGHLIGHT_0))
.floating(true)
.set(state.ids.indicator, ui);
// Compass directions

View File

@ -607,7 +607,7 @@ impl<'a> Widget for Skillbar<'a> {
.fabricate(hotbar::Slot::Four, [40.0; 2])
.filled_slot(self.imgs.inv_slot)
.right_from(state.ids.slot3, 0.0);
if let Some((title, desc)) = tooltip_text(hotbar::Slot::Three) {
if let Some((title, desc)) = tooltip_text(hotbar::Slot::Four) {
slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
.set(state.ids.slot4, ui);
} else {
@ -618,7 +618,7 @@ impl<'a> Widget for Skillbar<'a> {
.fabricate(hotbar::Slot::Five, [40.0; 2])
.filled_slot(self.imgs.inv_slot)
.right_from(state.ids.slot4, 0.0);
if let Some((title, desc)) = tooltip_text(hotbar::Slot::Three) {
if let Some((title, desc)) = tooltip_text(hotbar::Slot::Five) {
slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
.set(state.ids.slot5, ui);
} else {