Skip to content

Commit

Permalink
改进了窗口和分页组件效果(仅改版 Druid 可用)
Browse files Browse the repository at this point in the history
修正了定位 Java 运行时行为问题
  • Loading branch information
Steve-xmh committed Nov 5, 2023
1 parent 85c3cbf commit 906828e
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 24 deletions.
16 changes: 12 additions & 4 deletions scl-core/src/java.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use std::path::{Path, PathBuf};

use inner_future::stream::StreamExt;

use crate::{prelude::*, utils::Arch};
use crate::{
prelude::*,
utils::{locate_path, Arch},
};

/// 一个 Java 运行时类型
#[derive(Debug, Clone)]
Expand All @@ -20,14 +23,19 @@ impl JavaRuntime {
///
/// 在此会尝试运行这个文件并获取相关的版本信息,确认无误后返回
pub async fn from_java_path(java_path: impl AsRef<std::ffi::OsStr>) -> DynResult<Self> {
tracing::debug!(
"正在重新定位 Java 执行文件: {}",
java_path.as_ref().to_string_lossy()
);
let java_path = locate_path(java_path.as_ref());
tracing::debug!("Java 执行文件已重新定位: {}", java_path.display());
let output = query_java_version_output(&java_path).await?;
let version = query_java_version(&output);
let java_main_version = get_java_version(version);
let java_64bit = query_java_is_64bit(&output);
let java_arch =
crate::utils::get_exec_arch(std::path::PathBuf::from(java_path.as_ref())).await?;
let java_arch = crate::utils::get_exec_arch(&java_path).await?;
Ok(Self {
java_path: java_path.as_ref().to_string_lossy().to_string(),
java_path: java_path.to_string_lossy().to_string(),
java_64bit,
java_version: version.to_owned(),
java_main_version,
Expand Down
48 changes: 46 additions & 2 deletions scl-core/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! 一些启动/安装游戏时会用到的实用模块

use std::fmt::Display;
use std::{
fmt::Display,
path::{Path, PathBuf},
};

use inner_future::io::{AsyncRead, AsyncReadExt};
use sha1_smol::*;
Expand Down Expand Up @@ -141,6 +144,47 @@ pub fn get_full_path(p: impl AsRef<std::path::Path>) -> String {
}
}

/// 根据传入的参数,返回一个可执行文件的绝对路径,如有必要会加上 `.exe` 后缀
///
/// 首先会确认路径是否存在,存在就直接返回,否则获取 `PATH` 环境变量并根据其中的路径逐个查询。
pub fn locate_path(exe_name: impl AsRef<Path>) -> PathBuf {
if exe_name.as_ref().is_file() {
return exe_name.as_ref().to_path_buf();
} else {
#[cfg(target_os = "windows")]
{
let exe_path = exe_name.as_ref().with_extension("exe");
if exe_path.is_file() {
return exe_path;
}
}
}
std::env::var_os("PATH")
.and_then(|paths| {
std::env::split_paths(&paths).find_map(|dir| {
let full_path = dir.join(&exe_name);
if full_path.is_file() {
Some(full_path)
} else {
#[cfg(target_os = "windows")]
{
let exe_path = full_path.with_extension("exe");
if exe_path.is_file() {
Some(exe_path)
} else {
None
}
}
#[cfg(not(target_os = "windows"))]
{
None
}
}
})
})
.unwrap_or_else(|| exe_name.as_ref().to_path_buf())
}

/// 系统架构枚举
///
/// 目前根据 SCL 自身会支持的平台增加此处的枚举值
Expand Down Expand Up @@ -258,7 +302,7 @@ pub async fn get_exec_arch(file_path: impl AsRef<std::path::Path>) -> DynResult<

file.read_exact(&mut buf).await?;

match dbg!(buf) {
match buf {
[0x4C, 0x01] => Ok(Arch::X86), // X86 I386
[0x64, 0x86] => Ok(Arch::X64), // X86_64
[0x64, 0xAA] => Ok(Arch::ARM64), // ARM64
Expand Down
4 changes: 4 additions & 0 deletions scl-gui-widgets/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ authors = ["Steve-xmh <[email protected]>"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
defaults = []
druid-ext = []

[dependencies]
scl-gui-animation = { path = "../scl-gui-animation" }
scl-macro = { path = "../scl-macro" }
Expand Down
5 changes: 5 additions & 0 deletions scl-gui-widgets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ SCL Druid 组件库,其组件风格大量参考了 WinUI 3 和 Fluent Design
有部分组件是从 [linebender/druid-widget-nursery](https://github.com/linebender/druid-widget-nursery)
这个项目移植过来并修改成了大体符合 SCL 需求的组件们。在这里感谢他们的组件,原仓库是使用
MIT / Apache 2.0 开源协议开源的。

### 部分功能

为了辅助 SCL 的部分组件更好地实现部分效果,作者对 Druid/Piet 做了二次开发,其中添加了一些特性(例如文字裁切,全局透明度等)。
为了保证和主线 Druid 的兼容性,组件库提供了一个 `druid-ext` 特性用于开启这些增加的特殊效果,但必须使用来自 [`Steve-xmh/druid`](https://github.com/Steve-xmh/druid)[`Steve-xmh/piet`](https://github.com/Steve-xmh/piet) 分支改版方可正确编译。
47 changes: 32 additions & 15 deletions scl-gui-widgets/src/widgets/page_switcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ impl<T: Data> Widget<T> for PageSwitcher<T> {
}

fn paint(&mut self, ctx: &mut druid::PaintCtx, data: &T, env: &druid::Env) {
#[cfg(not(feature = "druid-ext"))]
let page_mask = env.get(druid::theme::WINDOW_BACKGROUND_COLOR);
let anime_timer = self.page_anime_timer.min(ANIMATION_TIME);
let size = ctx.size();
Expand All @@ -330,12 +331,18 @@ impl<T: Data> Widget<T> for PageSwitcher<T> {
size.height * s * -SCALE_LEVEL / 2.,
)),
);
// ctx.apply_global_transparency(1. - s);
#[cfg(feature = "druid-ext")]
ctx.set_global_alpha(1. - s);
ctx.save().unwrap();
inner.paint(ctx, data, env);
ctx.fill(
transparent_rect.to_owned(),
&PaintBrush::Color(page_mask.with_alpha(s)),
);
#[cfg(not(feature = "druid-ext"))]
{
ctx.fill(
transparent_rect.to_owned(),
&PaintBrush::Color(page_mask.with_alpha(s)),
);
}
ctx.restore().unwrap();
}
} else {
let s = (s - 0.5) * 2.;
Expand All @@ -348,12 +355,16 @@ impl<T: Data> Widget<T> for PageSwitcher<T> {
size.height * (1. - s) * SCALE_LEVEL / 2.,
)),
);
// ctx.apply_global_transparency(s);
#[cfg(feature = "druid-ext")]
ctx.set_global_alpha(s);
ctx.save().unwrap();
inner.paint(ctx, data, env);
#[cfg(not(feature = "druid-ext"))]
ctx.fill(
transparent_rect.to_owned(),
&PaintBrush::Color(page_mask.with_alpha(1. - s)),
);
ctx.restore().unwrap();
}
}
}
Expand All @@ -371,12 +382,16 @@ impl<T: Data> Widget<T> for PageSwitcher<T> {
size.height * s * SCALE_LEVEL / 2.,
)),
);
// ctx.apply_global_transparency(1. - s);
#[cfg(feature = "druid-ext")]
ctx.set_global_alpha(1. - s);
ctx.save().unwrap();
inner.paint(ctx, data, env);
#[cfg(not(feature = "druid-ext"))]
ctx.fill(
transparent_rect.to_owned(),
&PaintBrush::Color(page_mask.with_alpha(s)),
);
ctx.restore().unwrap();
}
} else {
let s = (s - 0.5) * 2.;
Expand All @@ -389,12 +404,16 @@ impl<T: Data> Widget<T> for PageSwitcher<T> {
transparent_size.height * (1. - s) * -SCALE_LEVEL / 2.,
)),
);
// ctx.apply_global_transparency(s);
#[cfg(feature = "druid-ext")]
ctx.set_global_alpha(s);
ctx.save().unwrap();
inner.paint(ctx, data, env);
#[cfg(not(feature = "druid-ext"))]
ctx.fill(
transparent_rect.to_owned(),
&PaintBrush::Color(page_mask.with_alpha(1. - s)),
);
ctx.restore().unwrap();
}
}
}
Expand Down Expand Up @@ -435,20 +454,14 @@ impl<T: Data> Widget<T> for PageSwitcher<T> {
// 要退出的页面
if let Some(inner) = self.inner.get_mut(self.active_page) {
ctx.transform(Affine::translate((size.width * s, 0.)));
// ctx.apply_global_transparency(1. - s);
inner.paint(ctx, data, env);
}
} else {
let s = (s - 0.5) * 2.;
// 要进入的页面
if let Some(inner) = self.inner.get_mut(page) {
ctx.transform(Affine::translate((size.width * (s - 1.), 0.)));
// ctx.apply_global_transparency(s);
inner.paint(ctx, data, env);
// ctx.fill(
// transparent_rect.to_owned(),
// &PaintBrush::Color(page_mask.with_alpha(1. - s)),
// );
}
}
}
Expand All @@ -457,12 +470,16 @@ impl<T: Data> Widget<T> for PageSwitcher<T> {
let x = ((anime_timer) as f64) / ANIMATION_TIME as f64;
let s = 1. - scl_gui_animation::tween::ease_out_expo(x);
ctx.transform(Affine::translate((0., s * size.height.min(100.))));
// ctx.apply_global_transparency(1. - s);
#[cfg(feature = "druid-ext")]
ctx.set_global_alpha(1. - s);
ctx.save().unwrap();
inner.paint(ctx, data, env);
#[cfg(not(feature = "druid-ext"))]
ctx.fill(
transparent_rect.to_owned(),
&PaintBrush::Color(page_mask.with_alpha(s)),
);
ctx.restore().unwrap();
}
}
None => {
Expand Down
12 changes: 9 additions & 3 deletions scl-gui-widgets/src/widgets/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,14 +425,20 @@ impl<T: Data> Widget<T> for WindowWidget<T> {
RawWindowHandle::Win32(handle)
}
}
window_shadows::set_shadow(
let _ = window_shadows::set_shadow(
WinHandle {
handle: handle.hwnd as _,
instance: handle.hinstance as _,
},
true,
)
.unwrap_or_default();
);
let _ = window_vibrancy::apply_acrylic(
WinHandle {
handle: handle.hwnd as _,
instance: handle.hinstance as _,
},
None,
);
}
}
#[cfg(target_os = "macos")]
Expand Down

0 comments on commit 906828e

Please sign in to comment.