Skip to content

Commit b65214a

Browse files
committed
feat: add construct global for constructing arbitrary FromReflect implementing types in scripts
1 parent 18cee6f commit b65214a

File tree

20 files changed

+786
-15
lines changed

20 files changed

+786
-15
lines changed

crates/bevy_mod_scripting_core/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ bevy_mod_scripting_derive = { workspace = true }
4848
[dev-dependencies]
4949
test_utils = { workspace = true }
5050
tokio = { version = "1", features = ["rt", "macros"] }
51+
pretty_assertions = "1.4"
5152

5253
[lints]
5354
workspace = true

crates/bevy_mod_scripting_core/src/bindings/function/arg_meta.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
};
99

1010
use super::{
11-
from::{FromScript, Mut, Ref, Val},
11+
from::{FromScript, Mut, Ref, Union, Val},
1212
into::IntoScript,
1313
script_function::{DynamicScriptFunction, DynamicScriptFunctionMut, FunctionCallContext},
1414
type_dependencies::GetTypeDependencies,
@@ -72,6 +72,7 @@ impl_arg_info!(
7272
&'static str
7373
);
7474

75+
impl<T1, T2> ArgMeta for Union<T1, T2> {}
7576
impl<T> ArgMeta for Val<T> {}
7677
impl<T> ArgMeta for Ref<'_, T> {}
7778
impl<T> ArgMeta for Mut<'_, T> {}

crates/bevy_mod_scripting_core/src/bindings/function/from.rs

+43
Original file line numberDiff line numberDiff line change
@@ -456,3 +456,46 @@ where
456456
}
457457
}
458458
}
459+
460+
/// A union of two or more (by nesting unions) types.
461+
pub struct Union<T1, T2>(Result<T1, T2>);
462+
463+
impl<T1, T2> Union<T1, T2> {
464+
/// Try interpret the union as the left type
465+
pub fn into_left(self) -> Result<T1, T2> {
466+
match self.0 {
467+
Ok(r) => Ok(r),
468+
Err(l) => Err(l),
469+
}
470+
}
471+
472+
/// Try interpret the union as the right type
473+
pub fn into_right(self) -> Result<T2, T1> {
474+
match self.0 {
475+
Err(r) => Ok(r),
476+
Ok(l) => Err(l),
477+
}
478+
}
479+
}
480+
481+
impl<T1: FromScript, T2: FromScript> FromScript for Union<T1, T2>
482+
where
483+
for<'a> T1::This<'a>: Into<T1>,
484+
for<'a> T2::This<'a>: Into<T2>,
485+
{
486+
type This<'w> = Self;
487+
fn from_script(
488+
value: ScriptValue,
489+
world: WorldGuard<'_>,
490+
) -> Result<Self::This<'_>, InteropError> {
491+
let _ = match T1::from_script(value.clone(), world.clone()) {
492+
Ok(v) => return Ok(Union(Ok(v.into()))),
493+
Err(e) => e,
494+
};
495+
496+
match T2::from_script(value, world) {
497+
Ok(v) => Ok(Union(Err(v.into()))),
498+
Err(e) => Err(e),
499+
}
500+
}
501+
}

crates/bevy_mod_scripting_core/src/bindings/function/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ mod test {
1818
use crate::{
1919
bindings::{
2020
function::{
21-
from::{Ref, Val},
21+
from::{Ref, Union, Val},
2222
namespace::IntoNamespace,
2323
script_function::AppScriptFunctionRegistry,
2424
},
@@ -109,6 +109,8 @@ mod test {
109109

110110
#[test]
111111
fn composites_are_valid_args() {
112+
test_is_valid_arg::<Union<usize, usize>>();
113+
112114
fn test_val<T>()
113115
where
114116
T: ScriptArgument + ScriptReturn,

crates/bevy_mod_scripting_core/src/bindings/function/type_dependencies.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This module contains the [`GetTypeDependencies`] trait and its implementations for various types.
22
33
use super::{
4-
from::{Mut, Ref, Val},
4+
from::{Mut, Ref, Union, Val},
55
script_function::FunctionCallContext,
66
};
77
use crate::{
@@ -88,6 +88,13 @@ recursive_type_dependencies!(
8888
(HashMap<K,V> where K: GetTypeRegistration;FromReflect;Typed;Hash;Eq, V: GetTypeRegistration;FromReflect;Typed => with Self)
8989
);
9090

91+
impl<T1: GetTypeDependencies, T2: GetTypeDependencies> GetTypeDependencies for Union<T1, T2> {
92+
fn register_type_dependencies(registry: &mut TypeRegistry) {
93+
T1::register_type_dependencies(registry);
94+
T2::register_type_dependencies(registry);
95+
}
96+
}
97+
9198
bevy::utils::all_tuples!(register_tuple_dependencies, 1, 14, T);
9299

93100
/// A trait collecting type dependency information for a whole function. Used to register everything used by a function with the type registry

crates/bevy_mod_scripting_core/src/bindings/query.rs

+10
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ impl ScriptResourceRegistration {
8080
pub fn type_registration(&self) -> &ScriptTypeRegistration {
8181
&self.registration
8282
}
83+
84+
/// Convert to a generic [`ScriptTypeRegistration`] ditching the resource information.
85+
pub fn into_type_registration(self) -> ScriptTypeRegistration {
86+
self.registration
87+
}
8388
}
8489

8590
impl ScriptComponentRegistration {
@@ -101,6 +106,11 @@ impl ScriptComponentRegistration {
101106
pub fn type_registration(&self) -> &ScriptTypeRegistration {
102107
&self.registration
103108
}
109+
110+
/// Convert to a generic [`ScriptTypeRegistration`] ditching the component information.
111+
pub fn into_type_registration(self) -> ScriptTypeRegistration {
112+
self.registration
113+
}
104114
}
105115

106116
impl std::fmt::Debug for ScriptTypeRegistration {

crates/bevy_mod_scripting_core/src/bindings/reference.rs

+10
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ pub enum TypeIdSource {
6161
}
6262
#[profiling::all_functions]
6363
impl ReflectReference {
64+
/// If this points to a variant of an enum, returns the name of the variant.
65+
pub fn variant_name(&self, world: WorldGuard) -> Result<Option<String>, InteropError> {
66+
self.with_reflect(world, |s| {
67+
s.reflect_ref()
68+
.as_enum()
69+
.ok()
70+
.map(|enum_ref| enum_ref.variant_name().to_owned())
71+
})
72+
}
73+
6474
/// Creates a new infinite iterator. This iterator will keep returning the next element reference forever.
6575
pub fn into_iter_infinite(self) -> ReflectRefIter {
6676
ReflectRefIter::new_indexed(self)

0 commit comments

Comments
 (0)