mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-18 07:35:19 +00:00
Debug toggling (#9)
#8 introduced some additional debug information to the view, which was already rendering some information and visualizations which were not necessary relevant to the end-user experience. This PR adds an input action (bound to Ctrl + `) to toggle the display of those visualizations, and disables them by default.
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
import { LitElement, html, unsafeCSS } from "lit";
|
import { LitElement, html, unsafeCSS, nothing, HTMLTemplateResult } from "lit";
|
||||||
import { customElement } from "lit/decorators.js";
|
import { customElement } from "lit/decorators.js";
|
||||||
|
|
||||||
import styles from "./help.element.scss?inline";
|
import styles from "./help.element.scss?inline";
|
||||||
|
import { isDevEnvironment } from "./util";
|
||||||
|
|
||||||
@customElement("sts-help")
|
@customElement("sts-help")
|
||||||
export class HelpElement extends LitElement {
|
export class HelpElement extends LitElement {
|
||||||
@@ -9,68 +10,62 @@ export class HelpElement extends LitElement {
|
|||||||
|
|
||||||
protected override render = () => html`
|
protected override render = () => html`
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
${section("Navigation", [
|
||||||
<tr>
|
{ name: "Pan View", controls: "MMB" },
|
||||||
<th class="section-header" colspan="3">
|
{ name: "Orbit around point", controls: "Alt + LMB" },
|
||||||
Navigation
|
{ name: "Zoom", controls: ["Alt + RMB", "Mouse Wheel"]},
|
||||||
</th>
|
{ name: "Free fly", controls: "W, A, S, D, E, Q" },
|
||||||
</tr>
|
{ name: "Free look", controls: ["RMB", "Shift"] },
|
||||||
<tr>
|
])}
|
||||||
<th>Action</th>
|
${section("Interaction", [
|
||||||
<th>Controls</th>
|
{ name: "Select", controls: "LMB" },
|
||||||
<th>Alternate</th>
|
{ name: "Clear selection", controls: "Esc" },
|
||||||
</tr>
|
{ name: "Focus selection", controls: "F" },
|
||||||
</thead>
|
])}
|
||||||
<tbody>
|
${isDevEnvironment()
|
||||||
<tr>
|
? section("Developer", [
|
||||||
<td>Pan view</td>
|
{ name: "Toggle debug info", controls: html`Ctrl + `` }
|
||||||
<td colspan="2">MMB</td>
|
])
|
||||||
</tr>
|
: nothing}
|
||||||
<tr>
|
|
||||||
<td>Orbit around point</td>
|
|
||||||
<td colspan="2">Alt + LMB</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Zoom</td>
|
|
||||||
<td>Alt + RMB</td>
|
|
||||||
<td>Mouse Wheel</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Free fly</td>
|
|
||||||
<td colspan="2">W, A, S, D, E, Q</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Free look</td>
|
|
||||||
<td>RMB</td>
|
|
||||||
<td>Shift</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="section-header" colspan="3">
|
|
||||||
Interaction
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Action</th>
|
|
||||||
<th>Controls</th>
|
|
||||||
<th>Alternate</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Select</td>
|
|
||||||
<td colspan="2">LMB</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Clear Selection</td>
|
|
||||||
<td colspan="2">Esc</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Focus Selection</td>
|
|
||||||
<td colspan="2">F</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Action {
|
||||||
|
name: string | HTMLTemplateResult;
|
||||||
|
controls:
|
||||||
|
| string
|
||||||
|
| HTMLTemplateResult
|
||||||
|
| [
|
||||||
|
string | HTMLTemplateResult,
|
||||||
|
string | HTMLTemplateResult
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function section(title: string, actions: Action[]): HTMLTemplateResult {
|
||||||
|
return html`
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="section-header" colspan="3">${title}</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Action</th>
|
||||||
|
<th>Controls</th>
|
||||||
|
<th>Alternate</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
${actions.map(({ name, controls }) => html`
|
||||||
|
<tr>
|
||||||
|
<td>${name}</td>
|
||||||
|
${Array.isArray(controls) ? html`
|
||||||
|
<td>${controls[0]}</td>
|
||||||
|
<td>${controls[1]}</td>
|
||||||
|
` : html`
|
||||||
|
<td colspan="2">${controls}</td>
|
||||||
|
`}
|
||||||
|
</tr>
|
||||||
|
`)}
|
||||||
|
</tbody>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export function isDevEnvironment(): boolean {
|
||||||
|
return window.location.hostname === "localhost"
|
||||||
|
|| window.location.hostname === "127.0.0.1"
|
||||||
|
|| window.location.hostname.includes("deploy-preview");
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
use bevy::{prelude::*, window::PrimaryWindow};
|
||||||
|
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
||||||
|
use bevy_mod_picking::debug::DebugPickingMode;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
camera_controller::{CameraController, CameraMotionSystem},
|
||||||
|
input::{Action, InputAction, Lifecycle},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Resource, Deref, DerefMut)]
|
||||||
|
pub struct DebugMode(bool);
|
||||||
|
|
||||||
|
pub struct DebugPlugin;
|
||||||
|
impl Plugin for DebugPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.insert_resource(DebugMode(false))
|
||||||
|
.add_plugins(WorldInspectorPlugin::new().run_if(is_debug_mode))
|
||||||
|
.insert_resource(State::new(DebugPickingMode::Disabled))
|
||||||
|
.insert_resource(GizmoConfig {
|
||||||
|
enabled: true,
|
||||||
|
depth_bias: -0.1,
|
||||||
|
line_perspective: false,
|
||||||
|
line_width: 2.,
|
||||||
|
..default()
|
||||||
|
})
|
||||||
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
(
|
||||||
|
toggle_debug_mode,
|
||||||
|
update_debug_picking_mode.run_if(resource_changed::<DebugMode>()),
|
||||||
|
update_gizmo_line_thickness,
|
||||||
|
draw_world_axes
|
||||||
|
.after(CameraMotionSystem)
|
||||||
|
.run_if(is_debug_mode),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toggle_debug_mode(mut input: EventReader<InputAction>, mut r_debug: ResMut<DebugMode>) {
|
||||||
|
if input
|
||||||
|
.iter()
|
||||||
|
.any(|action| matches!(action, InputAction(Lifecycle::Stop, Action::ToggleDebug)))
|
||||||
|
{
|
||||||
|
**r_debug = !**r_debug;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_debug_picking_mode(
|
||||||
|
r_debug: Res<DebugMode>,
|
||||||
|
mut s_debug_picking: ResMut<NextState<DebugPickingMode>>,
|
||||||
|
) {
|
||||||
|
s_debug_picking.set(match **r_debug {
|
||||||
|
true => DebugPickingMode::Normal,
|
||||||
|
false => DebugPickingMode::Disabled,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_debug_mode(r_debug: Res<DebugMode>) -> bool {
|
||||||
|
**r_debug
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_gizmo_line_thickness(
|
||||||
|
mut config: ResMut<GizmoConfig>,
|
||||||
|
q_window: Query<&Window, (Changed<Window>, With<PrimaryWindow>)>,
|
||||||
|
) {
|
||||||
|
if let Ok(scale_factor) = q_window.get_single().map(|win| win.scale_factor() as f32) {
|
||||||
|
config.line_width = 2. * scale_factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_world_axes(mut gizmos: Gizmos, q: Query<&CameraController>) {
|
||||||
|
let &CameraController { focus, radius, .. } = q.single();
|
||||||
|
|
||||||
|
let mut draw_axis = |direction: Vec3, color: Color| {
|
||||||
|
let end = focus + direction * radius / 15.;
|
||||||
|
gizmos.line(focus, end, color);
|
||||||
|
};
|
||||||
|
|
||||||
|
draw_axis(Vec3::X, Color::RED);
|
||||||
|
draw_axis(Vec3::Y, Color::GREEN);
|
||||||
|
draw_axis(Vec3::Z, Color::BLUE);
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ impl Plugin for StudioInputPlugin {
|
|||||||
PreUpdate,
|
PreUpdate,
|
||||||
(
|
(
|
||||||
translate_selection_events,
|
translate_selection_events,
|
||||||
|
translate_debug_toggle,
|
||||||
translate_dcc_camera_events,
|
translate_dcc_camera_events,
|
||||||
translate_fps_camera_events,
|
translate_fps_camera_events,
|
||||||
)
|
)
|
||||||
@@ -38,6 +39,7 @@ pub enum Lifecycle {
|
|||||||
pub enum Action {
|
pub enum Action {
|
||||||
Camera(CameraMotion),
|
Camera(CameraMotion),
|
||||||
Selection(Selection),
|
Selection(Selection),
|
||||||
|
ToggleDebug,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@@ -83,6 +85,16 @@ fn translate_selection_events(keyboard: Res<Input<KeyCode>>, mut input: EventWri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn translate_debug_toggle(keyboard: Res<Input<KeyCode>>, mut input: EventWriter<InputAction>) {
|
||||||
|
if keyboard.pressed(KeyCode::ControlLeft) || keyboard.pressed(KeyCode::ControlRight) {
|
||||||
|
if keyboard.just_pressed(KeyCode::Grave) {
|
||||||
|
input.send(InputAction(Lifecycle::Start, Action::ToggleDebug));
|
||||||
|
} else if keyboard.just_released(KeyCode::Grave) {
|
||||||
|
input.send(InputAction(Lifecycle::Stop, Action::ToggleDebug));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn translate_dcc_camera_events(
|
fn translate_dcc_camera_events(
|
||||||
mouse_motion: EventReader<MouseMotion>,
|
mouse_motion: EventReader<MouseMotion>,
|
||||||
mouse_buttons: Res<Input<MouseButton>>,
|
mouse_buttons: Res<Input<MouseButton>>,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use bevy_mod_picking::{prelude::Pointer, selection::Select};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
camera_controller::CameraMotionSystem,
|
camera_controller::CameraMotionSystem,
|
||||||
|
debug,
|
||||||
input::{self, Action, InputAction, Lifecycle},
|
input::{self, Action, InputAction, Lifecycle},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ impl Plugin for InteractionPlugin {
|
|||||||
draw_selection_outline.run_if(resource_changed_or_removed::<Selection>()),
|
draw_selection_outline.run_if(resource_changed_or_removed::<Selection>()),
|
||||||
draw_selection_axes
|
draw_selection_axes
|
||||||
.run_if(resource_exists::<Selection>())
|
.run_if(resource_exists::<Selection>())
|
||||||
|
.run_if(debug::is_debug_mode)
|
||||||
.after(CameraMotionSystem),
|
.after(CameraMotionSystem),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
+5
-40
@@ -1,9 +1,9 @@
|
|||||||
#![allow(clippy::type_complexity, clippy::too_many_arguments)]
|
#![allow(clippy::type_complexity, clippy::too_many_arguments)]
|
||||||
|
|
||||||
use bevy::{prelude::*, window::PrimaryWindow};
|
use bevy::prelude::*;
|
||||||
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
|
||||||
use bevy_mod_picking::DefaultPickingPlugins;
|
use bevy_mod_picking::DefaultPickingPlugins;
|
||||||
use camera_controller::{CameraController, CameraControllerPlugin, CameraMotionSystem};
|
use camera_controller::CameraControllerPlugin;
|
||||||
|
use debug::DebugPlugin;
|
||||||
use input::StudioInputPlugin;
|
use input::StudioInputPlugin;
|
||||||
use interaction::InteractionPlugin;
|
use interaction::InteractionPlugin;
|
||||||
use math::InterpolationPlugin;
|
use math::InterpolationPlugin;
|
||||||
@@ -14,6 +14,7 @@ use viewport::ViewportSize;
|
|||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
mod camera_controller;
|
mod camera_controller;
|
||||||
|
mod debug;
|
||||||
mod input;
|
mod input;
|
||||||
mod interaction;
|
mod interaction;
|
||||||
mod math;
|
mod math;
|
||||||
@@ -42,7 +43,7 @@ pub fn init(viewport_size: ViewportSize) {
|
|||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
DefaultPickingPlugins,
|
DefaultPickingPlugins,
|
||||||
WorldInspectorPlugin::new(),
|
DebugPlugin,
|
||||||
InteractionPlugin,
|
InteractionPlugin,
|
||||||
StudioInputPlugin,
|
StudioInputPlugin,
|
||||||
InterpolationPlugin,
|
InterpolationPlugin,
|
||||||
@@ -51,41 +52,5 @@ pub fn init(viewport_size: ViewportSize) {
|
|||||||
SkyboxPlugin,
|
SkyboxPlugin,
|
||||||
UiLayerPlugin,
|
UiLayerPlugin,
|
||||||
))
|
))
|
||||||
.insert_resource(GizmoConfig {
|
|
||||||
enabled: true,
|
|
||||||
depth_bias: -0.1,
|
|
||||||
line_perspective: false,
|
|
||||||
line_width: 2.,
|
|
||||||
..default()
|
|
||||||
})
|
|
||||||
.add_systems(
|
|
||||||
Update,
|
|
||||||
(
|
|
||||||
update_gizmo_line_thickness,
|
|
||||||
draw_world_axes.after(CameraMotionSystem),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_gizmo_line_thickness(
|
|
||||||
mut config: ResMut<GizmoConfig>,
|
|
||||||
q_window: Query<&Window, (Changed<Window>, With<PrimaryWindow>)>,
|
|
||||||
) {
|
|
||||||
if let Ok(scale_factor) = q_window.get_single().map(|win| win.scale_factor() as f32) {
|
|
||||||
config.line_width = 2. * scale_factor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_world_axes(mut gizmos: Gizmos, q: Query<&CameraController>) {
|
|
||||||
let &CameraController { focus, radius, .. } = q.single();
|
|
||||||
|
|
||||||
let mut draw_axis = |direction: Vec3, color: Color| {
|
|
||||||
let end = focus + direction * radius / 15.;
|
|
||||||
gizmos.line(focus, end, color);
|
|
||||||
};
|
|
||||||
|
|
||||||
draw_axis(Vec3::X, Color::RED);
|
|
||||||
draw_axis(Vec3::Y, Color::GREEN);
|
|
||||||
draw_axis(Vec3::Z, Color::BLUE);
|
|
||||||
}
|
|
||||||
|
|||||||
+38
-16
@@ -3,13 +3,19 @@ use bevy::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::debug::DebugMode;
|
||||||
|
|
||||||
pub(super) struct FpsCounterPlugin;
|
pub(super) struct FpsCounterPlugin;
|
||||||
|
|
||||||
impl Plugin for FpsCounterPlugin {
|
impl Plugin for FpsCounterPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_plugins(FrameTimeDiagnosticsPlugin)
|
app.add_plugins(FrameTimeDiagnosticsPlugin)
|
||||||
.add_systems(Startup, layout)
|
.add_systems(Startup, layout)
|
||||||
.add_systems(Update, update);
|
.add_systems(Update, update)
|
||||||
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
update_visibility.run_if(resource_exists_and_changed::<DebugMode>()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,24 +23,28 @@ impl Plugin for FpsCounterPlugin {
|
|||||||
struct FramerateCounter;
|
struct FramerateCounter;
|
||||||
|
|
||||||
fn layout(mut cmd: Commands) {
|
fn layout(mut cmd: Commands) {
|
||||||
|
let mut text_bundle = TextBundle::from_section(
|
||||||
|
"0 fps",
|
||||||
|
TextStyle {
|
||||||
|
color: Color::GREEN,
|
||||||
|
font_size: 14.,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.with_text_alignment(TextAlignment::Right)
|
||||||
|
.with_style(Style {
|
||||||
|
position_type: PositionType::Absolute,
|
||||||
|
right: Val::Px(16.),
|
||||||
|
bottom: Val::Px(16.),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
|
||||||
|
text_bundle.visibility = Visibility::Hidden;
|
||||||
|
|
||||||
cmd.spawn((
|
cmd.spawn((
|
||||||
FramerateCounter,
|
FramerateCounter,
|
||||||
Name::new("Framerate Counter"),
|
Name::new("Framerate Counter"),
|
||||||
TextBundle::from_section(
|
text_bundle,
|
||||||
"0 fps",
|
|
||||||
TextStyle {
|
|
||||||
color: Color::GREEN,
|
|
||||||
font_size: 14.,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.with_text_alignment(TextAlignment::Right)
|
|
||||||
.with_style(Style {
|
|
||||||
position_type: PositionType::Absolute,
|
|
||||||
right: Val::Px(16.),
|
|
||||||
bottom: Val::Px(16.),
|
|
||||||
..default()
|
|
||||||
}),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,3 +63,15 @@ fn update(
|
|||||||
counter.single_mut().sections[0].value = format!("{fps:.2} fps");
|
counter.single_mut().sections[0].value = format!("{fps:.2} fps");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_visibility(
|
||||||
|
r_debug: Res<DebugMode>,
|
||||||
|
mut q_visibility: Query<&mut Visibility, With<FramerateCounter>>,
|
||||||
|
) {
|
||||||
|
for mut visibility in q_visibility.iter_mut() {
|
||||||
|
*visibility = match **r_debug {
|
||||||
|
true => Visibility::Inherited,
|
||||||
|
false => Visibility::Hidden,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user