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