0.2.0: redesign ui to match yuhko concepts and change iced repo... also delete nix

This commit is contained in:
RabbyDevs 2025-05-01 23:20:46 +03:00
parent da4cfc0a48
commit 4d6f9c0d80
13 changed files with 142 additions and 248 deletions

36
Cargo.lock generated
View file

@ -717,7 +717,6 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
[[package]] [[package]]
name = "dpi" name = "dpi"
version = "0.1.1" version = "0.1.1"
source = "git+https://github.com/iced-rs/winit.git?rev=11414b6aa45699f038114e61b4ddf5102b2d3b4b#11414b6aa45699f038114e61b4ddf5102b2d3b4b"
[[package]] [[package]]
name = "drm" name = "drm"
@ -965,6 +964,7 @@ dependencies = [
"futures-core", "futures-core",
"futures-task", "futures-task",
"futures-util", "futures-util",
"num_cpus",
] ]
[[package]] [[package]]
@ -1357,6 +1357,12 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.4.0" version = "0.4.0"
@ -1372,7 +1378,6 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
[[package]] [[package]]
name = "iced" name = "iced"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"iced_core", "iced_core",
"iced_debug", "iced_debug",
@ -1389,7 +1394,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_beacon" name = "iced_beacon"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"bincode", "bincode",
"futures", "futures",
@ -1404,7 +1408,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_core" name = "iced_core"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"bitflags 2.9.0", "bitflags 2.9.0",
"bytes", "bytes",
@ -1422,7 +1425,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_debug" name = "iced_debug"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"iced_beacon", "iced_beacon",
"iced_core", "iced_core",
@ -1432,7 +1434,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_devtools" name = "iced_devtools"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"iced_debug", "iced_debug",
"iced_program", "iced_program",
@ -1442,13 +1443,11 @@ dependencies = [
[[package]] [[package]]
name = "iced_futures" name = "iced_futures"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"futures", "futures",
"iced_core", "iced_core",
"log", "log",
"rustc-hash 2.1.1", "rustc-hash 2.1.1",
"tokio",
"wasm-bindgen-futures", "wasm-bindgen-futures",
"wasmtimer", "wasmtimer",
] ]
@ -1456,7 +1455,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_graphics" name = "iced_graphics"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"bitflags 2.9.0", "bitflags 2.9.0",
"bytemuck", "bytemuck",
@ -1476,7 +1474,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_program" name = "iced_program"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"iced_graphics", "iced_graphics",
"iced_runtime", "iced_runtime",
@ -1485,7 +1482,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_renderer" name = "iced_renderer"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"iced_graphics", "iced_graphics",
"iced_tiny_skia", "iced_tiny_skia",
@ -1497,7 +1493,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_runtime" name = "iced_runtime"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"bytes", "bytes",
"iced_core", "iced_core",
@ -1510,7 +1505,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_tiny_skia" name = "iced_tiny_skia"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"cosmic-text", "cosmic-text",
@ -1542,7 +1536,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_wgpu" name = "iced_wgpu"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"bitflags 2.9.0", "bitflags 2.9.0",
"bytemuck", "bytemuck",
@ -1561,7 +1554,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_widget" name = "iced_widget"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"iced_renderer", "iced_renderer",
"iced_runtime", "iced_runtime",
@ -1575,7 +1567,6 @@ dependencies = [
[[package]] [[package]]
name = "iced_winit" name = "iced_winit"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/iced-rs/iced.git?rev=388a419#388a419ed5c229aadbca57bb09b474b1475b1ef9"
dependencies = [ dependencies = [
"iced_debug", "iced_debug",
"iced_program", "iced_program",
@ -2236,6 +2227,16 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi 0.3.9",
"libc",
]
[[package]] [[package]]
name = "num_enum" name = "num_enum"
version = "0.7.3" version = "0.7.3"
@ -2620,7 +2621,7 @@ checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"concurrent-queue", "concurrent-queue",
"hermit-abi", "hermit-abi 0.4.0",
"pin-project-lite", "pin-project-lite",
"rustix 0.38.44", "rustix 0.38.44",
"tracing", "tracing",
@ -4417,7 +4418,6 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "winit" name = "winit"
version = "0.30.8" version = "0.30.8"
source = "git+https://github.com/iced-rs/winit.git?rev=11414b6aa45699f038114e61b4ddf5102b2d3b4b#11414b6aa45699f038114e61b4ddf5102b2d3b4b"
dependencies = [ dependencies = [
"ahash", "ahash",
"android-activity", "android-activity",

View file

@ -1,12 +1,12 @@
#![feature(let_chains)] #![feature(let_chains)]
[package] [package]
name = "reversed-rooms-launcher" name = "reversed-rooms-launcher"
version = "0.1.0" version = "0.2.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
directories = "6.0.0" directories = "6.0.0"
iced = { git = "https://github.com/iced-rs/iced.git", rev = "388a419", features = ["tokio", "tiny-skia", "wgpu", "image", "debug"], default-features = false } iced = { git = "https://github.com/rabbydevs/iced.git", rev = "388a419", features = ["tokio", "tiny-skia", "wgpu", "image", "debug"], default-features = false }
image = "0.25.6" image = "0.25.6"
serde = { version = "1.0.219", features = ["serde_derive"] } serde = { version = "1.0.219", features = ["serde_derive"] }
serde_json = "1.0.140" serde_json = "1.0.140"

1
iced Submodule

@ -0,0 +1 @@
Subproject commit 24ccb057b5b0750f2bcee7a4ef306260259ef94e

View file

@ -1 +0,0 @@
use flake || use nix shell.nix

View file

@ -16,8 +16,8 @@ exclude = [
] ]
[dependencies] [dependencies]
iced = { git = "https://github.com/iced-rs/iced.git", rev = "388a419", features = ["tokio", "wgpu", "image", "advanced"], default-features = false } iced = { path = "https://github.com/rabbydevs/iced.git", features = ["thread-pool", "wgpu", "image", "advanced"], default-features = false }
iced_wgpu = { git = "https://github.com/iced-rs/iced.git", rev = "388a419" } iced_wgpu = { path = "https://github.com/rabbydevs/iced.git/wgpu" }
gstreamer = "0.23.5" gstreamer = "0.23.5"
gstreamer-app = "0.23.5" # appsink gstreamer-app = "0.23.5" # appsink
gstreamer-base = "0.23.5" # basesrc gstreamer-base = "0.23.5" # basesrc

View file

@ -1,98 +0,0 @@
{
"nodes": {
"devshell": {
"locked": {
"lastModified": 1629275356,
"narHash": "sha256-R17M69EKXP6q8/mNHaK53ECwjFo1pdF+XaJC9Qq8zjg=",
"owner": "numtide",
"repo": "devshell",
"rev": "26f25a12265f030917358a9632cd600b51af1d97",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"flakeCompat": {
"flake": false,
"locked": {
"lastModified": 1627913399,
"narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"nixCargoIntegration": {
"inputs": {
"devshell": "devshell",
"nixpkgs": [
"nixpkgs"
],
"rustOverlay": "rustOverlay"
},
"locked": {
"lastModified": 1629871751,
"narHash": "sha256-QjnDg34ApcnjmXlNLnbHswT9OroCPY7Wip6r9Zkgkfo=",
"owner": "yusdacra",
"repo": "nix-cargo-integration",
"rev": "4f164ecad242537d5893426eef02c47c9e5ced59",
"type": "github"
},
"original": {
"owner": "yusdacra",
"repo": "nix-cargo-integration",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1629618782,
"narHash": "sha256-2K8SSXu3alo/URI3MClGdDSns6Gb4ZaW4LET53UWyKk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "870959c7fb3a42af1863bed9e1756086a74eb649",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flakeCompat": "flakeCompat",
"nixCargoIntegration": "nixCargoIntegration",
"nixpkgs": "nixpkgs"
}
},
"rustOverlay": {
"flake": false,
"locked": {
"lastModified": 1629857564,
"narHash": "sha256-dClWiHkbaCDaIl520Miri66UOA8OecWbaVTWJBajHyM=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "88848c36934318e16c86097f65dbf97a57968d81",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,28 +0,0 @@
{
inputs = {
flakeCompat = {
url = "github:edolstra/flake-compat";
flake = false;
};
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixCargoIntegration = {
url = "github:yusdacra/nix-cargo-integration";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = inputs:
inputs.nixCargoIntegration.lib.makeOutputs {
root = ./.;
overrides = {
shell = common: prev: {
env = prev.env ++ [
{
name = "GST_PLUGIN_PATH";
value = "${common.pkgs.gst_all_1.gstreamer}:${common.pkgs.gst_all_1.gst-plugins-bad}:${common.pkgs.gst_all_1.gst-plugins-ugly}:${common.pkgs.gst_all_1.gst-plugins-good}:${common.pkgs.gst_all_1.gst-plugins-base}";
}
];
};
};
};
}

View file

@ -1,12 +0,0 @@
# Flake's devShell for non-flake-enabled nix instances
(import
(
let lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball {
url =
"https://github.com/edolstra/flake-compat/archive/${lock.nodes.flakeCompat.locked.rev}.tar.gz";
sha256 = lock.nodes.flakeCompat.locked.narHash;
}
)
{ src = ./.; }).shellNix.default

Binary file not shown.

View file

@ -4,17 +4,27 @@ mod utils;
use file_format::FileFormat; use file_format::FileFormat;
use ::image::{DynamicImage, ImageReader}; use ::image::{DynamicImage, ImageReader};
use iced::{ use iced::{
alignment::Vertical::{Bottom, Top}, border, font::{self, Family, Stretch, Weight}, gradient, mouse::{self, Interaction}, wgpu::naga::back, widget::{button, center, column, container, image, mouse_area, opaque, row, stack, text, Column, Space}, window::{self, icon, Settings}, Alignment::Center, Color, Element, Font, Length, Point, Renderer, Size, Subscription, Task, Theme alignment::Vertical::{Bottom, Top}, border, font::{self, Family, Stretch, Weight}, gradient, mouse::{self, Interaction}, wgpu::naga::back, widget::{button, center, column, container, image, mouse_area, opaque, row, stack, text, Column, Space}, window::{self, icon, Settings}, Alignment::Center, Color, Element, Font, Length::{self, Fill}, Point, Renderer, Size, Subscription, Task, Theme
}; };
use iced_video_player::{Video, VideoPlayer}; use iced_video_player::{Video, VideoPlayer};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use strum_macros::EnumIter; use strum_macros::EnumIter;
use utils::{img_utils::round_image, visual_helper::{get_game_background, get_game_icon, get_game_icon_handle}}; use utils::{img_utils::round_image, visual_helper::{get_game_background, get_game_icon_dynamic_image, style_container}};
use std::{ use std::{
collections::HashMap, env, fs::{self, create_dir_all, read_to_string}, io::{Cursor, Read, Write}, path::PathBuf, sync::Arc collections::HashMap, env, fs::{self, create_dir_all, read_to_string}, io::{Cursor, Read, Write}, path::PathBuf, sync::Arc
}; };
trait InterfaceImage {
fn into_handle(&self) -> image::Handle;
}
impl InterfaceImage for DynamicImage {
fn into_handle(&self) -> image::Handle {
image::Handle::from_rgba(self.width(), self.height(), self.to_rgba8().into_raw())
}
}
#[derive(rust_embed::Embed)] #[derive(rust_embed::Embed)]
#[folder = "resources"] #[folder = "resources"]
struct Assets; struct Assets;
@ -61,8 +71,8 @@ pub fn main() -> iced::Result {
enum PossibleGames { enum PossibleGames {
#[default] #[default]
WutheringWaves, WutheringWaves,
ZenlessZoneZero,
HonkaiStarRail, HonkaiStarRail,
ZenlessZoneZero,
GenshinImpact, GenshinImpact,
} }
@ -75,7 +85,7 @@ enum Launcher {
#[derive(Debug)] #[derive(Debug)]
enum LauncherBackground { enum LauncherBackground {
Video(Video), Video(Video),
Image(image::Handle), Image(DynamicImage),
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -85,7 +95,46 @@ struct State {
installed_game_servers: Vec<PossibleGames>, installed_game_servers: Vec<PossibleGames>,
db_software_installed: bool, db_software_installed: bool,
background: Option<LauncherBackground>, background: Option<LauncherBackground>,
icon_images: HashMap<PossibleGames, image::Handle> icon_images: HashMap<PossibleGames, DynamicImage>
}
impl State {
fn get_background_element(&self) -> Element<Message> {
match self.background.as_ref().unwrap() {
LauncherBackground::Video(video) => VideoPlayer::new(video).into(),
LauncherBackground::Image(img) => image(image::Handle::from_rgba(img.width(), img.height(), img.to_rgba8().into_raw())).into(),
}
}
fn get_game_icon_row(&self) -> Element<Message> {
container(row![
self.create_game_icon(&PossibleGames::WutheringWaves),
self.create_game_icon(&PossibleGames::HonkaiStarRail),
self.create_game_icon(&PossibleGames::ZenlessZoneZero),
self.create_game_icon(&PossibleGames::GenshinImpact),
]
.spacing(10)
).align_x(Center).width(Length::Fill).into()
}
fn create_game_icon(&self, game: &PossibleGames) -> Element<Message> {
let icon = self.icon_images.get(game).unwrap();
let img = if &self.selected_game == game {
image(icon.into_handle())
.width(Length::Fixed(52.0))
.height(Length::Fixed(68.0))
} else {
image(icon.brighten(-85).blur(2.5).adjust_contrast(-15.0).into_handle())
.width(Length::Fixed(48.0))
.height(Length::Fixed(64.0))
};
mouse_area(
img
)
.on_press(Message::GameSelected(game.clone()))
.interaction(Interaction::Pointer)
.into()
}
} }
#[derive(Debug, Default, Clone, Serialize, Deserialize)] #[derive(Debug, Default, Clone, Serialize, Deserialize)]
@ -168,29 +217,12 @@ impl State {
// } // }
} }
fn rad(deg: f32) -> f32 {
deg * std::f32::consts::PI / 180.0
}
fn style_container(direction: f32, use_gradient: bool) -> container::Style {
let angle = rad(direction);
let gradient: Option<iced::Background> = if use_gradient {
Some(gradient::Linear::new(angle)
.add_stop(0.0, Color::from_rgba8(0, 0, 0, 0.0))
.add_stop(0.75, Color::from_rgba8(0, 0, 0, 0.75)).into())
} else {None};
container::Style {
text_color: Color::from_rgba8(255, 255, 255, 1.0).into(),
background: gradient,
..container::Style::default()
}
}
impl Launcher { impl Launcher {
fn boot() -> (Self, Task<Message>) { fn boot() -> (Self, Task<Message>) {
let launcher_bg = get_game_background(&State::default()); let launcher_bg = get_game_background(&State::default());
let mut icons = HashMap::new(); let mut icons = HashMap::new();
for game in PossibleGames::iter() { for game in PossibleGames::iter() {
let icon = get_game_icon_handle(&game); let icon = get_game_icon_dynamic_image(&game);
icons.insert(game, icon); icons.insert(game, icon);
} }
let final_state = State { let final_state = State {
@ -220,7 +252,7 @@ impl Launcher {
window::get_latest().and_then(move |id: window::Id| { window::get_latest().and_then(move |id: window::Id| {
window::drag(id) window::drag(id)
}) })
}, }
Message::Close => { Message::Close => {
window::get_latest().and_then(move |id: window::Id| { window::get_latest().and_then(move |id: window::Id| {
window::close(id) window::close(id)
@ -245,35 +277,34 @@ impl Launcher {
match self { match self {
Launcher::Loading => center(text("Loading...").size(50)).into(), Launcher::Loading => center(text("Loading...").size(50)).into(),
Launcher::Loaded(state) => { Launcher::Loaded(state) => {
let game_selector = mouse_area(container( let top_bar = stack![
row![ mouse_area(container(
get_game_icon(state, &PossibleGames::WutheringWaves), stack![
get_game_icon(state, &PossibleGames::ZenlessZoneZero), row![
get_game_icon(state, &PossibleGames::HonkaiStarRail), text("Reversed Rooms").size(35).font(font).color(Color::from_rgb8(255, 255, 255)),
get_game_icon(state, &PossibleGames::GenshinImpact), Space::new(Length::Fill, Length::Fixed(0.0)),
] row![
.spacing(10), opaque(mouse_area(text("\u{E949}").font(Font::with_name("Segoe MDL2 Assets")).size(25)).on_release(Message::Minimize).interaction(Interaction::Pointer)),
) opaque(mouse_area(text("\u{E106}").font(Font::with_name("Segoe MDL2 Assets")).size(25)).on_release(Message::Close).interaction(Interaction::Pointer))
.padding(10) ].spacing(20)
.align_y(Top) ].align_y(Center).padding(4),
.align_x(Center) state.get_game_icon_row(),
.width(Length::Fill)
.style(move |_| style_container(0.0, true)))
.on_press(Message::DragStarted())
.interaction(Interaction::Grab);
let topbar = container( ]
row![ )
text("Reversed Rooms").size(25).font(font), .padding(5)
Space::new(Length::Fill, Length::Fixed(0.0)), .align_y(Top)
row![ .align_x(Center)
opaque(mouse_area(text("\u{E949}").font(Font::with_name("Segoe MDL2 Assets")).size(25)).on_release(Message::Minimize).interaction(Interaction::Pointer)), .width(Length::Fill)
opaque(mouse_area(text("\u{E106}").font(Font::with_name("Segoe MDL2 Assets")).size(25)).on_release(Message::Close).interaction(Interaction::Pointer)) .style(move |_|
].spacing(20) container::Style {
]) text_color: Color::from_rgba8(255, 255, 255, 1.0).into(),
.width(Length::Fill) background: Some(Color::from_rgba8(0, 0, 0, 0.75).into()),
.style(move |_| style_container(0.0, false)) ..container::Style::default()
.padding(20); }))
.on_press(Message::DragStarted())
.interaction(Interaction::Grab)
];
let bottom_bar = container(row![ let bottom_bar = container(row![
text("The quick brown fox jumped over the lazy dog.").size(25).font(font).align_y(Bottom), text("The quick brown fox jumped over the lazy dog.").size(25).font(font).align_y(Bottom),
@ -294,17 +325,13 @@ impl Launcher {
.style(move |_theme| style_container(180.0, true)) .style(move |_theme| style_container(180.0, true))
.padding(20); .padding(20);
let user_area = column![topbar, Space::new(Length::Fill, Length::Fill), bottom_bar] let user_area = column![top_bar, Space::new(Length::Fill, Length::Fill), bottom_bar]
.width(Length::Fill) .width(Length::Fill)
.height(Length::Fill); .height(Length::Fill);
let background = state.background.as_ref().unwrap(); let bg_element: Element<Message> = state.get_background_element();
let bg_element: Element<Message> = match background {
LauncherBackground::Video(video) => VideoPlayer::new(video).into(),
LauncherBackground::Image(handle) => image(handle.clone()).into(),
};
stack![bg_element, game_selector, user_area].into() stack![bg_element, user_area].into()
} }
} }
} }

View file

@ -33,18 +33,12 @@ pub fn is_in_rounded_rect(x: u32, y: u32, width: u32, height: u32, radius: f32)
x >= 0.0 && x < width && y >= 0.0 && y < height x >= 0.0 && x < width && y >= 0.0 && y < height
} }
pub fn round_image(img_data: Cursor<std::borrow::Cow<'static, [u8]>>) -> Result<DynamicImage, Box<dyn std::error::Error>> { pub fn round_image(img: DynamicImage) -> Result<DynamicImage, Box<dyn std::error::Error>> {
let img = ImageReader::new(img_data)
.with_guessed_format()
.unwrap()
.decode()
.unwrap();
let (width, height) = img.dimensions(); let (width, height) = img.dimensions();
let mut rounded_img = ImageBuffer::new(width, height); let mut rounded_img = ImageBuffer::new(width, height);
let radius = 50.0; let radius = 10.0;
for (x, y, pixel) in img.pixels() { for (x, y, pixel) in img.pixels() {
if is_in_rounded_rect(x, y, width, height, radius) { if is_in_rounded_rect(x, y, width, height, radius) {

View file

@ -2,11 +2,11 @@ use std::{io::{Cursor, Write}, sync::Arc};
use file_format::FileFormat; use file_format::FileFormat;
use iced_video_player::Video; use iced_video_player::Video;
use ::image::ImageReader; use ::image::{DynamicImage, ImageReader};
use iced::{widget::{container, image}, Element, Length}; use iced::{gradient, widget::{container, image}, Color};
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
use crate::{Assets, LauncherBackground, Message, PossibleGames, State}; use crate::{Assets, LauncherBackground, PossibleGames, State};
use super::img_utils::round_image; use super::img_utils::round_image;
@ -41,11 +41,7 @@ pub fn get_game_background(state: &State) -> LauncherBackground {
.unwrap() .unwrap()
.decode() .decode()
.unwrap(); .unwrap();
LauncherBackground::Image(image::Handle::from_rgba( LauncherBackground::Image(img)
img.width(),
img.height(),
img.to_rgba8().into_raw()
))
} }
} else { } else {
@ -53,7 +49,7 @@ pub fn get_game_background(state: &State) -> LauncherBackground {
} }
} }
pub fn get_game_icon_handle(game: &PossibleGames) -> image::Handle { pub fn get_game_icon_dynamic_image(game: &PossibleGames) -> DynamicImage {
let file_path: &str = match game { let file_path: &str = match game {
PossibleGames::WutheringWaves => "wutheringwaves-icon.png", PossibleGames::WutheringWaves => "wutheringwaves-icon.png",
PossibleGames::ZenlessZoneZero => "zenlesszonezero-icon.png", PossibleGames::ZenlessZoneZero => "zenlesszonezero-icon.png",
@ -62,21 +58,35 @@ pub fn get_game_icon_handle(game: &PossibleGames) -> image::Handle {
}; };
if let Some(img_file) = Assets::get(file_path) { if let Some(img_file) = Assets::get(file_path) {
let data_cursor = Cursor::new(img_file.data); let data_cursor = Cursor::new(img_file.data);
let img = round_image(data_cursor)
.unwrap()
.resize(126, 126, ::image::imageops::FilterType::Lanczos3);
image::Handle::from_rgba( let img = ImageReader::new(data_cursor)
img.width(), .with_guessed_format()
img.height(), .unwrap()
img.to_rgba8().into_raw() .decode()
) .unwrap()
.resize(128, 128, ::image::imageops::FilterType::Lanczos3);
round_image(img)
.unwrap()
} else { } else {
panic!("Missing icon for {:?}, path: {}", game, file_path) panic!("Missing icon for {:?}, path: {}", game, file_path)
} }
} }
pub fn get_game_icon<'a>(state: &'a State, game: &'a PossibleGames) -> Element<'a, Message> { fn rad(deg: f32) -> f32 {
let handle = state.icon_images.get(game).unwrap(); deg * std::f32::consts::PI / 180.0
container(image(handle).content_fit(iced::ContentFit::Contain).height(Length::Fixed(64.0)).filter_method(image::FilterMethod::Linear)).into() }
pub fn style_container(direction: f32, use_gradient: bool) -> container::Style {
let angle = rad(direction);
let gradient: Option<iced::Background> = if use_gradient {
Some(gradient::Linear::new(angle)
.add_stop(0.0, Color::from_rgba8(0, 0, 0, 0.0))
.add_stop(0.75, Color::from_rgba8(0, 0, 0, 0.75)).into())
} else {None};
container::Style {
text_color: Color::from_rgba8(255, 255, 255, 1.0).into(),
background: gradient,
..container::Style::default()
}
} }

1
winit Submodule

@ -0,0 +1 @@
Subproject commit 61e07f0aa59f988dba5960e47011466d5aaa1870