on-deck/src/slides/standard_slide.rs

123 lines
3.5 KiB
Rust

use crate::config::FrenApiConfig;
use crate::effects::star_field;
use crate::slide::Slide;
use crate::slide_show_config::Context;
use macroquad::color::{BLACK, WHITE};
use macroquad::math::Vec2;
use macroquad::prelude::{
DrawTextureParams, Texture2D, clear_background, draw_texture_ex, load_texture,
};
use macroquad::window::{screen_height, screen_width};
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
#[derive(Debug, Deserialize)]
pub struct StandardSlideConfig {
pub title: String,
pub body: String,
pub image: Option<PathBuf>,
pub voice: Option<String>,
pub audio_track: Option<String>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct AudioTrackRequest {
api_key: String,
voice: String,
phrase: String,
}
#[derive(Debug)]
pub struct StandardSlide {
cfg: StandardSlideConfig,
image: Option<Texture2D>,
audio_started: bool,
}
impl StandardSlide {
pub async fn new(cfg: StandardSlideConfig, asset_path: &Path) -> Box<Self> {
let image = if let Some(image_path) = &cfg.image {
let image_path = asset_path.join(image_path);
Some(load_texture(image_path.to_str().unwrap()).await.unwrap())
} else {
None
};
Box::new(Self {
cfg,
image,
audio_started: false,
})
}
pub fn audio_track(&mut self, api: &FrenApiConfig) {
if !self.audio_started {
self.audio_started = true;
if let Some(track) = &self.cfg.audio_track
&& let Some(voice) = &self.cfg.voice
{
let request = AudioTrackRequest {
api_key: api.api_key.clone(),
voice: voice.to_string(),
phrase: track.to_string(),
};
reqwest::blocking::Client::new()
.post(&api.api_addr)
.json(&request)
.send()
.unwrap();
}
}
}
}
impl Slide for StandardSlide {
fn display(&mut self, ctx: &Context<'_>) {
clear_background(BLACK);
star_field();
self.audio_track(&ctx.cfg.fren_api);
let title_pos = Vec2::new(screen_width() * 0.5, screen_height() * 0.10);
let info = ctx
.slide_show_theme
.heading_config
.draw_text(&self.cfg.title, title_pos);
let body_pos = Vec2::new(
screen_width() * 0.05,
screen_height() * 0.33 + info.text_dimensions.height,
);
ctx.slide_show_theme.body_config.draw_text_box(
&self.cfg.body,
body_pos,
Vec2::new(screen_width() * 0.5, screen_height() * 0.8),
);
if let Some(image) = &self.image {
let size = image.size();
let image_center_pos = Vec2::new(screen_width() * 0.75, screen_height() * 0.5);
let target_image_size = Vec2::new(screen_width() * 0.33, screen_height() * 0.66);
let scale = f32::min(target_image_size.x / size.x, target_image_size.y / size.y);
let new_image_size = size * scale;
let image_pos = image_center_pos - new_image_size * 0.5;
draw_texture_ex(
image,
image_pos.x,
image_pos.y,
WHITE,
DrawTextureParams {
dest_size: Some(new_image_size),
..Default::default()
},
);
}
}
}