1use bevy::{color::palettes::tailwind, prelude::*};
2
3mod plugin;
4pub mod rendering;
5pub mod systems;
6
7pub use plugin::*;
8use rendering::*;
9use systems::*;
10
11pub mod prelude {
12 pub use crate::plugin::*;
13 pub use super::{
14 Grid,
15 SubGrid,
16 GridAlignment,
17 GridAxis,
18 TrackedGrid,
19 };
20}
21
22#[derive(Component, Clone, Debug)]
24pub struct Grid {
25 pub spacing: f32,
27 pub count: usize,
29 pub color: Color,
31 pub alpha_mode: AlphaMode,
33}
34
35impl Grid {
36 pub const DEFAULT_SRGBA: Srgba = tailwind::GRAY_400;
37 pub const DEFAULT_ALPHA: f32 = 0.5_f32;
38}
39
40impl Default for Grid {
41 fn default() -> Self {
42 Self {
43 spacing: 0.25_f32,
44 count: 8,
45 color: Color::Srgba(Self::DEFAULT_SRGBA.with_alpha(Self::DEFAULT_ALPHA)),
46 alpha_mode: AlphaMode::Blend,
47 }
48 }
49}
50
51#[derive(Component)]
53pub struct GridChild;
54
55#[derive(Component, Clone, Debug)]
58pub struct SubGrid {
59 pub count: usize,
61 pub color: Color,
63}
64
65impl SubGrid {
66 pub const DEFAULT_SRGBA: Srgba = tailwind::GRAY_500;
67}
68
69impl Default for SubGrid {
70 fn default() -> Self {
71 Self {
72 count: 9,
73 color: Color::Srgba(Self::DEFAULT_SRGBA.with_alpha(Grid::DEFAULT_ALPHA)),
74 }
75 }
76}
77
78#[derive(Component)]
80pub struct SubGridChild;
81
82#[derive(Component, Default, Debug, Copy, Clone, PartialEq, Eq)]
84pub enum GridAlignment {
85 X,
86 #[default]
87 Y,
88 Z,
89}
90
91impl GridAlignment {
92 pub const fn to_axis_vec3(&self) -> Vec3 {
93 match self {
94 Self::X => Vec3::X,
95 Self::Y => Vec3::Y,
96 Self::Z => Vec3::Z,
97 }
98 }
99
100 pub fn to_inverted_axis_vec3(&self) -> Vec3 {
101 Vec3::ONE - self.to_axis_vec3()
102 }
103
104 pub const fn shift_vec3(&self, input: Vec3) -> Vec3 {
106 match self {
107 Self::X => Vec3::new(input.y, input.z, input.x),
108 Self::Y => input,
109 Self::Z => Vec3::new(input.z, input.x, input.y),
110 }
111 }
112}
113
114impl From<GridAlignment> for Vec3 {
115 fn from(val: GridAlignment) -> Self {
116 val.to_inverted_axis_vec3()
117 }
118}
119
120#[derive(Component, Clone, Debug)]
123pub struct GridAxis {
124 pub x: Option<Color>,
126 pub y: Option<Color>,
128 pub z: Option<Color>,
130}
131
132impl GridAxis {
133 pub const fn new_empty() -> Self {
136 Self {
137 x: None,
138 y: None,
139 z: None,
140 }
141 }
142
143 pub const fn new_rgb() -> Self {
146 Self {
147 x: Some(Color::Srgba(tailwind::RED_500)),
148 y: Some(Color::Srgba(tailwind::GREEN_500)),
149 z: Some(Color::Srgba(tailwind::BLUE_500)),
150 }
151 }
152
153 pub fn create_single_axis(size: f32, alignment: GridAlignment) -> [Vec3; 2] {
155 [
156 alignment.shift_vec3(Vec3::new(0.0_f32, size, 0.0_f32)),
157 alignment.shift_vec3(Vec3::new(0.0_f32, -size, 0.0_f32)),
158 ]
159 }
160
161 pub fn create_axis(&self) -> (Vec<(GridAlignment, Color)>, Vec<GridAlignment>) {
164 let mut axis = Vec::new();
165 let mut unused = Vec::new();
166
167 if let Some(color) = self.x {
168 axis.push((GridAlignment::X, color));
169 } else {
170 unused.push(GridAlignment::X);
171 }
172 if let Some(color) = self.y {
174 axis.push((GridAlignment::Y, color));
175 }
176 if let Some(color) = self.z {
177 axis.push((GridAlignment::Z, color));
178 } else {
179 unused.push(GridAlignment::Z);
180 }
181
182 (axis, unused)
183 }
184
185 pub const fn default_axis() -> [GridAlignment; 2] {
187 [GridAlignment::X, GridAlignment::Z]
188 }
189
190 pub const fn get_by_alignment(&self, alignment: &GridAlignment) -> Option<Color> {
192 match alignment {
193 GridAlignment::X => self.x,
194 GridAlignment::Y => self.y,
195 GridAlignment::Z => self.z,
196 }
197 }
198}
199
200impl Default for GridAxis {
201 fn default() -> Self {
202 Self::new_empty()
203 }
204}
205
206#[derive(Component)]
208pub struct GridAxisChild;
209
210#[derive(Component, Clone, Debug, Default)]
214pub struct TrackedGrid {
215 pub alignment: GridAlignment,
217 pub offset: f32,
219 pub tracking_override: Option<Entity>,
221}