Skip to content

Commit 66d24fc

Browse files
committed
initial rhai work
1 parent c71fa0a commit 66d24fc

File tree

10 files changed

+171
-195
lines changed

10 files changed

+171
-195
lines changed

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ mlua_macros = ["bevy_mod_scripting_lua/mlua_macros"]
4444
mlua_async = ["bevy_mod_scripting_lua/mlua_async"]
4545

4646
## rhai
47-
# rhai = ["bevy_mod_scripting_rhai"]
47+
rhai = ["bevy_mod_scripting_rhai"]
4848

4949
## rune
5050
# rune = ["bevy_mod_scripting_rune"]
@@ -53,7 +53,7 @@ mlua_async = ["bevy_mod_scripting_lua/mlua_async"]
5353
bevy = { workspace = true }
5454
bevy_mod_scripting_core = { workspace = true }
5555
bevy_mod_scripting_lua = { path = "crates/languages/bevy_mod_scripting_lua", version = "0.9.0-alpha.7", optional = true }
56-
# bevy_mod_scripting_rhai = { path = "crates/languages/bevy_mod_scripting_rhai", version = "0.9.0-alpha.2", optional = true }
56+
bevy_mod_scripting_rhai = { path = "crates/languages/bevy_mod_scripting_rhai", version = "0.9.0-alpha.2", optional = true }
5757
# bevy_mod_scripting_rune = { path = "crates/languages/bevy_mod_scripting_rune", version = "0.9.0-alpha.2", optional = true }
5858
bevy_mod_scripting_functions = { workspace = true }
5959

@@ -62,7 +62,7 @@ bevy = { version = "0.15.0", default-features = false }
6262
bevy_mod_scripting_core = { path = "crates/bevy_mod_scripting_core", version = "0.9.0-alpha.7" }
6363
bevy_mod_scripting_functions = { path = "crates/bevy_mod_scripting_functions", version = "0.9.0-alpha.7", default-features = false }
6464
mlua = { version = "0.10" }
65-
# rhai = { version = "1.20.1" }
65+
rhai = { git = "https://github.com/rhaiscript/rhai", rev = "4ead53eb40f4a18d6f827609041ef1c742f04799" }
6666

