wde_terrain_grid/core/
grid_entity.rs1use bevy::prelude::*;
2
3use crate::{
4 core::{
5 entries::PlacementConfigEntry,
6 grid::{GridTilePos, TILE_SIZE}
7 },
8 prelude::Grid
9};
10
11#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Reflect)]
13pub enum GridRotation {
14 #[default]
15 R0,
16 R90,
17 R180,
18 R270
19}
20impl GridRotation {
21 pub fn rotation(self) -> f32 {
23 match self {
24 GridRotation::R0 => 0.0,
25 GridRotation::R90 => std::f32::consts::FRAC_PI_2,
26 GridRotation::R180 => std::f32::consts::PI,
27 GridRotation::R270 => 3.0 * std::f32::consts::FRAC_PI_2
28 }
29 }
30}
31
32#[derive(Component, Clone, Debug, Reflect)]
34#[reflect(Component)]
35pub struct GridEntity {
36 entry: PlacementConfigEntry,
37 center: Vec2,
38 rotation: GridRotation,
39 bbox: (Vec2, Vec2), footprint: Vec<GridTilePos>
41}
42impl GridEntity {
43 pub fn new(center: Vec2, rotation: GridRotation, entry: PlacementConfigEntry) -> Self {
50 let (center, bbox, footprint) = compute_footprint(center, entry.extent, rotation);
51 GridEntity {
52 entry,
53 center,
54 rotation,
55 bbox,
56 footprint
57 }
58 }
59 pub fn center(&self) -> Vec2 {
61 self.center
62 }
63 pub fn rotation(&self) -> GridRotation {
65 self.rotation
66 }
67 pub fn bbox(&self) -> (Vec2, Vec2) {
69 self.bbox
70 }
71 pub fn footprint(&self) -> &Vec<GridTilePos> {
73 &self.footprint
74 }
75 pub fn entry(&self) -> &PlacementConfigEntry {
77 &self.entry
78 }
79}
80
81fn compute_footprint(
82 center: Vec2,
83 extent: UVec2,
84 rotation: GridRotation
85) -> (Vec2, (Vec2, Vec2), Vec<GridTilePos>) {
86 let extent = match rotation {
88 GridRotation::R0 | GridRotation::R180 => extent,
89 GridRotation::R90 | GridRotation::R270 => UVec2::new(extent.y, extent.x)
90 };
91
92 let offset_to_center_object =
94 Vec2::new(extent.x as f32, extent.y as f32) * TILE_SIZE / 2.0 - TILE_SIZE / 2.0;
95
96 let mut footprint = Vec::new();
98 for x in 0..extent.x {
99 for z in 0..extent.y {
100 let local_pos =
101 center - offset_to_center_object + Vec2::new(x as f32, z as f32) * TILE_SIZE;
102 let (chunk_pos, local_pos) = Grid::get_nearest_tile(local_pos);
103 footprint.push((chunk_pos, (local_pos.0, local_pos.1)));
104 }
105 }
106
107 let bottom_left_pos = center - offset_to_center_object
109 + Vec2::new(extent.x as f32 - 1.0, extent.y as f32 - 1.0) * TILE_SIZE;
110 let bottom_left_pos = Grid::get_tile_world_pos(Grid::get_nearest_tile(bottom_left_pos));
111 let top_right_pos = center - offset_to_center_object;
112 let top_right_pos = Grid::get_tile_world_pos(Grid::get_nearest_tile(top_right_pos));
113 let center = (bottom_left_pos + top_right_pos) / 2.0;
114
115 (center, (bottom_left_pos, top_right_pos), footprint)
116}