3 个不稳定版本
0.2.1 | 2022 年 12 月 19 日 |
---|---|
0.2.0 | 2022 年 12 月 17 日 |
0.1.0 | 2022 年 3 月 10 日 |
1271 在 游戏开发 中
每月 24 次下载
5.5MB
2.5K SLoC
use dip::prelude::*;
fn main() {
App::new()
.insert_resource(WindowDescriptor {
title: "dip Plugin Example".to_string(),
..Default::default()
})
.add_plugin(DesktopPlugin::<NoUiState, NoUiAction, NoAsyncAction>::new(Root))
.run();
}
fn Root(cx: Scope) -> Element {
cx.render(rsx! {
h1 { "Hello, World !" }
})
}
- 所有功能都作为 Bevy 插件实现
- 数据驱动 ECS 设计模式
- 在游戏、桌面应用程序和命令行工具之间共享您的逻辑
- 基于 Webview 的 UI,由 Tauri 提供
- 通过 Dioxus 提供类似 React 的声明式 UI
- 开发者工具
警告:
dip
仍处于非常早期的开发阶段。
v0.1
完全是不同的应用程序。我想制作一个跨平台的文本编辑器,但最终制作了这个框架。
功能
桌面应用程序
具有组件状态的最小设置
代码示例
# Cargo.toml
[dependencies]
dip = { version = "0.2", features = ["desktop"] }
use dip::prelude::*;
fn main() {
App::new()
.insert_resource(WindowDescriptor {
title: "Desktop App".to_string(),
..Default::default()
})
.add_plugin(DesktopPlugin::<NoUiState, NoUiAction, NoAsyncAction>::new(Root))
.run();
}
fn Root(cx: Scope) -> Element {
let name = use_state(&cx, || "world".to_string());
cx.render(rsx! {
h1 { "Hello, {name} !" }
input {
value: "{name}",
oninput: |e| {
name.set(e.value.to_string());
},
}
})
}
键盘处理
命令行应用程序
CliPlugin
代码示例
# Cargo.toml
[dependencies]
dip = { version = "0.2", features = ["cli"] }
clap = { version = "3.2", features = ["derive"] }
use dip::{bevy::log::LogPlugin, prelude::*};
fn main() {
App::new()
.add_plugin(CliPlugin::<NoAsyncAction>::oneshot())
.add_plugin(ActionPlugin)
.add_plugin(LogPlugin)
.add_system(log_root_arg)
.add_system(log_path_flag)
.add_system(handle_hello)
.add_system(handle_task)
.add_system(handle_ping)
.run();
}
#[derive(CliPlugin, clap::Parser)]
#[clap(author, version, about, long_about = None)]
struct Cli {
root_arg: Option<String>,
#[clap(short, long)]
path: Option<String>,
#[clap(subcommand)]
action: Action,
}
#[derive(SubcommandPlugin, clap::Subcommand, Clone)]
pub enum Action {
// Named variant
Hello { name: Option<String> },
// Unnamed
Hello2(Hello2Args),
// Unit
Ping,
}
#[derive(clap::Args, Debug, Clone)]
pub struct Hello2Args {
name: Option<String>,
}
fn log_root_arg(cli: Res<Cli>) {
if let Some(arg) = &cli.root_arg {
info!("root arg: {:?}", arg);
}
}
fn log_path_flag(cli: Res<Cli>) {
if let Some(path) = &cli.path {
info!("path flag: {:?}", path);
}
}
fn handle_hello(mut events: EventReader<HelloAction>) {
for e in events.iter() {
info!("Hello, {}!", e.name.clone().unwrap_or("world".to_string()));
}
}
fn handle_task(mut events: EventReader<Hello2Action>) {
for e in events.iter() {
info!("Hello, {}!", e.name.clone().unwrap_or("world".to_string()));
}
}
fn handle_ping(mut events: EventReader<PingAction>) {
for _ in events.iter() {
info!("Pong !");
}
}
cargo run -- --help
dip-cli-example 0.1.0
Junichi Sugiura
Example binary project to showcase CliPlugin usage.
USAGE:
cli [OPTIONS] [ROOT_ARG] <SUBCOMMAND>
ARGS:
<ROOT_ARG>
OPTIONS:
-h, --help Print help information
-p, --path <PATH>
-V, --version Print version information
SUBCOMMANDS:
hello
hello2
help Print this message or the help of the given subcommand(s)
ping
状态管理(受 Redux 启发)
UiStatePlugin,UiActionPlugin
代码示例
# Cargo.toml
[dependencies]
dip = { version = "0.2", features = ["desktop"] }
# Removing this crate throws error.
# This is because some derive macros generates code using sub crate name instead of root
# (e.x. bevy_ecs::Component vs bevy::ecs::Compoent)
bevy_ecs = "0.8"
use dip::prelude::*;
fn main() {
App::new()
// Step 7. Put it all together
.add_plugin(DesktopPlugin::<UiState, UiAction, NoAsyncAction>::new(Root))
.add_plugin(UiStatePlugin) // generated by #[ui_state]
.add_plugin(UiActionPlugin) // generated by #[ui_action]
.add_system(update_name)
.run();
}
// Step 1: Define UiState
// Each field represents root state. You can create multiple of them.
// This macro generates UiState enum and UiStatePlugin which will be used in step 7.
#[ui_state]
struct UiState {
name: Name,
}
// Make sure to wrap primitive types or common type such as String with named struct or enum.
// You need to distinguish types in order to query specific root state in step 4 (system).
#[derive(Clone, Debug)]
pub struct Name {
value: String,
}
// This is how you define default value for Name root state.
impl Default for Name {
fn default() -> Self {
Self {
value: "world".to_string(),
}
}
}
// Step 2. Define actions
// Create as many as actions with struct or enum.
#[derive(Clone, Debug)]
pub struct UpdateName {
value: String,
}
// Step 3. Implement action creators
// Each method needs to return one of actions that you defined in step 2.
// This macro derives UiActionPlugin and UiAction which will be used in step 7.
#[ui_action]
impl ActionCreator {
fn update_name(value: String) -> UpdateName {
UpdateName { value }
}
}
// Step 4. Implement systems to handle each action defined in step 2.
// System is like reducer in Redux but more flexible.
fn update_name(mut events: EventReader<UpdateName>, mut name: ResMut<Name>) {
for action in events.iter() {
name.value = action.value.clone();
}
}
fn Root(cx: Scope) -> Element {
// Step 5. Select state
let name = use_read(&cx, NAME);
let window = use_window::<UiAction, NoAsyncAction>(&cx);
cx.render(rsx! {
h1 { "Hello, {name.value} !" }
input {
value: "{name.value}",
oninput: |e| {
// Step 6. Dispatch the action !
window.send(UiAction::update_name(e.value.to_string()));
},
}
})
}
关于 Bevy 和 Dioxus
Bevy
https://github.com/bevyengine/bevy
- 基于实体组件系统 (ECS) 设计模式的数据驱动游戏引擎
- 灵活的插件设计
- 插件生态系统
Bevy是一个基于Rust的,基于实体组件系统(ECS)设计模式的先进游戏引擎。把它想象成一个类似于Redux的全局状态管理工具,但性能更出色,因为所有系统都会尽可能并行运行。得益于其插件系统,已经有许多第三方Bevy插件。想象一下,将核心逻辑作为CorePlugin
实现,将其与UI层分离。您可以从dip::desktop
开始,构建桌面应用程序。然后假设您想在将来某个时候发布一个元宇宙版本,这就像将UI插件切换为Bevy的3D渲染插件一样简单,同时仍然使用相同的CorePlugin。
Tauri
Tao是一个窗口管理器,是winit
的分支。`DesktopPlugin`依赖于这个库来渲染webview。而webview由WRY提供支持,WRY本质上是一个围绕特定操作系统webview的Rust封装。
为什么不选择Tauri呢?
如果您想用除Rust以外的任何语言编写前端,那么Tauri是一个更好的选择!如果您想全栈使用Rust,那么dip
就非常出色。
Dioxus
https://github.com/DioxusLabs/dioxus
- 跨平台(macOS、Linux、Windows、TUI等)
- 类似React的声明式UI库
- 虚拟DOM比React快3倍
- 最小包大小比Electron轻20倍左右(8 MB vs 160MB)
Dioxus是一个跨平台的声明式UI库。它提供了React开发者期望的熟悉功能,如组件、状态、属性、钩子、全局状态和路由。如果您熟悉任何现代的状态驱动UI框架,您应该能够阅读或编写Dioxus组件而无需了解Rust。
示例
请确保安装Tauri的所有先决条件。
克隆仓库
gh repo clone diptools/dip
cd dip
计数器示例
cargo run --example counter --features desktop
更多信息请参阅examples/目录。
TodoMVC示例
- 安装dip CLI。
cargo install dip
# or install local binary
cargo install --path .
- 编译Tailwind CSS
dip build -p examples/todomvc
- 运行
cargo run -p todomvc
依赖项
~30–79MB
~1.5M SLoC