1个不稳定版本
0.1.2 | 2024年1月18日 |
---|
#1923 in 游戏开发
26 每月下载次数
在 2 crates 中使用
23KB
265 行
gdrust_export_node_path_macro
通过NodePath获取引用时减少样板代码。使用方法包括(下文几段完整的示例)
- 将
#[derive(NativeClass, Default)] #[inherit(Node)]
替换为#[extends(Node)]
- 删除带有
#[property]
标记的NodePath
字段 - 在您希望通过
NodePath
获取的字段之后放置#[export_path]
- 删除您的
fn new(&mut self, _owner: &Node)
实现 - 在您的
_ready()
声明中手动调用self.grab_nodes_by_path(_owner);
#[extends]
属性宏
- 用
#[derive(NativeClass)] #[inherit(Node)]
替换自身 - 然后,对于每个标记有
#[export_path]
- 声明另一个同名但带有
path_
前缀和NodePath
类型的字段,以及一个常规的#[property]
属性。 (Vec<Ref<Node>>
使用Vec<NodePath>
类型) - 示例输入/输出:
#[export_path] node: Option<Ref<Node>>
/#[property] path_node: NodePath, node: Option<Ref<Node>>,
- 声明另一个同名但带有
- 声明一个包含两个函数的 impl 块
fn grab_nodes_by_path(&mut self, _owner: &Node) { //搜索从生成的 NodePath 字段中生成的所有节点/实例,并将每个分配给 self 中的原始字段}
fn new(_owner: &Node) -> Self { Self::default() }
支持导出
Option<Ref<T>>
其中 T 是继承自Node
的 Godot 内置类型(例如:Node2D
,Control
,ProgressBar
,KinematicBody
,...)Vec<Ref<T>>
其中 T 是继承自Node
的 Godot 内置类型Option<Instance<T>>
其中 T 是您定义的自定义原生脚本,只要该脚本继承自 Godot 内置类型Node
Vec<Instance<T>>
其中 T 是您定义的自定义原生脚本,只要该脚本继承自 Godot 内置类型Node
PS 1:请注意,Vec<Ref<T>>
/Vec<Instance<T>>
使用 Ref<T>
/Instance<T>
直接,而不是 Option<Ref<T>>
/Option<Instance<T>>
PS 2:这与本 crate 无关,而是与 gdnative-rust
本身相关:在编辑器中,Vec<NodePath>
将显示为 Variant
数组,您必须点击数组中的每个元素,选择 NodePath
,然后您就可以拖动节点了。
实现的基础取自 gdrust。
用法
替换
#[derive(NativeClass)]
#[inherit(Node)]
struct MyGodotScript {
#[property] path_exported_node: NodePath,
exported_node: Option<Ref<Node>>,
#[property] path_exported_instance: NodePath,
exported_instance: Option<Instance<NativeScriptTest>>,
#[property] paths_exported_nodes: Vec<NodePath>,
vec_nodes: Vec<Ref<Node>>,
#[property] paths_exported_instances: Vec<NodePath>,
vec_instances: Vec<Instance<NativeScriptTest>>,
}
impl MyGodotScript {
fn new(_owner: &Node) -> Self {
return Self {
path_exported_node: NodePath::default(),
exported_node: None,
path_exported_instance: NodePath::default(),
exported_instance: None,
paths_exported_nodes: Vec::new(),
vec_nodes: Vec::new(),
paths_exported_instances: Vec::new(),
vec_instances: Vec::new(),
};
}
}
#[methods]
impl MyGodotScript {
#[method]
fn _ready(&mut self, #[base] _owner: &Node) {
self.exported_node = Some(unsafe {_owner.get_node_as::<Node>(self.path_exported_node.new_ref()).unwrap().assume_shared()});
self.exported_instance = Some(unsafe {_owner.get_node_as_instance::<NativeScriptTest>(self.path_exported_instance.new_ref()).unwrap().claim()});
for path in self.paths_exported_nodes.iter() {
self.vec_nodes.push(unsafe { _owner.get_node_as::<Node>(path.new_ref()).unwrap().assume_shared()});
}
for path in self.paths_exported_instances.iter() {
self.vec_instances.push(unsafe { _owner.get_node_as_instance::<NativeScriptTest>(path.new_ref()).unwrap().claim()});
}
}
}
#[derive(NativeClass)]
#[inherit(Node)]
pub struct NativeScriptTest { }
impl NativeScriptTest {
fn new(_owner: &Node) -> Self {
return Self {};
}
}
为
#[extends(Node)] // you can replace Node with any other Godot built-in node type
struct MyGodotScript {
#[export_path] exported_node: Option<Ref<Node>>, // you can replace Node with any other Godot built-in node type
#[export_path] exported_instance: Option<Instance<NativeScriptTest>>, // replace NativeScriptTest with your own type
#[export_path] vec_nodes: Vec<Ref<Node>>, // you can replace Node with any other Godot built-in node type
#[export_path] vec_instances: Vec<Instance<NativeScriptTest>>, // replace NativeScriptTest with your own type
}
#[methods]
impl MyGodotScript {
#[method]
fn _ready(&mut self, #[base] _owner: &Node) { // replace Node with the extended type
self.grab_nodes_by_path(_owner); // you must call this manually, it replaces your old _ready() call
}
}
#[extends(Node)]
pub struct NativeScriptTest { }
它扩展为(手动格式化以增强可读性)
#[derive(gdnative::prelude::NativeClass, Default)]
#[inherit(Node)]
struct MyGodotScript {
#[property] path_vec_instances: Vec<gdnative::prelude::NodePath>,
#[property] path_vec_nodes : Vec<gdnative::prelude::NodePath>,
#[property] path_exported_instance: gdnative::prelude::NodePath,
#[property] path_exported_node : gdnative::prelude::NodePath,
exported_node: Option<Ref<Node>>,
exported_instance: Option<Instance<NativeScriptTest>>,
vec_nodes: Vec<Ref<Node>>,
vec_instances: Vec<Instance<NativeScriptTest>>,
}
impl MyGodotScript {
fn new(_owner: &Node) -> Self { Self::default() }
fn grab_nodes_by_path(&mut self, owner: &Node) {
self.exported_node = Some(unsafe { owner.get_node_as::<Node>(self.path_exported_node.new_ref()).unwrap().assume_shared() });
self.exported_instance = Some(unsafe { owner.get_node_as_instance::<NativeScriptTest>(self.path_exported_instance.new_ref()).unwrap().claim() });
for path in self.path_vec_nodes.iter() {
self.vec_nodes.push(unsafe { owner.get_node_as::<Node>(path.new_ref()).unwrap().assume_shared() });
}
for path in self.path_vec_instances.iter() {
self.vec_instances.push(unsafe { owner.get_node_as_instance::<NativeScriptTest>(path.new_ref()).unwrap().claim() });
}
}
}
杂项/限制
- 您仍然可以自由使用其他
gdnative
属性,如#[register_with]
#[no_constructor]
#[user_data]
#[property]
。只需确保始终将它们放置在#[extends]
下方,除了#[property]
,它仍然位于字段之后。 grab_nodes_by_path(&&mut self, owner: &Node)
如果在验证任何导出路径失败时将引发恐慌。- 您不能定义自己的
Self::new()
。 _owner
在grab_nodes_by_path(&mut self, owner: &Node)
中使用了硬编码的&
,因此您不能在_ready(&mut self, #[base] _owner: &Node)
中将owner
声明为owner: TRef<Node>
。
依赖项
~3–4.5MB
~88K SLoC