Closed makspll closed 2 years ago
You can certainly return Dynamic
from methods.
What is the error you got?
fn my_func(x: i64) -> Dynamic {
(x + 1).into()
}
engine.register_fn("func", my_func);
Hmm, Yeah i've since realised into
should be working, but it's not for some reason. Not sure why this isn't working:
#[derive(Clone)]
pub struct RhaiTypeRegistration(Arc<TypeRegistration>);
pub fn get_type_by_name(&mut self, type_name: &str) -> Dynamic {
let w = self.read();
let registry: &TypeRegistry = w.get_resource().unwrap();
let registry = registry.read();
registry
.get_with_short_name(type_name)
.or_else(|| registry.get_with_name(type_name))
.map(|registration| RhaiTypeRegistration::new(Arc::new(registration.clone())).into()) // <- error here
.unwrap_or_default()
}
I've thought maybe the type wasn't send/sync but even if i implement those it doesn't work. I get a bound error:
the trait bound `bevy_mod_scripting_rhai::rhai::ImmutableString: std::convert::From<rhai::bevy::RhaiTypeRegistration>` is not satisfied
the following other types implement trait `std::convert::From<T>`:
<bevy_mod_scripting_rhai::rhai::ImmutableString as std::convert::From<&smartstring::SmartString<smartstring::config::LazyCompact>>>
<bevy_mod_scripting_rhai::rhai::ImmutableString as std::convert::From<&std::string::String>>
<bevy_mod_scripting_rhai::rhai::ImmutableString as std::convert::From<&str>>
<bevy_mod_scripting_rhai::rhai::ImmutableString as std::convert::From<smartstring::SmartString<smartstring::config::LazyCompact>>>
<bevy_mod_scripting_rhai::rhai::ImmutableString as std::convert::From<std::boxed::Box<str>>>
<bevy_mod_scripting_rhai::rhai::ImmutableString as std::convert::From<std::string::String>>
required because of the requirements on the impl of `std::convert::Into<bevy_mod_scripting_rhai::rhai::ImmutableString>` for `rhai::bevy::RhaiTypeRegistration`
required because of the requirements on the impl of `std::convert::From<rhai::bevy::RhaiTypeRegistration>` for `bevy_mod_scripting_rhai::rhai::Dynamic`
1 redundant requirement hidden
required because of the requirements on the impl of `std::convert::Into<bevy_mod_scripting_rhai::rhai::Dynamic>` for `rhai::bevy::RhaiTypeRegistration`
Ah... switching into
into from
did the job, i didn't realise one could work without the other
Ah... switching
into
intofrom
did the job, i didn't realise one could work without the other
Well, Dynamic::from
is a special implementation that works with everything, not just pre-defined types. It is not the same as the From
trait (although the name is the same). It is quite common in Rust to have from
implementations that are separate from the From/Into
traits pair.
into
only works for types that are built into Rhai.
BTW, I just see your repo https://github.com/makspll/bevy_mod_scripting
Since you're supporting mlua and rhai, can you let me know how you feel about the two?
I never anticipated that Rhai can be used for gaming (since Lua is sorta the standard there).
It is not the same as the From trait
that would explain my confusion haha.
Since you're supporting mlua and rhai, can you let me know how you feel about the two? I never anticipated that Rhai can be used for gaming (since Lua is sorta the standard there).
Sure! The biggest difference between the two would be of course how workable they are with existing types, mlua, because it is built on Lua, requires a lot of traits/boilerplate to convert between things you don't own and Lua representable types. Rhai on the other hand, because it already supports ANY type, is so much more convenient to plug in.
Since my library deals with creating pass-by-ref wrappers, this interoperability is VERY valuable.
I think both languages have their strong suits, Lua's being performance of course (although the recent benchmarks I saw showed that Rhai is not that far behind!).
Rhai does work much better if you are already familiar with Rust, so having a language similar to Rust is very valuable when making a moddable game (since then your game becomes a mod itself), but a lot more people will be familiar with Lua of course.
I haven't scripted in either language for too long so I cannot comment much on language design and features, but I think Rhai is quite nice especially considering Lua indexing starting at 1 (aaaAAA), and that avoids bug-prone marshalling code (ew).
I think Overall Rhai is a fairly good contender for scripting, I don't know at the time how it would do performance wise, so it may be the case that it could only really be used for things like UI/light (and sparse) logic scripting, but even then I think it's a good option to have as part of a multi-language scripting approach
Lua indexing starting at 1
Yeah, that's always a big trip-up! Reminds me of Visual Basic days, but in VB you can further confuse everyone by using a global setting to make arrays start from zero.
Indeed, it's my one and biggest quam with Lua
Oh and I forgot but WASM support is REALLY good to have, and Rhai would allow my library to run in the browser I believe!
Rhai would allow my library to run in the browser I believe
This is correct. You're not the only one who comes to Rhai because of the lack of WASM support for Lua...
BTW, anything that you're frustrated with Rhai when integrating it into your engine? Any feature that would make your life easier?
BTW, anything that you're frustrated with Rhai when integrating it into your engine? Any feature that would make your life easier?
Hmm, native support for any references :p jk jk,
I think the integration experience is better than with Lua, I haven't encountered any deal-breaker issues yet, or anything stopping me from having the equivalent functionality I implemented in Lua.
The plugin system is quite convenient already, and avoids a lot of boilerplate which is very nice, i'll let you know if anything pops up though!
Actually @schungx, I wonder if it's possible to receive the scope as part of NativeCallContext API? I am making indexers for reflected types, and it's difficult to work around not having access to the globals available in the script
That would be difficult (otherwise it would have already been done).
That's because, for a native function, the &mut
parameter can (and usually is) point to a variable in the scope. That means the whole scope is locked. Rust won't allow access to the scope within the function as long as that &mut
parameter is alive.
Unless we resort to unsafe code, there is no easy way to deal with this. There is no way to guarantee that you're not gonna read the variable that happens to be passed in via the &mut
parameter. We can wrap all variables in RefCell
, for example, and detect data races there, but then it would have negative impacts to performance.
For functions without a &mut
parameter, technically speaking you can do it, but Rhai handles both types of functions in the same way, so it is also disallowed.
Ah, yeah I see the problem, alright, I'll just have to store the state in my structs, I guess a possible solution would be having "auto-passed" arguments i.e. the function always has the first n arguments automatically pulled out of the scope by name or something, but that'd be sort of unusual
Hmm, actually constants are accessible from the native context, but there is no way to change them in between script runs, in my case the constants are "constant" per-frame, and while the script is running rather than for the entire lifetime of the script
You can set the default "tag" in the Engine
, which is available for native Rust functions. This "tag" can be changed on the Engine
at any time (e.g. between r uns).
I can't seem to be able to return Dynamic values from methods even though Union is a public type,
I think there should be a method of constructing those to be able to create more powerful functions