mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added debug cylinder for selected entity. Added frame time graph.
This commit is contained in:
parent
483711ba67
commit
1c80ab705f
@ -33,6 +33,7 @@ pub mod combat;
|
||||
pub mod comp;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod consts;
|
||||
pub mod debug_info;
|
||||
#[cfg(not(target_arch = "wasm32"))] pub mod depot;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod effect;
|
||||
@ -77,7 +78,6 @@ pub mod uid;
|
||||
#[cfg(not(target_arch = "wasm32"))] pub mod vol;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod volumes;
|
||||
pub mod debug_info;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub use cached_spatial_grid::CachedSpatialGrid;
|
||||
|
@ -10,9 +10,14 @@ use common::{
|
||||
comp,
|
||||
comp::{Poise, PoiseState},
|
||||
};
|
||||
use core::mem;
|
||||
#[cfg(feature = "use-dyn-lib")]
|
||||
pub use dyn_lib::init;
|
||||
use egui::{Color32, Grid, ScrollArea, Slider, Ui};
|
||||
use egui::{
|
||||
plot::{Plot, Value},
|
||||
widgets::plot::Curve,
|
||||
Color32, Grid, ScrollArea, Slider, Ui,
|
||||
};
|
||||
use std::{cmp::Ordering, ffi::CStr};
|
||||
|
||||
#[cfg(feature = "use-dyn-lib")]
|
||||
@ -23,10 +28,17 @@ pub fn maintain(
|
||||
egui_state: &mut EguiInnerState,
|
||||
client: &Client,
|
||||
debug_info: &Option<DebugInfo>,
|
||||
) {
|
||||
added_cylinder_shape_id: Option<u64>,
|
||||
) -> EguiActions {
|
||||
#[cfg(not(feature = "use-dyn-lib"))]
|
||||
{
|
||||
maintain_egui_inner(platform, egui_state, client, debug_info);
|
||||
return maintain_egui_inner(
|
||||
platform,
|
||||
egui_state,
|
||||
client,
|
||||
debug_info,
|
||||
added_cylinder_shape_id,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "use-dyn-lib")]
|
||||
@ -35,15 +47,14 @@ pub fn maintain(
|
||||
let lib = &lock.as_ref().unwrap().lib;
|
||||
|
||||
let maintain_fn: libloading::Symbol<
|
||||
fn(&mut Platform, &mut EguiInnerState, &Client, &Option<DebugInfo>),
|
||||
> = unsafe {
|
||||
//let start = std::time::Instant::now();
|
||||
// Overhead of 0.5-5 us (could use hashmap to mitigate if this is an issue)
|
||||
let f = lib.get(MAINTAIN_EGUI_FN);
|
||||
//println!("{}", start.elapsed().as_nanos());
|
||||
f
|
||||
}
|
||||
.unwrap_or_else(|e| {
|
||||
fn(
|
||||
&mut Platform,
|
||||
&mut EguiInnerState,
|
||||
&Client,
|
||||
&Option<DebugInfo>,
|
||||
Option<u64>,
|
||||
) -> EguiActions,
|
||||
> = unsafe { lib.get(MAINTAIN_EGUI_FN) }.unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Trying to use: {} but had error: {:?}",
|
||||
CStr::from_bytes_with_nul(MAINTAIN_EGUI_FN)
|
||||
@ -54,14 +65,66 @@ pub fn maintain(
|
||||
)
|
||||
});
|
||||
|
||||
maintain_fn(platform, egui_state, client, debug_info);
|
||||
return maintain_fn(
|
||||
platform,
|
||||
egui_state,
|
||||
client,
|
||||
debug_info,
|
||||
added_cylinder_shape_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SelectedEntityInfo {
|
||||
entity_id: u32,
|
||||
debug_shape_id: Option<u64>,
|
||||
}
|
||||
|
||||
impl SelectedEntityInfo {
|
||||
fn new(entity_id: u32) -> Self {
|
||||
Self {
|
||||
entity_id,
|
||||
debug_shape_id: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EguiInnerState {
|
||||
pub read_ecs: bool,
|
||||
pub selected_entity_id: u32,
|
||||
pub max_entity_distance: f32,
|
||||
read_ecs: bool,
|
||||
selected_entity_info: Option<SelectedEntityInfo>,
|
||||
max_entity_distance: f32,
|
||||
selected_entity_cylinder_height: f32,
|
||||
frame_times: Vec<f32>,
|
||||
}
|
||||
|
||||
impl EguiInnerState {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
read_ecs: false,
|
||||
selected_entity_info: None,
|
||||
max_entity_distance: 100000.0,
|
||||
selected_entity_cylinder_height: 10.0,
|
||||
frame_times: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum DebugShapeAction {
|
||||
AddCylinder {
|
||||
radius: f32,
|
||||
height: f32,
|
||||
},
|
||||
SetPosAndColor {
|
||||
id: u64,
|
||||
pos: [f32; 4],
|
||||
color: [f32; 4],
|
||||
},
|
||||
RemoveCylinder(u64),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct EguiActions {
|
||||
pub actions: Vec<DebugShapeAction>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "maintain_egui_inner")]
|
||||
@ -70,27 +133,54 @@ pub fn maintain_egui_inner(
|
||||
egui_state: &mut EguiInnerState,
|
||||
client: &Client,
|
||||
debug_info: &Option<DebugInfo>,
|
||||
) {
|
||||
added_cylinder_shape_id: Option<u64>,
|
||||
) -> EguiActions {
|
||||
platform.begin_frame();
|
||||
let mut egui_actions = EguiActions::default();
|
||||
let mut previous_selected_entity: Option<SelectedEntityInfo> = None;
|
||||
let mut max_entity_distance = egui_state.max_entity_distance;
|
||||
let mut selected_entity_cylinder_height = egui_state.selected_entity_cylinder_height;
|
||||
|
||||
// If a debug cylinder was added in the last frame, store it against the
|
||||
// selected entity
|
||||
if let Some(shape_id) = added_cylinder_shape_id {
|
||||
if let Some(selected_entity) = &mut egui_state.selected_entity_info {
|
||||
selected_entity.debug_shape_id = Some(shape_id);
|
||||
}
|
||||
}
|
||||
|
||||
debug_info.as_ref().map(|x| {
|
||||
egui_state.frame_times.push(x.frame_time.as_nanos() as f32);
|
||||
if egui_state.frame_times.len() > 250 {
|
||||
egui_state.frame_times.remove(0);
|
||||
}
|
||||
});
|
||||
|
||||
if egui_state.read_ecs {
|
||||
let ecs = client.state().ecs();
|
||||
|
||||
let positions = client.state().ecs().read_storage::<comp::Pos>();
|
||||
let client_pos = positions.get(client.entity());
|
||||
let mut max_entity_distance = egui_state.max_entity_distance;
|
||||
|
||||
egui::Window::new("ECS Entities")
|
||||
.default_width(500.0)
|
||||
.default_height(500.0)
|
||||
.show(&platform.context(), |ui| {
|
||||
ui.label(format!("Entity count: {}", &ecs.entities().join().count()));
|
||||
ui.add(
|
||||
Slider::new(&mut max_entity_distance, 1.0..=17000.0)
|
||||
Slider::new(&mut max_entity_distance, 1.0..=100000.0)
|
||||
.logarithmic(true)
|
||||
.clamp_to_range(true)
|
||||
.text("Max entity distance"),
|
||||
);
|
||||
|
||||
ui.add(
|
||||
Slider::new(&mut selected_entity_cylinder_height, 0.1..=100.0)
|
||||
.logarithmic(true)
|
||||
.clamp_to_range(true)
|
||||
.text("Cylinder height"),
|
||||
);
|
||||
|
||||
let mut scroll_area = ScrollArea::from_max_height(800.0);
|
||||
let (current_scroll, max_scroll) = scroll_area.show(ui, |ui| {
|
||||
// if scroll_top {
|
||||
@ -108,16 +198,17 @@ pub fn maintain_egui_inner(
|
||||
ui.label("Body");
|
||||
ui.label("Poise");
|
||||
ui.end_row();
|
||||
for (entity, body, pos, ori, vel, poise) in (
|
||||
for (entity, body, stats, pos, ori, vel, poise) in (
|
||||
&ecs.entities(),
|
||||
ecs.read_storage::<comp::Body>().maybe(),
|
||||
ecs.read_storage::<comp::Stats>().maybe(),
|
||||
ecs.read_storage::<comp::Pos>().maybe(),
|
||||
ecs.read_storage::<comp::Ori>().maybe(),
|
||||
ecs.read_storage::<comp::Vel>().maybe(),
|
||||
ecs.read_storage::<comp::Poise>().maybe(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(_, _, pos, _, _, _)| {
|
||||
.filter(|(_, _, _, pos, _, _, _)| {
|
||||
client_pos.map_or(true, |client_pos| {
|
||||
pos.map_or(0.0, |pos| pos.0.distance_squared(client_pos.0))
|
||||
< max_entity_distance
|
||||
@ -130,28 +221,40 @@ pub fn maintain_egui_inner(
|
||||
// })
|
||||
{
|
||||
if ui.button("View").clicked() {
|
||||
egui_state.selected_entity_id = entity.id();
|
||||
previous_selected_entity =
|
||||
mem::take(&mut egui_state.selected_entity_info);
|
||||
|
||||
if pos.is_some() {
|
||||
egui_actions.actions.push(DebugShapeAction::AddCylinder {
|
||||
radius: 1.0,
|
||||
height: egui_state.selected_entity_cylinder_height,
|
||||
});
|
||||
}
|
||||
egui_state.selected_entity_info =
|
||||
Some(SelectedEntityInfo::new(entity.id()));
|
||||
}
|
||||
|
||||
ui.label(format!("{}", entity.id()));
|
||||
|
||||
if let Some(pos) = pos {
|
||||
ui.label(format!(
|
||||
"{:.3},{:.3},{:.3}",
|
||||
"{:.0},{:.0},{:.0}",
|
||||
pos.0.x, pos.0.y, pos.0.z
|
||||
));
|
||||
} else {
|
||||
ui.label("-");
|
||||
}
|
||||
|
||||
if let Some(vel) = vel {
|
||||
ui.label(format!(
|
||||
"{:.3},{:.3},{:.3}",
|
||||
"{:.1},{:.1},{:.1}",
|
||||
vel.0.x, vel.0.y, vel.0.z
|
||||
));
|
||||
} else {
|
||||
ui.label("-");
|
||||
}
|
||||
if let Some(body) = body {
|
||||
ui.label(format!("{:?}", body));
|
||||
if let Some(stats) = stats {
|
||||
ui.label(&stats.name);
|
||||
} else {
|
||||
ui.label("-");
|
||||
}
|
||||
@ -174,42 +277,41 @@ pub fn maintain_egui_inner(
|
||||
(current_scroll, max_scroll)
|
||||
});
|
||||
});
|
||||
egui_state.max_entity_distance = max_entity_distance;
|
||||
let selected_entity = ecs.entities().entity(egui_state.selected_entity_id);
|
||||
if selected_entity.gen().is_alive() {
|
||||
egui::Window::new("Selected Entity")
|
||||
.default_width(300.0)
|
||||
.default_height(200.0)
|
||||
.show(&platform.context(), |ui| {
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
for (entity, body, pos, ori, vel, poise, buffs) in (
|
||||
&ecs.entities(),
|
||||
ecs.read_storage::<comp::Body>().maybe(),
|
||||
ecs.read_storage::<comp::Pos>().maybe(),
|
||||
ecs.read_storage::<comp::Ori>().maybe(),
|
||||
ecs.read_storage::<comp::Vel>().maybe(),
|
||||
ecs.read_storage::<comp::Poise>().maybe(),
|
||||
ecs.read_storage::<comp::Buffs>().maybe(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(e, _, _, _, _, _, _)| e.id() == egui_state.selected_entity_id)
|
||||
{
|
||||
if let Some(body) = body {
|
||||
ui.group(|ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.label("Body");
|
||||
Grid::new("selected_entity_body_grid")
|
||||
.spacing([40.0, 4.0])
|
||||
.max_col_width(100.0)
|
||||
.striped(true)
|
||||
.show(ui, |ui| {
|
||||
ui.label("Type");
|
||||
ui.label(format!("{:?}", body));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
if let Some(selected_entity_info) = &mut egui_state.selected_entity_info {
|
||||
let selected_entity = ecs.entities().entity(selected_entity_info.entity_id);
|
||||
if !selected_entity.gen().is_alive() {
|
||||
previous_selected_entity = mem::take(&mut egui_state.selected_entity_info);
|
||||
} else {
|
||||
for (entity, body, stats, pos, ori, vel, poise, buffs) in (
|
||||
&ecs.entities(),
|
||||
ecs.read_storage::<comp::Body>().maybe(),
|
||||
ecs.read_storage::<comp::Stats>().maybe(),
|
||||
ecs.read_storage::<comp::Pos>().maybe(),
|
||||
ecs.read_storage::<comp::Ori>().maybe(),
|
||||
ecs.read_storage::<comp::Vel>().maybe(),
|
||||
ecs.read_storage::<comp::Poise>().maybe(),
|
||||
ecs.read_storage::<comp::Buffs>().maybe(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(e, _, _, _, _, _, _, _)| e.id() == selected_entity_info.entity_id)
|
||||
{
|
||||
egui::Window::new(format!(
|
||||
"Selected Entity - {}",
|
||||
stats.as_ref().map_or("<No Name>", |x| &x.name)
|
||||
))
|
||||
.default_width(300.0)
|
||||
.default_height(200.0)
|
||||
.show(&platform.context(), |ui| {
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
9-
|
||||
if let Some(pos) = pos {
|
||||
if let Some(shape_id) = selected_entity_info.debug_shape_id {
|
||||
egui_actions.actions.push(DebugShapeAction::SetPosAndColor {
|
||||
id: shape_id,
|
||||
color: [1.0, 1.0, 0.0, 0.5],
|
||||
pos: [pos.0.x, pos.0.y, pos.0.z + 2.0, 0.0],
|
||||
});
|
||||
}
|
||||
ui.group(|ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.label("Pos");
|
||||
@ -284,9 +386,10 @@ pub fn maintain_egui_inner(
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -305,6 +408,46 @@ pub fn maintain_egui_inner(
|
||||
egui_state.read_ecs = true;
|
||||
}
|
||||
});
|
||||
|
||||
egui::Window::new("Frame Time")
|
||||
.default_width(200.0)
|
||||
.default_height(200.0)
|
||||
.show(&platform.context(), |ui| {
|
||||
let plot = Plot::default().curve(Curve::from_values_iter(
|
||||
egui_state
|
||||
.frame_times
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, x)| Value::new(i as f64, *x)),
|
||||
));
|
||||
ui.add(plot);
|
||||
});
|
||||
|
||||
if let Some(previous) = previous_selected_entity {
|
||||
if let Some(debug_shape_id) = previous.debug_shape_id {
|
||||
egui_actions
|
||||
.actions
|
||||
.push(DebugShapeAction::RemoveCylinder(debug_shape_id));
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(selected_entity) = &egui_state.selected_entity_info {
|
||||
if let Some(debug_shape_id) = selected_entity.debug_shape_id {
|
||||
if egui_state.selected_entity_cylinder_height != selected_entity_cylinder_height {
|
||||
egui_actions
|
||||
.actions
|
||||
.push(DebugShapeAction::RemoveCylinder(debug_shape_id));
|
||||
egui_actions.actions.push(DebugShapeAction::AddCylinder {
|
||||
radius: 1.0,
|
||||
height: selected_entity_cylinder_height,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
egui_state.max_entity_distance = max_entity_distance;
|
||||
egui_state.selected_entity_cylinder_height = selected_entity_cylinder_height;
|
||||
egui_actions
|
||||
}
|
||||
|
||||
fn poise_state_label(ui: &mut Ui, poise: &Poise) {
|
||||
|
@ -50,7 +50,7 @@ impl DebugShape {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub struct DebugShapeId(u64);
|
||||
pub struct DebugShapeId(pub u64);
|
||||
|
||||
pub struct Debug {
|
||||
next_shape_id: DebugShapeId,
|
||||
|
@ -44,10 +44,10 @@ use crate::{
|
||||
window::{AnalogGameInput, Event, GameInput},
|
||||
Direction, Error, GlobalState, PlayState, PlayStateResult,
|
||||
};
|
||||
use common::debug_info::DebugInfo;
|
||||
use egui_wgpu_backend::epi::App;
|
||||
use hashbrown::HashMap;
|
||||
use settings_change::Language::ChangeLanguage;
|
||||
use common::debug_info::DebugInfo;
|
||||
|
||||
/// The action to perform after a tick
|
||||
enum TickAction {
|
||||
@ -1016,7 +1016,9 @@ impl PlayState for SessionState {
|
||||
);
|
||||
|
||||
// Maintain egui (debug interface)
|
||||
global_state.egui_state.maintain(&self.client.borrow(), &debug_info,);
|
||||
global_state
|
||||
.egui_state
|
||||
.maintain(&self.client.borrow(), &mut self.scene, &debug_info);
|
||||
|
||||
// Look for changes in the localization files
|
||||
if global_state.i18n.reloaded() {
|
||||
@ -1457,10 +1459,7 @@ impl PlayState for SessionState {
|
||||
|
||||
drop(third_pass);
|
||||
|
||||
drawer.draw_egui(
|
||||
&mut global_state.egui_state.platform,
|
||||
scale_factor,
|
||||
);
|
||||
drawer.draw_egui(&mut global_state.egui_state.platform, scale_factor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,18 @@
|
||||
use crate::window::Window;
|
||||
use crate::{
|
||||
scene::{DebugShape, DebugShapeId, Scene},
|
||||
window::Window,
|
||||
};
|
||||
use client::Client;
|
||||
use common::debug_info::DebugInfo;
|
||||
use core::mem;
|
||||
use egui::FontDefinitions;
|
||||
use egui_winit_platform::{Platform, PlatformDescriptor};
|
||||
use voxygen_egui::EguiInnerState;
|
||||
use voxygen_egui::{DebugShapeAction, EguiInnerState};
|
||||
|
||||
pub struct EguiState {
|
||||
pub platform: Platform,
|
||||
egui_inner_state: EguiInnerState,
|
||||
new_debug_shape_id: Option<u64>,
|
||||
}
|
||||
|
||||
impl EguiState {
|
||||
@ -22,20 +27,36 @@ impl EguiState {
|
||||
|
||||
Self {
|
||||
platform,
|
||||
egui_inner_state: EguiInnerState {
|
||||
read_ecs: false,
|
||||
selected_entity_id: 0,
|
||||
max_entity_distance: 17000.0,
|
||||
},
|
||||
egui_inner_state: EguiInnerState::new(),
|
||||
new_debug_shape_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maintain(&mut self, client: &Client, debug_info: &Option<DebugInfo>) {
|
||||
voxygen_egui::maintain(
|
||||
pub fn maintain(&mut self, client: &Client, scene: &mut Scene, debug_info: &Option<DebugInfo>) {
|
||||
let egui_actions = voxygen_egui::maintain(
|
||||
&mut self.platform,
|
||||
&mut self.egui_inner_state,
|
||||
client,
|
||||
debug_info,
|
||||
mem::take(&mut self.new_debug_shape_id),
|
||||
);
|
||||
|
||||
egui_actions.actions.iter().for_each(|action| match action {
|
||||
DebugShapeAction::AddCylinder { height, radius } => {
|
||||
let shape_id = scene.debug.add_shape(DebugShape::Cylinder {
|
||||
height: *height,
|
||||
radius: *radius,
|
||||
});
|
||||
self.new_debug_shape_id = Some(shape_id.0);
|
||||
},
|
||||
DebugShapeAction::RemoveCylinder(debug_shape_id) => {
|
||||
scene.debug.remove_shape(DebugShapeId(*debug_shape_id));
|
||||
},
|
||||
DebugShapeAction::SetPosAndColor { id, pos, color } => {
|
||||
scene
|
||||
.debug
|
||||
.set_pos_and_color(DebugShapeId(*id), pos.clone(), color.clone());
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user