bevy_mod_scripting_bindings/function/
namespace.rs1use crate::{
4 DummyScriptFunctionRegistry, ScriptFunctionRegistryArc,
5 docgen::info::GetFunctionInfo,
6 function::script_function::{AppScriptFunctionRegistry, ScriptFunction},
7};
8use ::bevy_reflect::{GetTypeRegistration, Reflect};
9use bevy_ecs::{reflect::AppTypeRegistry, world::World};
10use bevy_mod_scripting_derive::DebugWithTypeInfo;
11use bevy_mod_scripting_display::{DisplayWithTypeInfo, GetTypeInfo, WithTypeInfo};
12use std::{any::TypeId, borrow::Cow, marker::PhantomData};
13
14use super::type_dependencies::GetFunctionTypeDependencies;
15
16#[derive(Clone, Copy, PartialEq, Eq, Hash, Default, Reflect, DebugWithTypeInfo)]
18#[debug_with_type_info(bms_display_path = "bevy_mod_scripting_display")]
19pub enum Namespace {
20 #[default]
23 Global,
24 OnType(TypeId),
27}
28
29pub struct GlobalNamespace;
31
32pub trait IntoNamespace {
34 fn into_namespace() -> Namespace;
36}
37
38impl<T: ?Sized + 'static> IntoNamespace for T {
39 fn into_namespace() -> Namespace {
40 if TypeId::of::<T>() == TypeId::of::<GlobalNamespace>() {
41 Namespace::Global
42 } else {
43 Namespace::OnType(TypeId::of::<T>())
44 }
45 }
46}
47
48#[profiling::all_functions]
50impl Namespace {
51 pub fn prefix(self) -> Cow<'static, str> {
53 match self {
54 Namespace::Global => Cow::Borrowed(""),
55 Namespace::OnType(type_id) => Cow::Owned(format!("{type_id:?}::")),
56 }
57 }
58
59 pub fn function_name<I: Into<Cow<'static, str>>>(self, name: I) -> Cow<'static, str> {
61 match self {
62 Namespace::Global => name.into(),
63 Namespace::OnType(type_id) => Cow::Owned(format!("{:?}::{}", type_id, name.into())),
64 }
65 }
66}
67
68pub struct NamespaceBuilder<'a, N> {
70 registry: ScriptFunctionRegistryArc,
72 namespace: PhantomData<N>,
74 pub world: &'a mut World,
76}
77
78#[profiling::all_functions]
79impl<'a, S: IntoNamespace> NamespaceBuilder<'a, S> {
80 pub fn new(world: &'a mut World) -> Self
83 where
84 S: GetTypeRegistration,
85 {
86 {
87 let registry = world.get_resource_or_init::<AppTypeRegistry>();
88 let mut registry = registry.write();
89 registry.register::<S>();
90 }
91 Self {
92 registry: world
93 .get_resource_or_init::<AppScriptFunctionRegistry>()
94 .0
95 .clone(),
96 namespace: Default::default(),
97 world,
98 }
99 }
100
101 pub fn new_unregistered(world: &'a mut World) -> Self {
103 Self {
104 registry: world
105 .get_resource_or_init::<AppScriptFunctionRegistry>()
106 .0
107 .clone(),
108 namespace: Default::default(),
109 world,
110 }
111 }
112
113 pub fn with_dummy_registry(mut self) -> Self {
117 self.registry = self
118 .world
119 .get_resource_or_init::<DummyScriptFunctionRegistry>()
120 .0
121 .clone();
122 self
123 }
124
125 pub fn register<'env, N, F, M>(&mut self, name: N, function: F) -> &mut Self
127 where
128 N: Into<Cow<'static, str>>,
129 F: ScriptFunction<'env, M> + GetFunctionTypeDependencies<M> + GetFunctionInfo<M>,
130 {
131 self.register_inner(name, function, None, None)
132 }
133
134 pub fn register_documented<'env, N, F, M>(
136 &mut self,
137 name: N,
138 function: F,
139 docstring: &'static str,
140 arg_names: &'static [&'static str],
141 ) -> &mut Self
142 where
143 N: Into<Cow<'static, str>>,
144 F: ScriptFunction<'env, M> + GetFunctionTypeDependencies<M> + GetFunctionInfo<M>,
145 {
146 self.register_inner(name, function, Some(docstring), Some(arg_names))
147 }
148
149 fn register_inner<'env, N, F, M>(
150 &mut self,
151 name: N,
152 function: F,
153 docstring: Option<&'static str>,
154 arg_names: Option<&'static [&'static str]>,
155 ) -> &mut Self
156 where
157 N: Into<Cow<'static, str>>,
158 F: ScriptFunction<'env, M> + GetFunctionTypeDependencies<M> + GetFunctionInfo<M>,
159 {
160 {
161 {
162 let mut registry = self.registry.write();
163 registry.register_with_arg_names(
164 S::into_namespace(),
165 name,
166 function,
167 docstring.unwrap_or_default(),
168 arg_names.unwrap_or(&[]),
169 );
170 }
171 {
172 let type_registry = self.world.get_resource_or_init::<AppTypeRegistry>();
173 let mut type_registry = type_registry.write();
174 F::register_type_dependencies(&mut type_registry);
175 }
176 }
177 self
178 }
179}
180
181impl From<TypeId> for Namespace {
182 fn from(value: TypeId) -> Self {
183 Namespace::OnType(value)
184 }
185}
186
187impl DisplayWithTypeInfo for Namespace {
188 fn display_with_type_info(
189 &self,
190 f: &mut std::fmt::Formatter<'_>,
191 type_info_provider: Option<&dyn GetTypeInfo>,
192 ) -> std::fmt::Result {
193 match self {
194 Namespace::Global => f.write_str("Global Namespace"),
195 Namespace::OnType(type_id) => {
196 write!(
197 f,
198 "Namespace for type {}",
199 WithTypeInfo::new_with_opt_info(type_id, type_info_provider)
200 )
201 }
202 }
203 }
204}