Skip to content

Commit

Permalink
Adds seasonal fluff (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
sverrejb authored Oct 10, 2024
1 parent c176802 commit 29fe166
Show file tree
Hide file tree
Showing 18 changed files with 346 additions and 53 deletions.
13 changes: 7 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ serde = { version = "1.0.183", features = ["derive"] }
serde_json = "1.0.104"
serde_with = "3.4.0"
slint = "1.8.0"
rust-embed = "6.8.1"
rust-embed = "8.5.0"
log = "0.4.20"
env_logger = "0.10.1"
tokio = { version = "1.35.1", features = ["rt-multi-thread"] }
tide = "0.16.0"
ical = "0.10"
rand = "0.8.5"

[build-dependencies]
slint-build = "1.8.0"
Binary file added img/seasons/face.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/seasons/halloween/bat-0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/seasons/halloween/bat-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/seasons/halloween/bat-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/seasons/halloween/bat-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/seasons/halloween/bat-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/seasons/halloween/bat-5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/seasons/halloween/bat-6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/seasons/halloween/bat-7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/seasons/halloween/bat-8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod forecast;
mod selfie;
mod xkcd;
mod transportation;
mod seasons;

pub mod ui {
slint::include_modules!();
Expand All @@ -32,9 +33,10 @@ fn main() -> Result<(), PlatformError> {
transportation::setup(&main_window);

//we need to store the timers in variables to prevent them from being dropped
let _t = datetime::setup(&main_window);
#[cfg(feature = "selfie")] //grab screenshot of running app
let _s = selfie::grab_selfie(&main_window);
let _t = datetime::setup(&main_window);
let _f = seasons::setup_seasons(&main_window);

main_window.run()
}
69 changes: 69 additions & 0 deletions src/seasons/december.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use std::rc::Rc;
use rand::Rng;
use slint::{Timer, TimerMode, VecModel};
use crate::ui::*;

struct SnowflakeModel {
x: f32,
y: f32,
x_velocity: f32,
y_velocity: f32
}

impl From<&mut SnowflakeModel> for Snowflake {
fn from(val: &mut SnowflakeModel) -> Snowflake {
Snowflake{
x: val.x.into(),
y: val.y.into()
}
}
}


pub fn setup_snow(main_window: &MainWindow) -> Timer {

let snow_timer = Timer::default();
let mut rng = rand::thread_rng();

let snow_handle = main_window.as_weak();
let width = main_window.window().size().width;
let height = main_window.window().size().height;


let mut flurry = vec!();
for _ in 0..100 {
let snowflake = SnowflakeModel {
x: rng.gen_range(0.0..width as f32),
y: rng.gen_range(0.0..height as f32),
x_velocity: rng.gen_range(-1.0..1.0),
y_velocity: rng.gen_range(0.5..2.0)
};
flurry.push(snowflake);
}

snow_timer.start(TimerMode::Repeated, std::time::Duration::from_millis(10), move || {
let snowflakes : VecModel<Snowflake> = VecModel::default();
for flake in &mut flurry {
flake.x += flake.x_velocity;
flake.y += flake.y_velocity;

// bounce snowflake if out of bounds
if flake.x < -15.0 {
flake.x = -15.0;
flake.x_velocity = -flake.x_velocity;
} else if flake.x > width as f32 {
flake.x = width as f32;
flake.x_velocity = -flake.x_velocity;
}

// move flake to top when exiting bottom
if flake.y > height as f32 {
flake.y = 0.0;
}
snowflakes.push(flake.into());
}
snow_handle.unwrap().set_snowflakes(Rc::new(snowflakes).into());
});

snow_timer
}
105 changes: 105 additions & 0 deletions src/seasons/halloween.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use crate::{ui::*, StaticAssets};
use rand::Rng;
use slint::{Image, LogicalPosition, Rgba8Pixel, SharedPixelBuffer, Timer, TimerMode};

pub fn setup_halloween_spooky_face(main_window: &MainWindow) -> Timer {
let halloween_timer = Timer::default();
let halloween_handle = main_window.as_weak();

let width = main_window.window().size().width;
let height = main_window.window().size().height;
let mut rng = rand::thread_rng();

halloween_timer.start(
TimerMode::Repeated,
std::time::Duration::from_secs(10),
move || {
let mut current_spooky = halloween_handle.unwrap().get_spooky_face();
if current_spooky.hidden {
let face_width = rng.gen_range(100..500);
let x_pos = rng.gen_range(0..width - (face_width + 20));
let y_pos = rng.gen_range(0..height - (face_width + 20));
let spooky_face = SpookyFace {
pos: LogicalPosition {
x: x_pos as f32,
y: y_pos as f32,
},
size: face_width as f32,
hidden: false,
};
halloween_handle.unwrap().set_spooky_face(spooky_face);
} else {
current_spooky.hidden = true;
halloween_handle.unwrap().set_spooky_face(current_spooky);
}
},
);

halloween_timer
}

pub fn setup_halloween_bat(main_window: &MainWindow) -> Timer {
let width = main_window.window().size().width;
let height = main_window.window().size().height;

let timer = Timer::default();
let mut rng = rand::thread_rng();
let frames = read_bat_frames();
let handle = main_window.as_weak();
let mut frame_number = 0;
let mut current_pos = LogicalPosition { x: 0.0, y: 0.0 };

timer.start(
TimerMode::Repeated,
std::time::Duration::from_millis(100),
move || {
let frame = &frames.clone()[frame_number % 9];
let bat = Bat {
frame: frame.clone(),
pos: current_pos,
size: 200 as f32,
};

if frame_number % 200 == 0 {
current_pos = LogicalPosition {
x: rng.gen_range(0.0..width as f32),
y: rng.gen_range(0.0..height as f32),
};
}

frame_number += 1;

handle.unwrap().set_bat(bat)
},
);

timer
}

fn read_bat_frames() -> Vec<Image> {
let mut frames = vec![];

for i in 0..9 {
let bat_frame_path = std::format!("seasons/halloween/bat-{}.png", i);
let frame_data = match StaticAssets::get(&bat_frame_path) {
Some(icon_data) => icon_data.data.into_owned(),
None => StaticAssets::get("not-found.png")
.unwrap()
.data
.into_owned(),
};

let bat_frame = image::load_from_memory_with_format(&frame_data, image::ImageFormat::Png)
.unwrap()
.into_rgba8();

let buffer = SharedPixelBuffer::<Rgba8Pixel>::clone_from_slice(
bat_frame.as_raw(),
bat_frame.width(),
bat_frame.height(),
);

frames.push(Image::from_rgba8(buffer))
}
frames
}
34 changes: 34 additions & 0 deletions src/seasons/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
This module adds seasonal fluff:
Halloween bats and sppoky face in late october
Snow effect in December
....more? :D
*/

use crate::ui::*;
use chrono::{Datelike, Local};
use slint::Timer;
mod december;
mod halloween;
use december::setup_snow;
use halloween::{setup_halloween_bat, setup_halloween_spooky_face};

pub fn setup_seasons(main_window: &MainWindow) -> Vec<Timer> {
let mut season_timers = vec![];

if Local::now().month() == 12 {
let snow_timer = setup_snow(main_window);
season_timers.push(snow_timer);
}

let now = Local::now();
if now.month() == 10 && now.day() >= 10 && now.day() <= 31 {
let face_timer = setup_halloween_spooky_face(main_window);
let bat_timer = setup_halloween_bat(main_window);

season_timers.push(face_timer);
season_timers.push(bat_timer);
}

season_timers
}
Loading

0 comments on commit 29fe166

Please sign in to comment.