debug: split fps overlay and debug ui

This commit is contained in:
Victoria Brekenfeld 2022-02-04 21:08:11 +01:00
parent 2d76672188
commit 78cc1713ad
2 changed files with 178 additions and 145 deletions

View file

@ -4,25 +4,43 @@ use crate::state::{Common, Fps};
use smithay::utils::{Logical, Rectangle};
use smithay_egui::EguiFrame;
pub fn debug_ui(
state: &mut Common,
fps: &Fps,
pub fn fps_ui(
state: &Common,
fps: &mut Fps,
area: Rectangle<i32, Logical>,
scale: f64,
primary: bool,
) -> EguiFrame {
let size = area.size;
let alpha = state.egui.alpha;
use egui::widgets::plot::{Bar, BarChart, HLine, Legend, Plot};
state.egui.state.run(
let (max, min, avg, avg_fps) = (
fps.max_frametime().as_secs_f64(),
fps.min_frametime().as_secs_f64(),
fps.avg_frametime().as_secs_f64(),
fps.avg_fps(),
);
let bars = fps
.frames
.iter()
.rev()
.take(30)
.rev()
.enumerate()
.map(|(i, (_, d))| {
let value = d.as_secs_f64();
let transformed = ((value - min) / (max - min) * 255.0).round() as u8;
Bar::new(i as f64, transformed as f64).fill(egui::Color32::from_rgb(
transformed,
255 - transformed,
0,
))
})
.collect();
fps.state.run(
|ctx| {
egui::Area::new("main")
.anchor(egui::Align2::LEFT_TOP, (10.0, 10.0))
.show(ctx, |ui| {
use egui::widgets::plot::{Bar, BarChart, HLine, Legend, Plot};
// Basics
let label_res = ui.label(format!(
"cosmic-comp version {}",
std::env!("CARGO_PKG_VERSION")
@ -34,43 +52,15 @@ pub fn debug_ui(
if !state.egui.active {
ui.label("Press Mod+Escape for debug menu");
} else {
ui.set_max_width(label_res.rect.width());
ui.set_max_width(label_res.rect.min.x + label_res.rect.width());
ui.separator();
// FPS
let (max, min, avg, avg_fps) = (
fps.max_frametime().as_secs_f64(),
fps.min_frametime().as_secs_f64(),
fps.avg_frametime().as_secs_f64(),
fps.avg_fps(),
);
ui.label(egui::RichText::new(format!("FPS: {:>7.3}", avg_fps)).heading());
ui.label("Frame Times:");
ui.label(egui::RichText::new(format!("avg: {:>7.6}", avg)).code());
ui.label(egui::RichText::new(format!("min: {:>7.6}", min)).code());
ui.label(egui::RichText::new(format!("max: {:>7.6}", max)).code());
let fps_chart = BarChart::new(
fps.frames
.iter()
.rev()
.take(30)
.rev()
.enumerate()
.map(|(i, d)| {
let value = d.as_secs_f64();
let transformed =
((value - min) / (max - min) * 255.0).round() as u8;
Bar::new(i as f64, value).fill(egui::Color32::from_rgb(
transformed,
255 - transformed,
0,
))
})
.collect(),
)
.vertical();
let fps_chart = BarChart::new(bars).vertical();
Plot::new("FPS")
.legend(Legend::default())
@ -78,7 +68,7 @@ pub fn debug_ui(
.include_x(0.0)
.include_x(30.0)
.include_y(0.0)
.include_y(max * 2.0)
.include_y(300.0)
.show_x(false)
.show(ui, |plot_ui| {
plot_ui.bar_chart(fps_chart);
@ -86,117 +76,133 @@ pub fn debug_ui(
HLine::new(avg).highlight().color(egui::Color32::LIGHT_BLUE),
);
});
ui.separator();
// Toggles and stuff
ui.add(
egui::Slider::new(&mut state.egui.alpha, 0.1..=1.0)
.clamp_to_range(true)
.text("Opacity"),
);
ui.checkbox(&mut state.egui.spaces, "Workspace UI");
//TODO: ui.checkbox(&mut state.egui.outputs, "Outputs UI");
}
});
},
area,
scale,
1.0,
&state.start_time,
fps.modifiers.clone(),
)
}
// don't show these one others then the primary monitor
if primary {
egui::Window::new("Workspaces")
.open(&mut state.egui.spaces)
.vscroll(true)
.show(ctx, |ui| {
use crate::shell::workspaces::{ActiveWorkspace, Mode, MAX_WORKSPACES};
pub fn debug_ui(
state: &mut Common,
area: Rectangle<i32, Logical>,
scale: f64,
) -> Option<EguiFrame> {
if !state.egui.active {
return None;
}
ui.set_min_width(250.0);
Some(state.egui.state.run(
|ctx| {
egui::Window::new("Workspaces")
.default_pos([0.0, 300.0])
.vscroll(true)
.collapsible(true)
.show(ctx, |ui| {
use crate::shell::workspaces::{ActiveWorkspace, Mode, MAX_WORKSPACES};
// Mode
ui.set_min_width(250.0);
ui.label(egui::RichText::new("Mode").heading());
let mut mode = *state.spaces.mode();
let active = if let Mode::Global { active } = mode {
active
} else {
0
};
ui.radio_value(&mut mode, Mode::OutputBound, "Output bound");
ui.radio_value(&mut mode, Mode::Global { active }, "Global");
state.spaces.set_mode(mode);
// Mode
match *state.spaces.mode() {
Mode::OutputBound => {
ui.label("Workspaces:");
for output in state.spaces.outputs().cloned().collect::<Vec<_>>() {
ui.horizontal(|ui| {
let active = output
.user_data()
.get::<ActiveWorkspace>()
.unwrap()
.get()
.unwrap();
let mut active_val = active as f64;
ui.label(output.name());
ui.add(
egui::DragValue::new(&mut active_val)
.clamp_range(0..=(MAX_WORKSPACES - 1))
.speed(1.0),
);
if active != active_val as usize {
state.spaces.activate(&output, active_val as usize);
}
});
}
}
Mode::Global { active } => {
ui.label(egui::RichText::new("Mode").heading());
let mut mode = *state.spaces.mode();
let active = if let Mode::Global { active } = mode {
active
} else {
0
};
ui.radio_value(&mut mode, Mode::OutputBound, "Output bound");
ui.radio_value(&mut mode, Mode::Global { active }, "Global");
state.spaces.set_mode(mode);
match *state.spaces.mode() {
Mode::OutputBound => {
ui.label("Workspaces:");
for output in state.spaces.outputs().cloned().collect::<Vec<_>>() {
ui.horizontal(|ui| {
let active = output
.user_data()
.get::<ActiveWorkspace>()
.unwrap()
.get()
.unwrap();
let mut active_val = active as f64;
ui.label("Workspace:");
ui.label(output.name());
ui.add(
egui::DragValue::new(&mut active_val)
.clamp_range(0..=(MAX_WORKSPACES - 1))
.speed(1.0),
);
if active != active_val as usize {
let output =
state.spaces.outputs().next().cloned().unwrap();
state.spaces.activate(&output, active_val as usize);
}
});
}
}
// Spaces
for (i, space) in state.spaces.spaces.iter().enumerate() {
ui.collapsing(format!("Space: {}", i), |ui| {
ui.collapsing(format!("Windows"), |ui| {
for window in space.windows() {
ui.collapsing(format!("{:?}", window.toplevel()), |ui| {
ui.label(format!(
"Rect: {:?}",
space.window_geometry(window)
));
ui.label(format!(
"Bounding box: {:?}",
space.window_bbox(window)
));
});
}
})
Mode::Global { active } => {
ui.horizontal(|ui| {
let mut active_val = active as f64;
ui.label("Workspace:");
ui.add(
egui::DragValue::new(&mut active_val)
.clamp_range(0..=(MAX_WORKSPACES - 1))
.speed(1.0),
);
if active != active_val as usize {
let output = state.spaces.outputs().next().cloned().unwrap();
state.spaces.activate(&output, active_val as usize);
}
});
}
});
}
egui::Window::new("Outputs")
.open(&mut state.egui.outputs)
.hscroll(true)
.show(ctx, |ui| {});
}
// Spaces
for (i, space) in state.spaces.spaces.iter().enumerate() {
ui.collapsing(format!("Space: {}", i), |ui| {
ui.collapsing(format!("Windows"), |ui| {
for window in space.windows() {
ui.collapsing(format!("{:?}", window.toplevel()), |ui| {
ui.label(format!(
"Rect: {:?}",
space.window_geometry(window)
));
ui.label(format!(
"Bounding box: {:?}",
space.window_bbox(window)
));
});
}
})
});
}
});
egui::Window::new("Outputs")
.collapsible(true)
.hscroll(true)
.default_pos([300.0, 300.0])
.show(ctx, |ui| {
ui.label(format!("Global Space: {:?}", state.spaces.global_space()));
for output in state.spaces.outputs().cloned().collect::<Vec<_>>().into_iter() {
ui.separator();
ui.collapsing(output.name(), |ui| {
ui.label(format!("Output: {:#?}", output));
ui.label(format!("Geometry: {:?}", state.spaces.output_geometry(&output)));
ui.label(format!("Local Geometry: {:?}", state.spaces.active_space(&output).output_geometry(&output)));
ui.label(format!("Relative Geometry: {:?}", state.spaces.space_relative_output_geometry((0, 0), &output)));
});
}
});
},
area,
size.to_f64().to_physical(scale).to_i32_round(),
scale,
alpha,
state.egui.alpha,
&state.start_time,
state.egui.modifiers.clone(),
)
))
}