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, pub voice: Option, pub audio_track: Option, } #[derive(Debug, Deserialize, Serialize)] pub struct AudioTrackRequest { api_key: String, voice: String, phrase: String, } #[derive(Debug)] pub struct StandardSlide { cfg: StandardSlideConfig, image: Option, audio_started: bool, } impl StandardSlide { pub async fn new(cfg: StandardSlideConfig, asset_path: &Path) -> Box { 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() }, ); } } }