experimental SVG-based video rendering engine made for music videos. React to MIDI or arbitrary signals from your DAW through "probe" VSTs
1use rand::{Rng, distr::uniform::SampleRange, seq::IndexedRandom};
2
3use crate::{LineSegment, Object, Point, Region, Shape};
4
5impl Shape {
6 pub fn random_starting_at<R: rand::Rng>(
7 rng: &mut R,
8 start: Point,
9 region: &Region,
10 line_width: f32,
11 polygon_vertices_range: impl SampleRange<usize>,
12 ) -> Self {
13 match rng.random_range(1..=7) {
14 1 => Self::random_polygon(rng, region, polygon_vertices_range),
15 2 => Self::BigCircle(start),
16 3 => Self::BigDot(start),
17 4 => Self::Dot(start),
18 5 => Self::CurveInward(
19 start,
20 region.random_end(rng, start),
21 line_width,
22 ),
23 6 => Self::CurveOutward(
24 start,
25 region.random_end(rng, start),
26 line_width,
27 ),
28 7 => Self::Line(
29 Point::random(rng, region),
30 Point::random(rng, region),
31 line_width,
32 ),
33 _ => unreachable!(),
34 }
35 }
36
37 pub fn random_polygon<R: rand::Rng>(
38 rng: &mut R,
39 region: &Region,
40 vertices_range: impl SampleRange<usize>,
41 ) -> Shape {
42 let number_of_anchors = rng.random_range(vertices_range);
43 let start = Point::random(rng, region);
44 let mut lines: Vec<LineSegment> = vec![];
45 for _ in 0..number_of_anchors {
46 let next_anchor = Point::random(rng, region);
47 lines.push(Self::random_line_segment(rng, next_anchor));
48 }
49 Shape::Polygon(start, lines)
50 }
51
52 pub fn random_line_segment<R: rand::Rng>(
53 rng: &mut R,
54 end: Point,
55 ) -> LineSegment {
56 match rng.random_range(1..=3) {
57 1 => LineSegment::Straight(end),
58 2 => LineSegment::InwardCurve(end),
59 3 => LineSegment::OutwardCurve(end),
60 _ => unreachable!(),
61 }
62 }
63
64 pub fn random(
65 rng: &mut impl Rng,
66 region: &Region,
67 line_width: f32,
68 polygon_vertices_range: impl SampleRange<usize>,
69 ) -> Shape {
70 let start = Point::random(rng, region);
71 Shape::random_starting_at(
72 rng,
73 start,
74 region,
75 line_width,
76 polygon_vertices_range,
77 )
78 }
79
80 pub fn random_curve_within(
81 rng: &mut impl Rng,
82 region: &Region,
83 line_width: f32,
84 ) -> Shape {
85 let start = region.random_point(rng);
86 match rng.random_range(1..=3) {
87 1 => Shape::CurveInward(
88 start,
89 region.random_end(rng, start),
90 line_width,
91 ),
92 2 => Shape::CurveOutward(
93 start,
94 region.random_end(rng, start),
95 line_width,
96 ),
97 3 => Shape::Line(
98 Point::random(rng, region),
99 Point::random(rng, region),
100 line_width,
101 ),
102 _ => unreachable!(),
103 }
104 }
105}
106
107impl Object {
108 pub fn flickering(self, rng: &mut impl Rng, amplitude: f32) -> Self {
109 self.opacified(rng.random_range((1.0 - amplitude).max(0.0)..1.0))
110 }
111
112 pub fn pick_random_tag<R: rand::Rng>(
113 &mut self,
114 rng: &mut R,
115 tags: &[&str],
116 ) -> String {
117 self.tag(tags.choose(rng).expect("Coudln't choose tag"))
118 }
119}