Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warn if there is no UI camera #1440

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions crates/bevy_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ impl Plugin for CorePlugin {
app.init_resource::<Time>()
.init_resource::<EntityLabels>()
.init_resource::<FixedTimesteps>()
.init_resource::<ValidationConfig>()
.register_type::<Option<String>>()
.register_type::<Name>()
.register_type::<Labels>()
Expand All @@ -47,3 +48,29 @@ impl Plugin for CorePlugin {
.add_system_to_stage(stage::POST_UPDATE, entity_labels_system.system());
}
}

/// Configures which validation checks are run.
///
/// By default, they are all enabled in debug mode but
/// disabled in release mode.
pub struct ValidationConfig {
/// Checks whether the world contains no ui camera but ui nodes.
pub missing_ui_cam: bool,
#[doc(hidden)]
#[allow(unused)]
// we cannot use `#[non_exhaustive]`, since that wouldn't allow `ValidationConfig { ..Default::default() }`
pub non_exhaustive: (),
}

impl Default for ValidationConfig {
fn default() -> Self {
#[cfg(debug_assertions)]
let default_value = true;
#[cfg(not(debug_assertions))]
let default_value = false;
ValidationConfig {
missing_ui_cam: default_value,
non_exhaustive: (),
}
}
}
35 changes: 33 additions & 2 deletions crates/bevy_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ pub mod prelude {
}

use bevy_app::prelude::*;
use bevy_ecs::{IntoSystem, ParallelSystemDescriptorCoercion, SystemStage};
use bevy_render::render_graph::RenderGraph;
use bevy_ecs::{prelude::*, IntoSystem, ParallelSystemDescriptorCoercion, SystemStage};
use bevy_render::{
camera::{Camera, OrthographicProjection},
render_graph::RenderGraph,
};
use update::ui_z_system;

#[derive(Default)]
Expand Down Expand Up @@ -54,8 +57,36 @@ impl Plugin for UiPlugin {
.add_system_to_stage(stage::UI, ui_z_system.system())
.add_system_to_stage(bevy_render::stage::DRAW, widget::draw_text_system.system());

let add_ui_cam_validation_system = app
.resources()
.get::<bevy_core::ValidationConfig>()
.map_or(false, |config| config.missing_ui_cam);

if add_ui_cam_validation_system {
app.add_startup_system_to_stage(
bevy_app::startup_stage::POST_STARTUP,
warn_no_ui_cam.system(),
);
}

let resources = app.resources();
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
render_graph.add_ui_graph(resources);
}
}

fn warn_no_ui_cam(
node_query: Query<Entity, With<Node>>,
ui_cam_query: Query<&Camera, With<OrthographicProjection>>,
) {
let world_contains_nodes = node_query.iter().next().is_some();
let world_contains_ui_cam = ui_cam_query
.iter()
.any(|cam| cam.name.as_deref() == Some(crate::camera::CAMERA_UI));

if world_contains_nodes && !world_contains_ui_cam {
bevy_log::warn!(
"The world contains ui nodes but no ui camera. Consider spawning a UiCameraBundle."
);
}
}