monorepo/cyberpunk-slideshow/src/main.rs

160 lines
4.2 KiB
Rust
Raw Normal View History

use std::{fs::File, io::Read, path::Path, rc::Rc, time::Duration};
2024-10-05 00:56:37 +00:00
use cyberpunk::{AsymLine, AsymLineCutout, GlowPen, Pen, Text};
use glib::Object;
use gtk::{glib, prelude::*, subclass::prelude::*};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "lowercase")]
enum TextArea {
Top,
Middle,
Bottom,
}
#[derive(Serialize, Deserialize, Debug)]
struct Fade {
duration: Duration,
}
#[derive(Serialize, Deserialize, Debug)]
enum AnimationIn {
Fade(Fade),
}
#[derive(Serialize, Deserialize, Debug)]
enum AnimationOut {
Fade(Fade),
}
#[derive(Serialize, Deserialize, Debug)]
struct ScriptElement {
text: String,
position: TextArea,
transition_in: AnimationIn,
}
#[derive(Serialize, Deserialize, Debug)]
struct Script(Vec<ScriptElement>);
impl Script {
fn from_file(path: &Path) -> Result<Script, serde_yml::Error> {
let mut buf: Vec<u8> = Vec::new();
let mut f = File::open(path).unwrap();
f.read_to_end(&mut buf).unwrap();
let script = serde_yml::from_slice(&buf)?;
Ok(Self(script))
}
fn iter<'a>(&'a self) -> impl Iterator<Item = &'a ScriptElement> {
self.0.iter()
}
}
#[derive(Default)]
pub struct CyberScreenPrivate {}
#[glib::object_subclass]
impl ObjectSubclass for CyberScreenPrivate {
const NAME: &'static str = "CyberScreen";
type Type = CyberScreen;
type ParentType = gtk::DrawingArea;
}
impl ObjectImpl for CyberScreenPrivate {}
impl WidgetImpl for CyberScreenPrivate {}
impl DrawingAreaImpl for CyberScreenPrivate {}
glib::wrapper! {
pub struct CyberScreen(ObjectSubclass<CyberScreenPrivate>) @extends gtk::DrawingArea, gtk::Widget;
}
impl CyberScreen {
pub fn new() -> Self {
let s: Self = Object::builder().build();
s.set_draw_func({
move |_, context, width, height| {
let _ = context.set_source_rgb(0., 0., 0.);
let _ = context.paint();
let pen = GlowPen::new(width, height, 2., 8., (0.7, 0., 1.));
AsymLine {
orientation: gtk::Orientation::Horizontal,
start_x: 50.,
start_y: height as f64 / 2.,
start_length: 75.,
height: 50.,
2024-10-05 00:56:37 +00:00
end_length: 75.,
invert: false,
}
.draw(&pen);
pen.stroke();
2024-10-05 00:56:37 +00:00
AsymLineCutout {
orientation: gtk::Orientation::Horizontal,
start_x: 50.,
start_y: height as f64 / 4. * 3.,
start_length: 75.,
cutout_length: 15.,
end_length: 75.,
height: 15.,
invert: true,
}.draw(&pen);
pen.stroke();
let tracery = pen.finish();
let _ = context.set_source(tracery);
let _ = context.paint();
2024-10-05 00:56:37 +00:00
let text = Text::new("Test text".to_owned(), &context, 64.);
let text_extents = text.extents();
context.move_to(20., text_extents.height() + 40.);
context.set_source_rgb(0.7, 0., 1.);
text.draw();
}
});
s
}
}
fn main() {
/*
let script: Script = Script(vec![ScriptElement {
text: "abcdefg".to_owned(),
position: TextArea::Top,
transition_in: AnimationIn::Fade(Fade {
duration: Duration::from_secs(10),
}),
}]);
println!("{}", serde_yml::to_string(&script).unwrap());
*/
let script = Script::from_file(Path::new("./script.yml")).unwrap();
for element in script.iter() {
println!("{:?}", element);
}
let app = gtk::Application::builder()
.application_id("com.luminescent-dreams.cyberpunk-slideshow")
.build();
app.connect_activate(|app| {
let window = gtk::ApplicationWindow::new(app);
window.present();
let screen = CyberScreen::new();
window.set_child(Some(&screen));
window.set_width_request(800);
window.set_height_request(600);
window.present();
});
app.run();
}