#![allow(warnings)] use bevy::render::mesh::MeshVertexAttribute; use bevy::render::render_resource::VertexFormat; use bevy::render::view::NoFrustumCulling; use bevy::render::MainWorld; /** * * NOTE: this module and its submodules are only temporary. It is a copy-paste of the bevy-debug-lines * crate: https://github.com/Toqozz/bevy_debug_lines (MIT license) * It has been partially updated to work with bevy 0.7, but hasn’t been released yet. * So, in the mean time, we are keeping a version here that we will replace by the * upstream dependency once: * 1. The version compatible with bevy 0.7 is released to crates.io. * 2. We find a way to make the 2D version work with our examples. The problem * only happens when running our own examples because cargo’s unification of * features will enable the `3d` feature of `bevy_debug_lines` when running * a `2d` example. * */ use bevy::{ asset::{Assets, HandleUntyped}, pbr::{NotShadowCaster, NotShadowReceiver}, prelude::*, reflect::TypeUuid, render::{ mesh::{/*Indices,*/ Mesh, VertexAttributeValues}, render_phase::AddRenderCommand, render_resource::PrimitiveTopology, render_resource::Shader, }, }; mod render_dim; // This module exists to "isolate" the `#[cfg]` attributes to this part of the // code. Otherwise, we would pollute the code with a lot of feature // gates-specific code. #[cfg(feature = "dim3")] mod dim { pub(crate) use super::render_dim::r3d::{queue, DebugLinePipeline, DrawDebugLines}; pub(crate) use bevy::core_pipeline::core_3d::Opaque3d as Phase; use bevy::{asset::Handle, render::mesh::Mesh}; pub(crate) type MeshHandle = Handle; pub(crate) fn from_handle(from: &MeshHandle) -> &Handle { from } pub(crate) fn into_handle(from: Handle) -> MeshHandle { from } pub(crate) const SHADER_FILE: &str = include_str!("debuglines.wgsl"); pub(crate) const DIMMENSION: &str = "3d"; } #[cfg(feature = "dim2")] mod dim { pub(crate) use super::render_dim::r2d::{queue, DebugLinePipeline, DrawDebugLines}; pub(crate) use bevy::core_pipeline::core_2d::Transparent2d as Phase; use bevy::{asset::Handle, render::mesh::Mesh, sprite::Mesh2dHandle}; pub(crate) type MeshHandle = Mesh2dHandle; pub(crate) fn from_handle(from: &MeshHandle) -> &Handle { &from.0 } pub(crate) fn into_handle(from: Handle) -> MeshHandle { Mesh2dHandle(from) } pub(crate) const SHADER_FILE: &str = include_str!("debuglines2d.wgsl"); pub(crate) const DIMMENSION: &str = "2d"; } // See debuglines.wgsl for explanation on 2 shaders. //pub(crate) const SHADER_FILE: &str = include_str!("debuglines.wgsl"); pub(crate) const DEBUG_LINES_SHADER_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 17477439189930443325); #[derive(Resource)] pub(crate) struct DebugLinesConfig { depth_test: bool, } /// Bevy plugin, for initializing stuff. /// /// # Usage /// /// ```.ignore /// use bevy::prelude::*; /// use bevy_prototype_debug_lines::*; /// /// App::new() /// .add_plugins(DefaultPlugins) /// .add_plugin(DebugLinesPlugin::default()) /// .run(); /// ``` /// /// Alternatively, you can initialize the plugin with depth testing, so that /// debug lines cut through geometry. To do this, use [`DebugLinesPlugin::with_depth_test(true)`]. /// ```.ignore /// use bevy::prelude::*; /// use bevy_prototype_debug_lines::*; /// /// App::new() /// .add_plugins(DefaultPlugins) /// .add_plugin(DebugLinesPlugin::with_depth_test(true)) /// .run(); /// ``` #[derive(Debug, Default, Clone)] pub struct DebugLinesPlugin { depth_test: bool, } impl DebugLinesPlugin { /// Controls whether debug lines should be drawn with depth testing enabled /// or disabled. /// /// # Arguments /// /// * `val` - True if lines should intersect with other geometry, or false /// if lines should always draw on top be drawn on top (the default). pub fn with_depth_test(val: bool) -> Self { Self { depth_test: val } } } impl Plugin for DebugLinesPlugin { fn build(&self, app: &mut App) { use bevy::render::{render_resource::SpecializedMeshPipelines, RenderApp, RenderStage}; let mut shaders = app.world.get_resource_mut::>().unwrap(); shaders.set_untracked( DEBUG_LINES_SHADER_HANDLE, Shader::from_wgsl(dim::SHADER_FILE), ); app.init_resource::(); app.add_startup_system(setup) .add_system_to_stage(CoreStage::PostUpdate, update.label("draw_lines")); app.sub_app_mut(RenderApp) .add_render_command::() .insert_resource(DebugLinesConfig { depth_test: self.depth_test, }) .init_resource::() .init_resource::>() .add_system_to_stage(RenderStage::Extract, extract) .add_system_to_stage(RenderStage::Queue, dim::queue); info!("Loaded {} debug lines plugin.", dim::DIMMENSION); } } // Number of meshes to separate line buffers into. // We don't really do culling currently but this is a gateway to that. const MESH_COUNT: usize = 4; // Maximum number of points for each individual mesh. const MAX_POINTS_PER_MESH: usize = 2_usize.pow(16); const _MAX_LINES_PER_MESH: usize = MAX_POINTS_PER_MESH / 2; /// Maximum number of points. pub const MAX_POINTS: usize = MAX_POINTS_PER_MESH * MESH_COUNT; /// Maximum number of unique lines to draw at once. pub const MAX_LINES: usize = MAX_POINTS / 2; const ATTRIBUTE_COLOR: MeshVertexAttribute = MeshVertexAttribute::new("Vertex_Color", 1, VertexFormat::Uint32); fn setup(mut cmds: Commands, mut meshes: ResMut>) { // Spawn a bunch of meshes to use for lines. for i in 0..MESH_COUNT { // Create a new mesh with the number of vertices we need. let mut mesh = Mesh::new(PrimitiveTopology::LineList); mesh.insert_attribute( Mesh::ATTRIBUTE_POSITION, VertexAttributeValues::Float32x3(Vec::with_capacity(MAX_POINTS_PER_MESH)), ); mesh.insert_attribute( ATTRIBUTE_COLOR, VertexAttributeValues::Uint32(Vec::with_capacity(MAX_POINTS_PER_MESH)), ); // https://github.com/Toqozz/bevy_debug_lines/issues/16 //mesh.set_indices(Some(Indices::U16(Vec::with_capacity(MAX_POINTS_PER_MESH)))); cmds.spawn_bundle(( dim::into_handle(meshes.add(mesh)), NotShadowCaster, NotShadowReceiver, NoFrustumCulling, Transform::default(), GlobalTransform::default(), Visibility::default(), ComputedVisibility::default(), DebugLinesMesh(i), )); } } fn update( debug_line_meshes: Query<(&dim::MeshHandle, &DebugLinesMesh)>, time: Res