bevy_ghx_grid/debug_plugin/
view.rs

1use bevy::{
2    color::Color,
3    ecs::{component::Component, query::With, system::Query},
4    gizmos::{config::GizmoConfigGroup, gizmos::Gizmos},
5    math::{Vec2, Vec3, Vec3Swizzles},
6    reflect::Reflect,
7    transform::components::Transform,
8};
9use ghx_grid::cartesian::{coordinates::CartesianCoordinates, grid::CartesianGrid};
10
11/// 3d-specific (`Camera3d`) component-marker of a grid debug view
12#[derive(Component, Default)]
13#[require(DebugGridView)]
14pub struct DebugGridView3d;
15
16/// 2d-specific (`Camera2d`) component-marker of a grid debug view
17#[derive(Component, Default)]
18#[require(DebugGridView)]
19pub struct DebugGridView2d;
20
21#[derive(Default, Reflect, GizmoConfigGroup)]
22/// The Gizmo configuration for grid views
23pub struct GridViewGizmoGroup;
24
25/// Component used on all debug grid to store configuration.
26///
27/// Updating the component members will update the grid debug view directly
28#[derive(Component)]
29pub struct DebugGridView {
30    /// Whether or not to display the grid
31    pub display_grid: bool,
32    /// Whether or not to display the grid markers
33    pub display_markers: bool,
34    /// Color of the displayed grid.
35    pub color: Color,
36    /// Size of a grid node in world units on all 3 axis. Defaults to [`Vec3::ONE`]
37    pub node_size: Vec3,
38}
39impl Default for DebugGridView {
40    fn default() -> Self {
41        Self {
42            display_grid: true,
43            display_markers: true,
44            color: Default::default(),
45            node_size: Vec3::ONE,
46        }
47    }
48}
49impl DebugGridView {
50    /// Creates a new [`DebugGridView`]
51    pub fn new(display_grid: bool, display_markers: bool, color: Color, node_size: Vec3) -> Self {
52        Self {
53            display_grid,
54            display_markers,
55            color,
56            node_size,
57        }
58    }
59}
60
61/// System that uses [`Gizmos`] to render the debug grid every frame.
62///
63/// To be used with a `Camera3d`
64pub fn draw_debug_grids_3d<T: CartesianCoordinates>(
65    mut gizmos: Gizmos,
66    debug_grids: Query<(&Transform, &CartesianGrid<T>, &DebugGridView), With<DebugGridView3d>>,
67) {
68    for (transform, grid, view) in debug_grids.iter() {
69        if !view.display_grid {
70            continue;
71        }
72        let end = Vec3 {
73            x: (grid.size_x() as f32) * view.node_size.x,
74            y: (grid.size_y() as f32) * view.node_size.y,
75            z: (grid.size_z() as f32) * view.node_size.z,
76        };
77        for x in 0..=grid.size_x() {
78            let current_x = x as f32 * view.node_size.x;
79            let points = vec![
80                transform.transform_point(Vec3::new(current_x, 0., 0.)),
81                transform.transform_point(Vec3::new(current_x, end.y, 0.)),
82                transform.transform_point(Vec3::new(current_x, end.y, end.z)),
83                transform.transform_point(Vec3::new(current_x, 0., end.z)),
84                transform.transform_point(Vec3::new(current_x, 0., 0.)),
85            ];
86            gizmos.linestrip(points, view.color);
87        }
88        for y in 0..=grid.size_y() {
89            let current_y = y as f32 * view.node_size.y;
90            let points = vec![
91                transform.transform_point(Vec3::new(0., current_y, 0.)),
92                transform.transform_point(Vec3::new(end.x, current_y, 0.)),
93                transform.transform_point(Vec3::new(end.x, current_y, end.z)),
94                transform.transform_point(Vec3::new(0., current_y, end.z)),
95                transform.transform_point(Vec3::new(0., current_y, 0.)),
96            ];
97            gizmos.linestrip(points, view.color);
98        }
99        for z in 0..=grid.size_z() {
100            let current_z = z as f32 * view.node_size.z;
101            let points = vec![
102                transform.transform_point(Vec3::new(0., 0., current_z)),
103                transform.transform_point(Vec3::new(end.x, 0., current_z)),
104                transform.transform_point(Vec3::new(end.x, end.y, current_z)),
105                transform.transform_point(Vec3::new(0., end.y, current_z)),
106                transform.transform_point(Vec3::new(0., 0., current_z)),
107            ];
108            gizmos.linestrip(points, view.color);
109        }
110    }
111}
112
113/// System that uses [`Gizmos`] to render the debug grid every frame.
114///
115/// To be used with a `Camera2d`
116pub fn draw_debug_grids_2d<T: CartesianCoordinates>(
117    mut gizmos: Gizmos,
118    debug_grids: Query<(&Transform, &CartesianGrid<T>, &DebugGridView), With<DebugGridView2d>>,
119) {
120    for (transform, grid, view) in debug_grids.iter() {
121        if !view.display_grid {
122            continue;
123        }
124        let end = Vec2 {
125            x: (grid.size_x() as f32) * view.node_size.x,
126            y: (grid.size_y() as f32) * view.node_size.y,
127        };
128        for y in 0..=grid.size_y() {
129            let current_y = y as f32 * view.node_size.y;
130            let from = transform.transform_point(Vec3::new(0., current_y, 0.));
131            let to = transform.transform_point(Vec3::new(end.x, current_y, 0.));
132            gizmos.line_2d(from.xy(), to.xy(), view.color);
133        }
134        for x in 0..=grid.size_x() {
135            let current_x = x as f32 * view.node_size.x;
136            let from = transform.transform_point(Vec3::new(current_x, 0., 0.));
137            let to = transform.transform_point(Vec3::new(current_x, end.y, 0.));
138            gizmos.line_2d(from.xy(), to.xy(), view.color);
139        }
140    }
141}