如何正确引用相同的代码作为依赖项的依赖项?
How to properly reference the same code as a dependency of a dependency?
我有一个玩具项目正在使用 Amethyst game engine. I'm trying to write my own System
for collecting user input, similar to the FlyMovementSystem
and ArcBallRotationSystem
they have implemented here。
看来收集鼠标移动的正确方法是通过 EventChannel<Event>
,其中 Event
来自 winit
板条箱,Amethyst 依赖于它,但并不依赖它-出口。
引用与 Amethyst 相同的 winit::Event
的 "right" 方法是什么?
- 我应该将
winit
添加到我的 Cargo.toml
文件吗?如果是这样,指定版本的推荐方法是什么? (我可以使用一些关键字来代替特定的版本号,以允许我 "inherit" 来自 Amethyst 的依赖项吗?)
- 真的不鼓励引用子依赖吗?如果是这样,我应该怎么做?
这个问题目前没有很好的解决方案。最好的解决方法是添加对相同版本传递依赖的直接依赖:
[dependencies]
foo = "0.1"
bar = "0.2" # `foo` depends on bar 0.2 and we need to keep these in sync
您可以使用 cargo tree
等工具 手动 确定 foo
所需的版本并使您的 Cargo.toml 保持最新。我强烈建议添加一条评论,说明您选择特定版本的原因。
如果 crate 在不同时使用底层依赖项的情况下很难使用,我也鼓励您向父 crate 提出问题,请求他们重新导出所需的内容。 Tokio crate 就是一个很好的例子,re-exports large chunks of the futures crate。
与您的想法相似,I proposed having a way to use the same version as a dependency. Instead, the Cargo team opted to add the distinction of public and private dependencies。虽然从工程的角度来看这将是一个更好的解决方案,但在实施方面进展甚微。
另请参阅:
我将@Shepmaster 的回答保留为已接受的回答,因为它回答了我要问的一般问题。但多亏了@trentcl 的温和推动,以防万一有人发现这个问题是因为它与 Amethyst 的关系,这就是我最终做的事情。
根本不要尝试获得 winit::Events
。
当您将 InputBundle<AX, AC>
附加到您的 GameData 时,它会设置一个 InputSystem<AX, AC>
,以 InputEvent<AC>
的形式重新发布 winit::Events
。
它通过将 EventChannel<InputEvent<AC>>
设置为资源来实现此目的,您可以通过 ECS 系统中的 Read
类型访问它。解释了 EventChannels 及其用法 in the Amethyst Book。
我后来改用另一种方法来处理我的用户输入,但大致是这样的(注意:Amethyst a little after v0.10.0):
pub struct MouseMovementSystem {
reader: Option<ReaderId<InputEvent<()>>>, // AC = ()
}
impl<'s> System<'s> for MouseMovementSystem {
type SystemData = (
Read<'s, EventChannel<InputEvent<()>>>,
/* and others */
}
fn run(&mut self, (events, /* and others */): Self::SystemData) {
let foo = events.read(self.reader.as_mut().unwrap())
.yadda_yadda(/* ... */); // event processing logic
do_stuff(foo);
}
fn setup(&mut self, res: &mut Resources) {
use amethyst::core::specs::prelude::SystemData;
Self::SystemData::setup(res);
self.reader = Some(res.fetch_mut::<EventChannel<InputEvent<()>>>().register_reader());
}
}
我有一个玩具项目正在使用 Amethyst game engine. I'm trying to write my own System
for collecting user input, similar to the FlyMovementSystem
and ArcBallRotationSystem
they have implemented here。
看来收集鼠标移动的正确方法是通过 EventChannel<Event>
,其中 Event
来自 winit
板条箱,Amethyst 依赖于它,但并不依赖它-出口。
引用与 Amethyst 相同的 winit::Event
的 "right" 方法是什么?
- 我应该将
winit
添加到我的Cargo.toml
文件吗?如果是这样,指定版本的推荐方法是什么? (我可以使用一些关键字来代替特定的版本号,以允许我 "inherit" 来自 Amethyst 的依赖项吗?) - 真的不鼓励引用子依赖吗?如果是这样,我应该怎么做?
这个问题目前没有很好的解决方案。最好的解决方法是添加对相同版本传递依赖的直接依赖:
[dependencies]
foo = "0.1"
bar = "0.2" # `foo` depends on bar 0.2 and we need to keep these in sync
您可以使用 cargo tree
等工具 手动 确定 foo
所需的版本并使您的 Cargo.toml 保持最新。我强烈建议添加一条评论,说明您选择特定版本的原因。
如果 crate 在不同时使用底层依赖项的情况下很难使用,我也鼓励您向父 crate 提出问题,请求他们重新导出所需的内容。 Tokio crate 就是一个很好的例子,re-exports large chunks of the futures crate。
与您的想法相似,I proposed having a way to use the same version as a dependency. Instead, the Cargo team opted to add the distinction of public and private dependencies。虽然从工程的角度来看这将是一个更好的解决方案,但在实施方面进展甚微。
另请参阅:
我将@Shepmaster 的回答保留为已接受的回答,因为它回答了我要问的一般问题。但多亏了@trentcl 的温和推动,以防万一有人发现这个问题是因为它与 Amethyst 的关系,这就是我最终做的事情。
根本不要尝试获得 winit::Events
。
当您将 InputBundle<AX, AC>
附加到您的 GameData 时,它会设置一个 InputSystem<AX, AC>
,以 InputEvent<AC>
的形式重新发布 winit::Events
。
它通过将 EventChannel<InputEvent<AC>>
设置为资源来实现此目的,您可以通过 ECS 系统中的 Read
类型访问它。解释了 EventChannels 及其用法 in the Amethyst Book。
我后来改用另一种方法来处理我的用户输入,但大致是这样的(注意:Amethyst a little after v0.10.0):
pub struct MouseMovementSystem {
reader: Option<ReaderId<InputEvent<()>>>, // AC = ()
}
impl<'s> System<'s> for MouseMovementSystem {
type SystemData = (
Read<'s, EventChannel<InputEvent<()>>>,
/* and others */
}
fn run(&mut self, (events, /* and others */): Self::SystemData) {
let foo = events.read(self.reader.as_mut().unwrap())
.yadda_yadda(/* ... */); // event processing logic
do_stuff(foo);
}
fn setup(&mut self, res: &mut Resources) {
use amethyst::core::specs::prelude::SystemData;
Self::SystemData::setup(res);
self.reader = Some(res.fetch_mut::<EventChannel<InputEvent<()>>>().register_reader());
}
}