6767
# test utilities
6868
script_integration_test_harness = { path = "crates/script_integration_test_harness" }
@@ -80,7 +80,7 @@ ansi-parser = "0.9"
8080
members = [
8181
"crates/bevy_mod_scripting_core",
8282
"crates/languages/bevy_mod_scripting_lua",
83-
# "crates/languages/bevy_mod_scripting_rhai",
83+
"crates/languages/bevy_mod_scripting_rhai",
8484
# "crates/languages/bevy_mod_scripting_rune",
8585
"crates/test_utils",
8686
"crates/bevy_mod_scripting_functions",

crates/bevy_mod_scripting_core/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ doc_always = []
2121

2222
# if enabled enables some common mlua trait implementations
2323
mlua_impls = ["mlua"]
24-
# rhai_impls = ["rhai"]
24+
rhai_impls = ["rhai"]
2525

2626
[dependencies]
2727
mlua = { optional = true, workspace = true }
28-
# rhai = { optional = true, workspace = true }
28+
rhai = { optional = true, workspace = true }
2929

3030
bevy = { workspace = true, default-features = false, features = [
3131
"bevy_asset",

crates/bevy_mod_scripting_core/src/error.rs

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -101,21 +101,21 @@ impl ScriptError {
101101
}
102102
}
103103

104-
// #[cfg(feature = "rhai_impls")]
105-
// pub fn from_rhai_error(error: rhai::EvalAltResult) -> Self {
106-
// match error {
107-
// rhai::EvalAltResult::ErrorSystem(message, error) => {
108-
// if let Some(inner) = error.downcast_ref::<InteropError>() {
109-
// Self::new(inner.clone())
110-
// } else if let Some(inner) = error.downcast_ref::<ScriptError>() {
111-
// inner.clone()
112-
// } else {
113-
// Self::new_external_boxed(error).with_context(message)
114-
// }
115-
// }
116-
// _ => Self::new_external(error),
117-
// }
118-
// }
104+
#[cfg(feature = "rhai_impls")]
105+
pub fn from_rhai_error(error: rhai::EvalAltResult) -> Self {
106+
match error {
107+
rhai::EvalAltResult::ErrorSystem(message, error) => {
108+
if let Some(inner) = error.downcast_ref::<InteropError>() {
109+
Self::new(inner.clone())
110+
} else if let Some(inner) = error.downcast_ref::<ScriptError>() {
111+
inner.clone()
112+
} else {
113+
Self::new_external_boxed(error).with_context(message)
114+
}
115+
}
116+
_ => Self::new_external(error),
117+
}
118+
}
119119

120120
pub fn new_external(reason: impl std::error::Error + Send + Sync + 'static) -> Self {
121121
Self::new_external_boxed(Box::new(reason))
@@ -211,39 +211,39 @@ impl From<mlua::Error> for ScriptError {
211211
}
212212
}
213213

214-
// #[cfg(feature = "rhai_impls")]
215-
// impl From<rhai::ParseError> for ScriptError {
216-
// fn from(value: rhai::ParseError) -> Self {
217-
// ScriptError::new_external(value)
218-
// }
219-
// }
220-
221-
// #[cfg(feature = "rhai_impls")]
222-
// impl From<Box<rhai::EvalAltResult>> for ScriptError {
223-
// fn from(value: Box<rhai::EvalAltResult>) -> Self {
224-
// ScriptError::from_rhai_error(*value)
225-
// }
226-
// }
227-
228-
// #[cfg(feature = "rhai_impls")]
229-
// impl From<ScriptError> for Box<rhai::EvalAltResult> {
230-
// fn from(value: ScriptError) -> Self {
231-
// Box::new(rhai::EvalAltResult::ErrorSystem(
232-
// "ScriptError".to_owned(),
233-
// Box::new(value),
234-
// ))
235-
// }
236-
// }
237-
238-
// #[cfg(feature = "rhai_impls")]
239-
// impl From<InteropError> for Box<rhai::EvalAltResult> {
240-
// fn from(value: InteropError) -> Self {
241-
// Box::new(rhai::EvalAltResult::ErrorSystem(
242-
// "InteropError".to_owned(),
243-
// Box::new(value),
244-
// ))
245-
// }
246-
// }
214+
#[cfg(feature = "rhai_impls")]
215+
impl From<rhai::ParseError> for ScriptError {
216+
fn from(value: rhai::ParseError) -> Self {
217+
ScriptError::new_external(value)
218+
}
219+
}
220+
221+
#[cfg(feature = "rhai_impls")]
222+
impl From<Box<rhai::EvalAltResult>> for ScriptError {
223+
fn from(value: Box<rhai::EvalAltResult>) -> Self {
224+
ScriptError::from_rhai_error(*value)
225+
}
226+
}
227+
228+
#[cfg(feature = "rhai_impls")]
229+
impl From<ScriptError> for Box<rhai::EvalAltResult> {
230+
fn from(value: ScriptError) -> Self {
231+
Box::new(rhai::EvalAltResult::ErrorSystem(
232+
"ScriptError".to_owned(),
233+
Box::new(value),
234+
))
235+
}
236+
}
237+
238+
#[cfg(feature = "rhai_impls")]
239+
impl From<InteropError> for Box<rhai::EvalAltResult> {
240+
fn from(value: InteropError) -> Self {
241+
Box::new(rhai::EvalAltResult::ErrorSystem(
242+
"InteropError".to_owned(),
243+
Box::new(value),
244+
))
245+
}
246+
}
247247

248248
#[derive(Clone, Debug, PartialEq)]
249249
pub struct MissingResourceError(&'static str);

crates/languages/bevy_mod_scripting_rhai/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bevy_mod_scripting_rhai"
3-
version = "0.9.0-alpha.2"
3+
version = "0.9.0-alpha.7"
44
authors = ["Maksymilian Mozolewski <makspl17@gmail.com>"]
55
edition = "2021"
66
license = "MIT OR Apache-2.0"

crates/languages/bevy_mod_scripting_rhai/src/bindings/reference.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::script_value::{FromDynamic, RHAI_CALLER_CONTEXT};
1+
use super::script_value::{FromDynamic, IntoDynamic, RHAI_CALLER_CONTEXT};
22
use bevy_mod_scripting_core::{
33
bindings::{
44
pretty_print::DisplayWithWorld, script_value::ScriptValue, ReflectReference,
@@ -53,7 +53,7 @@ impl CustomType for RhaiReflectReference {
5353
builder
5454
.with_name(std::any::type_name::<ReflectReference>())
5555
.with_indexer_get(|self_: &mut Self, _index: Dynamic| {
56-
let world = ThreadWorldContainer.get_world();
56+
let world = ThreadWorldContainer.try_get_world()?;
5757
let self_ = &self_.0;
5858
let type_id = self_.tail_type_id(world.clone())?.or_fake_id();
5959

@@ -63,7 +63,7 @@ impl CustomType for RhaiReflectReference {
6363
match world
6464
.lookup_function([type_id, TypeId::of::<ReflectReference>()], string)
6565
{
66-
Ok(func) => return Ok(Dynamic::from(func)),
66+
Ok(func) => return ScriptValue::Function(func).into_dynamic(),
6767
Err(string) => ScriptValue::String(string),
6868
}
6969
}
@@ -72,11 +72,10 @@ impl CustomType for RhaiReflectReference {
7272

7373
let func = world
7474
.lookup_function([type_id, TypeId::of::<ReflectReference>()], "get")
75-
.expect("No 'get' function registered for ReflectReference");
75+
.map_err(|_| InteropError::missing_function(type_id, "get".to_owned()))?;
7676

7777
let out = func.call(
7878
vec![ScriptValue::Reference(self_.clone()), key],
79-
world,
8079
RHAI_CALLER_CONTEXT,
8180
)?;
8281

@@ -93,13 +92,13 @@ impl CustomType for RhaiStaticReflectReference {
9392
builder
9493
.with_name(std::any::type_name::<RhaiStaticReflectReference>())
9594
.with_indexer_get(|self_: &mut Self, index: Dynamic| {
96-
let world = ThreadWorldContainer.get_world();
95+
let world = ThreadWorldContainer.try_get_world()?;
9796
let type_id = self_.0;
9897
let key: ScriptValue = ScriptValue::from_dynamic(index)?;
9998

10099
let key = match key.as_string() {
101100
Ok(name) => match world.lookup_function([type_id], name) {
102-
Ok(func) => return Ok(Dynamic::from(func)),
101+
Ok(func) => return ScriptValue::Function(func).into_dynamic(),
103102
Err(key) => ScriptValue::String(key),
104103
},
105104
Err(key) => key,

crates/languages/bevy_mod_scripting_rhai/src/bindings/script_value.rs

Lines changed: 52 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,16 @@
1-
use std::{str::FromStr, sync::Arc};
2-
31
use bevy_mod_scripting_core::{
4-
bindings::{
5-
function::script_function::{
6-
CallerContext, DynamicScriptFunction, DynamicScriptFunctionMut,
7-
},
8-
script_value::ScriptValue,
9-
},
2+
bindings::{function::script_function::FunctionCallContext, script_value::ScriptValue},
103
error::InteropError,
114
};
12-
use rhai::{
13-
plugin::{PluginFunc, RhaiFunc},
14-
Dynamic, EvalAltResult, FnPtr, RhaiNativeFunc,
15-
};
5+
use rhai::{Dynamic, EvalAltResult, FnPtr, NativeCallContext};
6+
use std::str::FromStr;
7+
8+
use super::reference::RhaiReflectReference;
169

17-
pub const RHAI_CALLER_CONTEXT: CallerContext = CallerContext {
10+
pub const RHAI_CALLER_CONTEXT: FunctionCallContext = FunctionCallContext {
1811
convert_to_0_indexed: false,
1912
};
2013

21-
#[allow(dead_code)]
22-
struct FuncWrapper(DynamicScriptFunction);
23-
24-
#[allow(dead_code)]
25-
struct FuncMutWrapper(DynamicScriptFunctionMut);
26-
27-
impl RhaiNativeFunc for FuncWrapper {
28-
fn into_rhai_function(self, is_pure: bool, is_volatile: bool) -> RhaiFunc {
29-
todo!()
30-
}
31-
32-
fn param_types() -> [std::any::TypeId; N] {
33-
todo!()
34-
}
35-
}
36-
3714
// impl PluginFunc for FuncWrapper {
3815
// fn call(
3916
// &self,
@@ -95,30 +72,11 @@ impl RhaiNativeFunc for FuncWrapper {
9572
// }
9673
// }
9774

98-
#[allow(dead_code)]
99-
pub(crate) fn to_rhai_fn(func: DynamicScriptFunction) -> RhaiFunc {
100-
RhaiFunc::Plugin {
101-
func: Arc::new(FuncWrapper(func)),
102-
}
103-
.into()
104-
// FnPtr {
105-
// name: todo!(),
106-
// curry: todo!(),
107-
// environ: todo!(),
108-
// fn_def: todo!(),
109-
// }
110-
}
111-
112-
pub(crate) fn to_rhai_fn_mut(func: DynamicScriptFunctionMut) -> RhaiFunc {
113-
RhaiFunc::Plugin {
114-
func: Arc::new(FuncMutWrapper(func)),
115-
}
116-
}
117-
11875
pub trait IntoDynamic {
11976
fn into_dynamic(self) -> Result<Dynamic, Box<EvalAltResult>>;
12077
}
12178

79+
#[allow(clippy::todo)]
12280
impl IntoDynamic for ScriptValue {
12381
fn into_dynamic(self) -> Result<Dynamic, Box<EvalAltResult>> {
12482
Ok(match self {
@@ -137,11 +95,43 @@ impl IntoDynamic for ScriptValue {
13795
.into(),
13896
)
13997
})?,
140-
ScriptValue::List(_vec) => todo!(),
141-
ScriptValue::Reference(_reflect_reference) => todo!(),
142-
ScriptValue::FunctionMut(func) => Dynamic::from(to_rhai_fn_mut(func)),
143-
ScriptValue::Function(func) => Dynamic::from(to_rhai_fn(func)),
144-
ScriptValue::Error(_interop_error) => todo!(),
98+
ScriptValue::List(_vec) => todo!("vec is not implemented yet"),
99+
ScriptValue::Reference(reflect_reference) => {
100+
Dynamic::from(RhaiReflectReference(reflect_reference))
101+
}
102+
ScriptValue::FunctionMut(func) => Dynamic::from(FnPtr::from_fn(
103+
func.name().to_string(),
104+
move |_ctxt: NativeCallContext, args: &mut [&mut Dynamic]| {
105+
let convert_args = args
106+
.iter_mut()
107+
.map(|arg| ScriptValue::from_dynamic(arg.clone()))
108+
.collect::<Result<Vec<_>, _>>()?;
109+
110+
let out = func.call(convert_args, RHAI_CALLER_CONTEXT)?;
111+
112+
out.into_dynamic()
113+
},
114+
)?),
115+
ScriptValue::Function(func) => Dynamic::from(FnPtr::from_fn(
116+
func.name().to_string(),
117+
move |_ctxt: NativeCallContext, args: &mut [&mut Dynamic]| {
118+
let convert_args = args
119+
.iter_mut()
120+
.map(|arg| ScriptValue::from_dynamic(arg.clone()))
121+
.collect::<Result<Vec<_>, _>>()?;
122+
123+
let out = func.call(convert_args, RHAI_CALLER_CONTEXT)?;
124+
125+
out.into_dynamic()
126+
},
127+
)?),
128+
ScriptValue::Error(interop_error) => {
129+
return Err(EvalAltResult::ErrorSystem(
130+
"Interop error in rhai script".to_string(),
131+
interop_error.into(),
132+
)
133+
.into())
134+
}
145135
})
146136
}
147137
}
@@ -150,6 +140,7 @@ pub trait FromDynamic: Sized {
150140
fn from_dynamic(dynamic: Dynamic) -> Result<Self, Box<EvalAltResult>>;
151141
}
152142

143+
#[allow(clippy::unwrap_used, clippy::todo)]
153144
impl FromDynamic for ScriptValue {
154145
fn from_dynamic(dynamic: Dynamic) -> Result<Self, Box<EvalAltResult>> {
155146
match dynamic {
@@ -160,7 +151,13 @@ impl FromDynamic for ScriptValue {
160151
d if d.is_string() => Ok(ScriptValue::String(
161152
d.into_immutable_string().unwrap().to_string().into(),
162153
)),
163-
_ => todo!(),
154+
d => {
155+
if let Some(v) = d.try_cast::<RhaiReflectReference>() {
156+
Ok(ScriptValue::Reference(v.0))
157+
} else {
158+
todo!("from conversion not implemented yet")
159+
}
160+
}
164161
}
165162
}
166163
}

0 commit comments

Comments
 (0)