black screen dead once and for all. now its just loss of input for a bit on first load
This commit is contained in:
parent
4c87d13eb8
commit
2e3c44b421
7 changed files with 107 additions and 115 deletions
19
Cargo.lock
generated
19
Cargo.lock
generated
|
@ -816,12 +816,6 @@ dependencies = [
|
|||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "file-format"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7ef3d5e8ae27277c8285ac43ed153158178ef0f79567f32024ca8140a0c7cd8"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.1"
|
||||
|
@ -1627,13 +1621,11 @@ dependencies = [
|
|||
"glib",
|
||||
"gstreamer",
|
||||
"gstreamer-app",
|
||||
"gstreamer-base",
|
||||
"iced",
|
||||
"iced_wgpu",
|
||||
"log",
|
||||
"thiserror 2.0.12",
|
||||
"url",
|
||||
"yuvutils-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3102,7 +3094,6 @@ name = "reversed-rooms-launcher"
|
|||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"directories",
|
||||
"file-format",
|
||||
"iced",
|
||||
"iced_video_player",
|
||||
"image",
|
||||
|
@ -3111,7 +3102,6 @@ dependencies = [
|
|||
"serde_json",
|
||||
"strum 0.27.1",
|
||||
"strum_macros 0.27.1",
|
||||
"tempfile",
|
||||
"url",
|
||||
]
|
||||
|
||||
|
@ -5051,15 +5041,6 @@ dependencies = [
|
|||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yuvutils-rs"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b699b6503cd14c70b258eaffedd7ada5a781ea23206eeb9066736b99ba37af1"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeno"
|
||||
version = "0.3.2"
|
||||
|
|
|
@ -10,10 +10,8 @@ iced = { git = "https://github.com/RabbyDevs/iced.git", features = ["tokio", "wg
|
|||
image = "0.25.6"
|
||||
serde = { version = "1.0.219", features = ["serde_derive"] }
|
||||
serde_json = "1.0.140"
|
||||
tempfile = "3.19.1"
|
||||
iced_video_player = {path = "./iced_video_player"}
|
||||
url = "2.5.4"
|
||||
file-format = "0.26.0"
|
||||
strum = "0.27.1"
|
||||
strum_macros = "0.27.1"
|
||||
reqwest = { version = "0.12.15", features = [
|
||||
|
|
|
@ -20,12 +20,12 @@ iced = { git = "https://github.com/RabbyDevs/iced.git", features = ["wgpu", "ima
|
|||
iced_wgpu = { git = "https://github.com/RabbyDevs/iced.git" }
|
||||
gstreamer = "0.23.5"
|
||||
gstreamer-app = "0.23.5" # appsink
|
||||
gstreamer-base = "0.23.5" # basesrc
|
||||
# gstreamer-base = "0.23.5" # basesrc
|
||||
glib = "0.20.9" # gobject traits and error type
|
||||
log = "0.4.27"
|
||||
thiserror = "2.0.12"
|
||||
url = "2.5.4" # media uri
|
||||
yuvutils-rs = "0.8.2"
|
||||
# yuvutils-rs = "0.8.2"
|
||||
|
||||
[package.metadata.nix]
|
||||
systems = ["x86_64-linux"]
|
||||
|
|
|
@ -336,7 +336,7 @@ impl Video {
|
|||
|
||||
frame,
|
||||
upload_frame,
|
||||
looping: false,
|
||||
looping: true,
|
||||
is_eos: false,
|
||||
restart_stream: false,
|
||||
})))
|
||||
|
|
|
@ -156,6 +156,7 @@ async fn refresh_kuro_install(proj_dirs: &ProjectDirs, client: &Client) -> Resul
|
|||
|
||||
update_file_if_needed(data_dir, client, &bg_information.background_file, "background").await?;
|
||||
update_file_if_needed(data_dir, client, &bg_information.slogan, "splash").await?;
|
||||
update_file_if_needed(data_dir, client, &bg_information.first_frame_image, "first_frame_image").await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
66
src/main.rs
66
src/main.rs
|
@ -96,9 +96,15 @@ enum Launcher {
|
|||
Loaded(Box<State>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct VideoBackground {
|
||||
video: Option<Video>,
|
||||
first_frame: DynamicImage
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum LauncherBackground {
|
||||
Video(Video),
|
||||
Video(VideoBackground),
|
||||
Image(DynamicImage),
|
||||
}
|
||||
|
||||
|
@ -117,8 +123,14 @@ impl State {
|
|||
fn get_background_element(&self) -> Option<Element<Message>> {
|
||||
if let Some(background) = &self.background {
|
||||
match background {
|
||||
LauncherBackground::Video(video) => Some(VideoPlayer::new(video).into()),
|
||||
LauncherBackground::Image(img) => Some(image(image::Handle::from_rgba(img.width(), img.height(), img.to_rgba8().into_raw())).into()),
|
||||
LauncherBackground::Video(video_object) => {
|
||||
if let Some(video) = &video_object.video {
|
||||
Some(VideoPlayer::new(video).into())
|
||||
} else {
|
||||
Some(image(video_object.first_frame.clone().into_handle()).into())
|
||||
}
|
||||
},
|
||||
LauncherBackground::Image(img) => Some(image(img.clone().into_handle()).into()),
|
||||
}
|
||||
} else {
|
||||
None
|
||||
|
@ -252,6 +264,7 @@ enum Message {
|
|||
LoadIcons(HashMap<PossibleGames, DynamicImage>),
|
||||
LoadSplashes(HashMap<PossibleGames, DynamicImage>),
|
||||
LoadBackground(()),
|
||||
LoadVideo(()),
|
||||
RefreshInstall(Result<(), String>),
|
||||
GameSelected(PossibleGames),
|
||||
Close,
|
||||
|
@ -328,12 +341,33 @@ impl Launcher {
|
|||
Task::none()
|
||||
},
|
||||
Message::LoadBackground(()) => {
|
||||
state.background = Some(get_game_background(&state.selected_game));
|
||||
|
||||
let (width, height) = state.selected_game.get_game_preferred_size();
|
||||
window::get_latest().and_then(move |id: window::Id| {
|
||||
let task = window::get_latest().and_then(move |id: window::Id| {
|
||||
window::resize(id, Size { width: width as f32, height: height as f32 })
|
||||
})
|
||||
});
|
||||
|
||||
if let Ok(background) = get_game_background(&state.selected_game, false) {
|
||||
if let LauncherBackground::Video(_) = background {
|
||||
state.background = Some(background);
|
||||
return task.chain(Task::perform(empty(), Message::LoadVideo));
|
||||
}
|
||||
state.background = Some(background);
|
||||
|
||||
} else {
|
||||
state.background = None
|
||||
}
|
||||
|
||||
task
|
||||
},
|
||||
Message::LoadVideo(()) => {
|
||||
if let Ok(background) = get_game_background(&state.selected_game, true) {
|
||||
state.background = Some(background);
|
||||
|
||||
} else {
|
||||
state.background = None
|
||||
}
|
||||
|
||||
Task::none()
|
||||
},
|
||||
Message::LoadIcons(icons) => {
|
||||
state.icon_images = icons;
|
||||
|
@ -344,12 +378,22 @@ impl Launcher {
|
|||
},
|
||||
Message::GameSelected(game) => {
|
||||
state.selected_game = game;
|
||||
state.background = Some(get_game_background(&state.selected_game));
|
||||
|
||||
let (width, height) = state.selected_game.get_game_preferred_size();
|
||||
window::get_latest().and_then(move |id: window::Id| {
|
||||
let task = window::get_latest().and_then(move |id: window::Id| {
|
||||
window::resize(id, Size { width: width as f32, height: height as f32 })
|
||||
})
|
||||
});
|
||||
|
||||
if let Ok(background) = get_game_background(&state.selected_game, false) {
|
||||
if let LauncherBackground::Video(_) = background {
|
||||
state.background = Some(background);
|
||||
return task.chain(Task::perform(empty(), Message::LoadVideo));
|
||||
}
|
||||
state.background = Some(background)
|
||||
} else {
|
||||
state.background = None
|
||||
}
|
||||
|
||||
task
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,47 +1,60 @@
|
|||
use std::{fs::DirEntry, io::{Cursor, Write}, sync::Arc};
|
||||
use std::{io::Cursor, path::PathBuf};
|
||||
|
||||
use directories::ProjectDirs;
|
||||
use file_format::FileFormat;
|
||||
use iced_video_player::Video;
|
||||
use ::image::{DynamicImage, ImageReader};
|
||||
use iced::{gradient, widget::container, Color};
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
use crate::{LauncherBackground, PossibleGames};
|
||||
use crate::{LauncherBackground, PossibleGames, VideoBackground};
|
||||
|
||||
use super::img_utils::round_image;
|
||||
|
||||
pub fn get_game_background(game: &PossibleGames) -> LauncherBackground {
|
||||
pub fn get_game_background(game: &PossibleGames, make_video: bool) -> Result<LauncherBackground, std::io::Error> {
|
||||
let proj_dirs = ProjectDirs::from("com", "RabbyDevs", "rr-launcher").unwrap();
|
||||
let background_bytes = get_background_file(&proj_dirs, game).unwrap();
|
||||
let data = Arc::new(background_bytes);
|
||||
let file_format = FileFormat::from_bytes(&*data);
|
||||
let background_path = get_asset_file(&proj_dirs, game, "background")?;
|
||||
|
||||
if file_format.extension() == "mp4" {
|
||||
let mut temp_file = NamedTempFile::new().unwrap();
|
||||
temp_file.write_all(&data).unwrap();
|
||||
|
||||
let temp_path = temp_file.path().to_str().unwrap().to_string();
|
||||
match Video::new(&url::Url::from_file_path(temp_path).unwrap()) {
|
||||
Ok(mut video) => {
|
||||
video.set_looping(true);
|
||||
LauncherBackground::Video(video)
|
||||
},
|
||||
Err(err) => {
|
||||
panic!("{:#?}", err)
|
||||
},
|
||||
}
|
||||
} else {
|
||||
let img = ImageReader::new(Cursor::new(&*data))
|
||||
if background_path.extension().unwrap().to_str().unwrap() == "mp4" {
|
||||
let first_frame_path = get_asset_file(&proj_dirs, game, "first_frame_image")?;
|
||||
let first_frame = ImageReader::new(Cursor::new(std::fs::read(first_frame_path)?))
|
||||
.with_guessed_format()
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
LauncherBackground::Image(img)
|
||||
|
||||
if !make_video {
|
||||
return Ok(LauncherBackground::Video(VideoBackground {
|
||||
first_frame,
|
||||
video: None
|
||||
}));
|
||||
}
|
||||
match Video::new(&url::Url::from_file_path(background_path).unwrap()) {
|
||||
Ok(video) => {
|
||||
let video_object = VideoBackground {
|
||||
first_frame,
|
||||
video: Some(video)
|
||||
};
|
||||
|
||||
Ok(LauncherBackground::Video(video_object))
|
||||
},
|
||||
Err(err) => {
|
||||
eprintln!("{:#?}", err);
|
||||
Ok(LauncherBackground::Video(VideoBackground {
|
||||
first_frame,
|
||||
video: None
|
||||
}))
|
||||
},
|
||||
}
|
||||
} else {
|
||||
let img = ImageReader::new(Cursor::new(std::fs::read(background_path)?))
|
||||
.with_guessed_format()
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
Ok(LauncherBackground::Image(img))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_background_file(proj_dirs: &ProjectDirs, game: &PossibleGames) -> Result<Vec<u8>, std::io::Error> {
|
||||
fn get_asset_file(proj_dirs: &ProjectDirs, game: &PossibleGames, identifier: &str) -> Result<PathBuf, std::io::Error> {
|
||||
let game_dir = match game {
|
||||
PossibleGames::WutheringWaves => proj_dirs.data_dir().join("kuro/wuwa"),
|
||||
PossibleGames::ZenlessZoneZero => proj_dirs.data_dir().join("hoyoverse/zzz"),
|
||||
|
@ -62,8 +75,8 @@ fn get_background_file(proj_dirs: &ProjectDirs, game: &PossibleGames) -> Result<
|
|||
let entry = entry?;
|
||||
let file_name = entry.file_name().into_string().unwrap_or_default();
|
||||
|
||||
if file_name.starts_with("background_") {
|
||||
return std::fs::read(entry.path());
|
||||
if file_name.starts_with(format!("{}_", identifier).as_str()) {
|
||||
return Ok(entry.path());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,9 +88,10 @@ fn get_background_file(proj_dirs: &ProjectDirs, game: &PossibleGames) -> Result<
|
|||
|
||||
pub fn get_game_splash_dynamic_image(game: &PossibleGames) -> Option<DynamicImage> {
|
||||
let proj_dirs = ProjectDirs::from("com", "RabbyDevs", "rr-launcher").unwrap();
|
||||
let file_data = get_splash_file(&proj_dirs, game);
|
||||
if let Some(data) = file_data {
|
||||
let data_cursor = Cursor::new(data);
|
||||
let file_path = get_asset_file(&proj_dirs, game, "splash");
|
||||
|
||||
if let Ok(path) = file_path {
|
||||
let data_cursor = Cursor::new(std::fs::read(path).unwrap());
|
||||
|
||||
Some(ImageReader::new(data_cursor)
|
||||
.with_guessed_format()
|
||||
|
@ -91,9 +105,9 @@ pub fn get_game_icon_dynamic_image(game: &PossibleGames) -> DynamicImage {
|
|||
let proj_dirs = ProjectDirs::from("com", "RabbyDevs", "rr-launcher").unwrap();
|
||||
let file_data: &[u8] = match game {
|
||||
PossibleGames::WutheringWaves => include_bytes!("../../resources/wutheringwaves-icon.png"),
|
||||
PossibleGames::ZenlessZoneZero => &get_hoyo_game_icon_file(&proj_dirs, game),
|
||||
PossibleGames::HonkaiStarRail => &get_hoyo_game_icon_file(&proj_dirs, game),
|
||||
PossibleGames::GenshinImpact => &get_hoyo_game_icon_file(&proj_dirs, game),
|
||||
PossibleGames::ZenlessZoneZero => &std::fs::read(get_asset_file(&proj_dirs, game, "icon").unwrap()).unwrap(),
|
||||
PossibleGames::HonkaiStarRail => &std::fs::read(get_asset_file(&proj_dirs, game, "icon").unwrap()).unwrap(),
|
||||
PossibleGames::GenshinImpact => &std::fs::read(get_asset_file(&proj_dirs, game, "icon").unwrap()).unwrap(),
|
||||
};
|
||||
|
||||
let data_cursor = Cursor::new(file_data);
|
||||
|
@ -109,52 +123,6 @@ pub fn get_game_icon_dynamic_image(game: &PossibleGames) -> DynamicImage {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
fn get_hoyo_game_icon_file(proj_dirs: &ProjectDirs, game: &PossibleGames) -> Vec<u8> {
|
||||
let game_abbrevation = match game {
|
||||
PossibleGames::ZenlessZoneZero => "zzz",
|
||||
PossibleGames::HonkaiStarRail => "hsr",
|
||||
PossibleGames::GenshinImpact => "gi",
|
||||
_ => panic!("Wuwa inputted in hoyo only func")
|
||||
};
|
||||
|
||||
let data_dir = proj_dirs.data_dir().join(format!("hoyoverse/{}", game_abbrevation));
|
||||
let icon: Option<DirEntry> = {
|
||||
let mut icon = None;
|
||||
for path in data_dir.read_dir().unwrap() {
|
||||
let path = path.unwrap();
|
||||
if path.file_name().into_string().unwrap().starts_with("icon_") {
|
||||
icon = Some(path);
|
||||
}
|
||||
}
|
||||
icon
|
||||
};
|
||||
|
||||
std::fs::read(icon.expect("installation went wrong.").path()).unwrap()
|
||||
}
|
||||
|
||||
fn get_splash_file(proj_dirs: &ProjectDirs, game: &PossibleGames) -> Option<Vec<u8>> {
|
||||
let game_path = match game {
|
||||
PossibleGames::ZenlessZoneZero => "hoyoverse/zzz",
|
||||
PossibleGames::HonkaiStarRail => "hoyoverse/hsr",
|
||||
PossibleGames::GenshinImpact => "hoyoverse/gi",
|
||||
PossibleGames::WutheringWaves => "kuro/wuwa"
|
||||
};
|
||||
|
||||
let data_dir = proj_dirs.data_dir().join(game_path);
|
||||
let icon: Option<DirEntry> = {
|
||||
let mut icon = None;
|
||||
for path in data_dir.read_dir().unwrap() {
|
||||
let path = path.unwrap();
|
||||
if path.file_name().into_string().unwrap().starts_with("splash_") {
|
||||
icon = Some(path);
|
||||
}
|
||||
}
|
||||
icon
|
||||
};
|
||||
|
||||
icon.map(|icon| std::fs::read(icon.path()).unwrap())
|
||||
}
|
||||
|
||||
fn rad(deg: f32) -> f32 {
|
||||
deg * std::f32::consts::PI / 180.0
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue