123 lines
3.5 KiB
Rust
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()
|
|
},
|
|
);
|
|
}
|
|
}
|
|
}
|