#![allow(dead_code)]
use std::env;
use macroquad::prelude::*;
use rae::shader;
use rae::{Palette, Rect, Rgba};
pub fn max_frames_from_env() -> Option<u64> {
env::var("RAE_RENDER_DEMO_FRAMES")
.ok()
.and_then(|value| value.parse::<u64>().ok())
}
pub fn should_stop(frames: u64, max_frames: Option<u64>) -> bool {
is_key_pressed(KeyCode::Escape) || max_frames.is_some_and(|max_frames| frames >= max_frames)
}
pub fn to_mq(color: Rgba) -> Color {
Color::new(color.r, color.g, color.b, color.a)
}
pub fn rgba8(r: u8, g: u8, b: u8, a: u8) -> Color {
to_mq(Rgba::rgba8(r, g, b, a))
}
pub fn draw_scene_backdrop(palette: &Palette, time: f32) {
clear_background(to_mq(palette.background));
let width = screen_width();
let height = screen_height();
for index in 0..28 {
let y = index as f32 * 42.0 + (time * 7.0).sin() * 4.0;
let alpha = if index % 3 == 0 { 0.040 } else { 0.022 };
draw_line(
0.0,
y,
width,
y + (time * 0.8 + index as f32).sin() * 16.0,
1.0,
to_mq(palette.accent.with_alpha(alpha)),
);
}
for index in 0..22 {
let x = index as f32 * 76.0 + (time * 5.0).cos() * 6.0;
draw_line(
x,
0.0,
x + (time * 0.6 + index as f32).cos() * 18.0,
height,
1.0,
rgba8(87, 118, 190, 11),
);
}
draw_glow(
width * (0.24 + (time * 0.07).sin() * 0.04),
height * 0.18,
280.0,
Rgba::rgb8(93, 144, 255).with_alpha(0.18),
8,
);
draw_glow(
width * 0.82,
height * (0.72 + (time * 0.09).cos() * 0.05),
380.0,
Rgba::rgb8(91, 255, 211).with_alpha(0.13),
10,
);
draw_glow(
width * (0.58 + (time * 0.05).cos() * 0.05),
height * 0.42,
260.0,
Rgba::rgb8(190, 94, 255).with_alpha(0.10),
7,
);
}
pub fn load_rae_material(source: shader::ShaderSource) -> Option<Material> {
let uniforms = source
.uniforms
.iter()
.map(|uniform| {
let kind = match uniform.kind {
shader::ShaderUniformKind::Float1 => UniformType::Float1,
shader::ShaderUniformKind::Float2 => UniformType::Float2,
};
UniformDesc::new(uniform.name, kind)
})
.collect();
load_material(
ShaderSource::Glsl {
vertex: source.vertex,
fragment: source.fragment,
},
MaterialParams {
uniforms,
..Default::default()
},
)
.ok()
}
pub fn draw_shader_rect(
material: Option<&Material>,
rect: Rect,
time: f32,
intensity: f32,
resolution: Vec2,
) {
if let Some(material) = material {
material.set_uniform("u_time", time);
material.set_uniform("u_resolution", resolution);
material.set_uniform("u_intensity", intensity);
gl_use_material(material);
draw_rectangle(rect.x, rect.y, rect.width, rect.height, WHITE);
gl_use_default_material();
}
}
pub fn draw_glow(x: f32, y: f32, radius: f32, color: Rgba, layers: usize) {
for index in (0..layers).rev() {
let t = (index + 1) as f32 / layers.max(1) as f32;
let alpha = color.a * (1.0 - t).powi(2) * 0.8;
draw_circle(x, y, radius * t, to_mq(color.with_alpha(alpha)));
}
}
pub fn draw_shadow(rect: Rect, radius: f32, strength: f32) {
for index in 0..8 {
let offset = 2.0 + index as f32 * 2.0;
let spread = index as f32 * 2.2;
let shadow = Rect::new(
rect.x - spread,
rect.y + offset - spread,
rect.width + spread * 2.0,
rect.height + spread * 2.0,
);
draw_rounded_rect(
shadow,
radius + spread,
Color::new(
0.0,
0.0,
0.0,
strength * (0.12 - index as f32 * 0.011).max(0.0),
),
);
}
}
pub fn draw_glass_panel(rect: Rect, radius: f32, palette: &Palette, accent: Rgba, focused: bool) {
draw_shadow(rect, radius, if focused { 1.2 } else { 0.82 });
draw_rounded_rect(
rect,
radius,
to_mq(palette.panel.with_alpha(if focused { 0.74 } else { 0.64 })),
);
let inner = rect.inset(rae::Insets::all(1.0));
draw_rounded_rect(
inner,
(radius - 1.0).max(0.0),
to_mq(
palette
.panel_hot
.with_alpha(if focused { 0.22 } else { 0.13 }),
),
);
draw_rectangle(
rect.x + radius,
rect.y + 1.0,
(rect.width - radius * 2.0).max(0.0),
1.0,
to_mq(Rgba::WHITE.with_alpha(0.16)),
);
draw_rectangle_lines(
rect.x,
rect.y,
rect.width,
rect.height,
if focused { 1.7 } else { 1.0 },
to_mq(accent.with_alpha(if focused { 0.70 } else { 0.34 })),
);
}
pub fn draw_section_header(label: &str, rect: Rect, accent: Rgba, muted: Rgba) {
draw_text_line(label, rect.x, rect.y, 12.0, to_mq(accent.with_alpha(0.90)));
draw_line(
rect.x + 92.0,
rect.y - 4.0,
rect.right(),
rect.y - 4.0,
1.0,
to_mq(muted.with_alpha(0.23)),
);
}
pub fn draw_pill(rect: Rect, label: &str, color: Rgba, text: Rgba) {
draw_rounded_rect(rect, rect.height * 0.5, to_mq(color.with_alpha(0.17)));
draw_rectangle_lines(
rect.x,
rect.y,
rect.width,
rect.height,
1.0,
to_mq(color.with_alpha(0.42)),
);
draw_text_line(
label,
rect.x + 12.0,
rect.y + rect.height * 0.64,
13.0,
to_mq(text),
);
}
pub fn draw_metric(rect: Rect, label: &str, value: &str, color: Rgba, palette: &Palette) {
draw_rounded_rect(rect, 16.0, to_mq(palette.background.with_alpha(0.42)));
draw_rectangle_lines(
rect.x,
rect.y,
rect.width,
rect.height,
1.0,
to_mq(color.with_alpha(0.32)),
);
draw_text_line(
label,
rect.x + 14.0,
rect.y + 22.0,
12.0,
to_mq(palette.muted),
);
draw_text_line(value, rect.x + 14.0, rect.y + 51.0, 24.0, to_mq(color));
}
pub fn draw_text_line(text: &str, x: f32, y: f32, size: f32, color: Color) {
draw_text_ex(
text,
x,
y,
TextParams {
font_size: size as u16,
color,
..Default::default()
},
);
}
pub fn draw_wrapped_text(
text: &str,
x: f32,
mut y: f32,
width: f32,
size: f32,
line_height: f32,
color: Color,
) -> f32 {
for source_line in text.lines() {
let mut line = String::new();
for word in source_line.split_whitespace() {
let candidate = if line.is_empty() {
word.to_string()
} else {
format!("{line} {word}")
};
if measure_text(&candidate, None, size as u16, 1.0).width > width && !line.is_empty() {
draw_text_line(&line, x, y, size, color);
y += line_height;
line.clear();
line.push_str(word);
} else {
line = candidate;
}
}
if !line.is_empty() {
draw_text_line(&line, x, y, size, color);
y += line_height;
}
}
y
}
pub fn draw_rounded_rect(rect: Rect, radius: f32, color: Color) {
if rect.width <= 0.0 || rect.height <= 0.0 {
return;
}
let radius = radius.min(rect.width * 0.5).min(rect.height * 0.5).max(0.0);
draw_rectangle(
rect.x + radius,
rect.y,
(rect.width - radius * 2.0).max(0.0),
rect.height,
color,
);
draw_rectangle(
rect.x,
rect.y + radius,
rect.width,
(rect.height - radius * 2.0).max(0.0),
color,
);
draw_circle(rect.x + radius, rect.y + radius, radius, color);
draw_circle(rect.right() - radius, rect.y + radius, radius, color);
draw_circle(rect.x + radius, rect.bottom() - radius, radius, color);
draw_circle(rect.right() - radius, rect.bottom() - radius, radius, color);
}