1use super::*;
2use crate::{Land, site::generation::PrimitiveTransform};
3use common::terrain::BlockKind;
4use rand::prelude::*;
5use vek::*;
6
7pub struct GliderRing {
9 center: Vec2<i32>,
11 direction: Dir2,
13 number: usize,
15 base: i32,
17 ring_thickness: i32,
19 ring_height: i32,
21 ring_radius: i32,
23}
24
25impl GliderRing {
26 pub fn generate(
27 land: &Land,
28 _rng: &mut impl Rng,
29 _site: &Site,
30 wpos: &Vec2<i32>,
31 number: usize,
32 direction: Dir2,
33 ) -> Self {
34 Self {
35 center: *wpos,
36 direction,
37 number,
38 base: land.get_alt_approx(*wpos) as i32 + 1,
39 ring_thickness: 4,
40 ring_height: 35,
41 ring_radius: 16,
42 }
43 }
44}
45
46impl Structure for GliderRing {
47 #[cfg(feature = "use-dyn-lib")]
48 const UPDATE_FN: &'static [u8] = b"render_glider_ring\0";
49
50 #[cfg_attr(feature = "be-dyn-lib", unsafe(export_name = "render_glider_ring"))]
51 fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
52 let rotate_turns = match self.direction {
53 Dir2::X => 0,
54 Dir2::Y => 1,
55 Dir2::NegX => 2,
56 Dir2::NegY => 3,
57 };
58 let rotation_center = Vec3::new(self.center.x, self.center.y, self.base);
59
60 let red = Fill::Brick(BlockKind::Wood, Rgb::new(200, 0, 0), 24);
61 let green = Fill::Brick(BlockKind::Wood, Rgb::new(0, 200, 0), 24);
62 let white = Fill::Brick(BlockKind::GlowingRock, Rgb::new(200, 200, 200), 24);
63 let black = Fill::Brick(BlockKind::Wood, Rgb::new(0, 0, 0), 24);
64 let wood = Fill::Brick(BlockKind::Wood, Rgb::new(55, 25, 8), 24);
65
66 let ring_base = self.base + self.ring_height;
67 let ring_diameter = self.ring_radius * 2;
68 let ring_top = ring_base + ring_diameter;
69
70 let base = painter.aabb(Aabb {
72 min: Vec2::new(self.center.x - 1, self.center.y - 2).with_z(self.base - 30),
73 max: Vec2::new(self.center.x + 2, self.center.y + 2)
74 .with_z(self.base + self.ring_height + 1),
75 });
76 let green_ring = painter.horizontal_cylinder(
78 Aabb {
79 min: Vec2::new(self.center.x - 1, self.center.y - self.ring_radius)
80 .with_z(ring_base),
81 max: Vec2::new(self.center.x, self.center.y + self.ring_radius).with_z(ring_top),
82 },
83 Dir2::X,
84 );
85 let red_ring = painter.horizontal_cylinder(
86 Aabb {
87 min: Vec2::new(self.center.x, self.center.y - self.ring_radius).with_z(ring_base),
88 max: Vec2::new(self.center.x + 2, self.center.y + self.ring_radius)
89 .with_z(ring_top),
90 },
91 Dir2::X,
92 );
93 let front_white_ring = painter.horizontal_cylinder(
94 Aabb {
95 min: Vec2::new(
96 self.center.x - 1,
97 self.center.y - self.ring_radius + self.ring_thickness - 1,
98 )
99 .with_z(ring_base + self.ring_thickness - 1),
100 max: Vec2::new(
101 self.center.x,
102 self.center.y + self.ring_radius - self.ring_thickness + 1,
103 )
104 .with_z(ring_top - self.ring_thickness + 1),
105 },
106 Dir2::X,
107 );
108 let back_white_ring = painter.horizontal_cylinder(
109 Aabb {
110 min: Vec2::new(
111 self.center.x + 1,
112 self.center.y - self.ring_radius + self.ring_thickness - 1,
113 )
114 .with_z(ring_base + self.ring_thickness - 1),
115 max: Vec2::new(
116 self.center.x + 2,
117 self.center.y + self.ring_radius - self.ring_thickness + 1,
118 )
119 .with_z(ring_top - self.ring_thickness + 1),
120 },
121 Dir2::X,
122 );
123 let mut black_fills = Vec::new();
124 for y in self.center.y - self.ring_radius + self.ring_thickness - 1
125 ..=self.center.y + self.ring_radius - self.ring_thickness + 1
126 {
127 if y % 4 == 0 {
128 let stripe = painter
129 .aabb(Aabb {
130 min: Vec2::new(self.center.x - 1, y + 1).with_z(ring_base),
131 max: Vec2::new(self.center.x, y + 3).with_z(ring_top),
132 })
133 .intersect(front_white_ring);
134 black_fills.push(stripe);
135 }
136 }
137 for z in ring_base + self.ring_thickness + 3..=ring_top - self.ring_thickness - 9 {
138 if z % 4 == 0 {
139 let stripe = painter
140 .aabb(Aabb {
141 min: Vec2::new(
142 self.center.x - 1,
143 self.center.y - self.ring_radius + self.ring_thickness - 1,
144 )
145 .with_z(z + 1),
146 max: Vec2::new(
147 self.center.x,
148 self.center.y + self.ring_radius - self.ring_thickness + 1,
149 )
150 .with_z(z + 3),
151 })
152 .intersect(front_white_ring);
153 black_fills.push(stripe);
154 }
155 }
156 let ring_clear = painter.horizontal_cylinder(
157 Aabb {
158 min: Vec2::new(
159 self.center.x - 5,
160 self.center.y - self.ring_radius + self.ring_thickness,
161 )
162 .with_z(ring_base + self.ring_thickness),
163 max: Vec2::new(
164 self.center.x + 6,
165 self.center.y + self.ring_radius - self.ring_thickness,
166 )
167 .with_z(ring_top - self.ring_thickness),
168 },
169 Dir2::X,
170 );
171 let sign_base = ring_top - self.ring_thickness - 1;
173 let sign_height = 7;
174 let sign = painter.aabb(Aabb {
175 min: Vec2::new(self.center.x - 1, self.center.y - 3).with_z(sign_base),
176 max: Vec2::new(self.center.x + 1, self.center.y + 3).with_z(sign_base + sign_height),
177 });
178 let numeral_origin = Vec3::new(self.center.x, self.center.y - 2, sign_base + 1);
180 let numeral = painter
183 .numeral(numeral_origin, self.number)
184 .rotate_z_90_about(2, rotation_center);
185
186 let wood_fills = [base];
187 let red_fills = [red_ring];
188 let green_fills = [green_ring];
189 let white_fills = [front_white_ring, back_white_ring];
190 let sign_fills = [numeral];
191 let black_sign_fills = [sign];
192 let clear_fills = [ring_clear];
193
194 let fills = [
195 (&wood_fills as &[_], Some(wood)),
196 (&red_fills, Some(red)),
197 (&green_fills, Some(green)),
198 (&white_fills, Some(white.clone())),
199 (&black_fills, Some(black.clone())),
200 (&clear_fills, None),
201 (&black_sign_fills, Some(black)),
202 (&sign_fills, Some(white)),
203 ];
204 for (primitives, fill_color_maybe) in fills {
205 for prim in primitives {
206 if let Some(fill_color) = &fill_color_maybe {
207 prim.rotate_z_90_about(rotate_turns, rotation_center)
208 .fill(fill_color.clone());
209 } else {
210 prim.rotate_z_90_about(rotate_turns, rotation_center)
211 .clear();
212 }
213 }
214 }
215 }
216}