Skip to content

Commit 1cac0aa

Browse files
committed
make the generics more tenable, and update docs
1 parent 5734de1 commit 1cac0aa

File tree

14 files changed

+279
-229
lines changed

14 files changed

+279
-229
lines changed

crates/bevy_mod_scripting_core/src/commands.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ use crate::{
88
prelude::{Runtime, RuntimeContainer},
99
script::{Script, ScriptId, Scripts},
1010
systems::handle_script_errors,
11+
IntoScriptPluginParams,
1112
};
1213

13-
pub struct DeleteScript<C: Context, R: Runtime> {
14+
pub struct DeleteScript<P: IntoScriptPluginParams> {
1415
pub id: ScriptId,
1516
// hack to make this Send, C does not need to be Send since it is not stored in the command
16-
pub _ph: PhantomData<fn(C, R)>,
17+
pub _ph: PhantomData<fn(P::C, P::R)>,
1718
}
1819

19-
impl<C: Context, R: Runtime> DeleteScript<C, R> {
20+
impl<P: IntoScriptPluginParams> DeleteScript<P> {
2021
pub fn new(id: ScriptId) -> Self {
2122
Self {
2223
id,
@@ -25,17 +26,17 @@ impl<C: Context, R: Runtime> DeleteScript<C, R> {
2526
}
2627
}
2728

28-
impl<C: Context, R: Runtime> Command for DeleteScript<C, R> {
29+
impl<P: IntoScriptPluginParams> Command for DeleteScript<P> {
2930
fn apply(self, world: &mut bevy::prelude::World) {
3031
let settings = world
31-
.get_resource::<ContextLoadingSettings<C, R>>()
32+
.get_resource::<ContextLoadingSettings<P>>()
3233
.expect("No ScriptLoadingSettings resource found")
3334
.clone();
3435

3536
world.resource_scope(|world, mut scripts: Mut<Scripts>| {
3637
if let Some(script) = scripts.scripts.remove(&self.id) {
3738
debug!("Deleting script with id: {}", self.id);
38-
let mut ctxts = world.get_non_send_resource_mut::<ScriptContexts<C>>();
39+
let mut ctxts = world.get_non_send_resource_mut::<ScriptContexts<P>>();
3940
let ctxts = ctxts.as_deref_mut().unwrap();
4041
let assigner = settings
4142
.assigner
@@ -58,15 +59,15 @@ impl<C: Context, R: Runtime> Command for DeleteScript<C, R> {
5859
/// Creates new script with the given ID, if a script with the given ID already exists, this is treated as an update
5960
///
6061
/// If script comes from an asset, expects it to be loaded, otherwise this command will fail to process the script.
61-
pub struct CreateOrUpdateScript<C: Context, R: Runtime> {
62+
pub struct CreateOrUpdateScript<P: IntoScriptPluginParams> {
6263
id: ScriptId,
6364
content: Box<[u8]>,
6465
asset: Option<Handle<ScriptAsset>>,
6566
// Hack to make this Send, C does not need to be Send since it is not stored in the command
66-
_ph: std::marker::PhantomData<fn(R, C)>,
67+
_ph: std::marker::PhantomData<fn(P::R, P::C)>,
6768
}
6869

69-
impl<C: Context, R: Runtime> CreateOrUpdateScript<C, R> {
70+
impl<P: IntoScriptPluginParams> CreateOrUpdateScript<P> {
7071
pub fn new(id: ScriptId, content: Box<[u8]>, asset: Option<Handle<ScriptAsset>>) -> Self {
7172
Self {
7273
id,
@@ -77,17 +78,17 @@ impl<C: Context, R: Runtime> CreateOrUpdateScript<C, R> {
7778
}
7879
}
7980

80-
impl<C: Context, R: Runtime> Command for CreateOrUpdateScript<C, R> {
81+
impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
8182
fn apply(self, world: &mut bevy::prelude::World) {
8283
let settings = world
83-
.get_resource::<ContextLoadingSettings<C, R>>()
84+
.get_resource::<ContextLoadingSettings<P>>()
8485
.unwrap()
8586
.clone();
8687
let mut contexts = world
87-
.remove_non_send_resource::<ScriptContexts<C>>()
88+
.remove_non_send_resource::<ScriptContexts<P>>()
8889
.unwrap();
8990
let mut runtime = world
90-
.remove_non_send_resource::<RuntimeContainer<R>>()
91+
.remove_non_send_resource::<RuntimeContainer<P>>()
9192
.unwrap();
9293
// assign context
9394
let assigner = settings.assigner.clone().expect("No context assigner set");
@@ -116,7 +117,7 @@ impl<C: Context, R: Runtime> Command for CreateOrUpdateScript<C, R> {
116117
match ctxt {
117118
Ok(ctxt) => contexts.insert(ctxt),
118119
Err(e) => {
119-
handle_script_errors(world, [e.with_context(format!("Loading context for script with id: {}. With runtime type: {} and context type: {}", self.id, type_name::<R>(), type_name::<C>()))].into_iter());
120+
handle_script_errors(world, [e.with_context(format!("Loading context for script with id: {}. With runtime type: {} and context type: {}", self.id, type_name::<P::R>(), type_name::<P::C>()))].into_iter());
120121
return;
121122
}
122123
}

crates/bevy_mod_scripting_core/src/context.rs

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use bevy::ecs::{entity::Entity, system::Resource, world::World};
55
use crate::{
66
prelude::{Runtime, ScriptError},
77
script::{Script, ScriptId},
8+
IntoScriptPluginParams,
89
};
910

1011
pub trait Context: 'static {}
@@ -13,11 +14,11 @@ impl<T: 'static> Context for T {}
1314
pub type ContextId = u32;
1415

1516
#[derive(Resource)]
16-
pub struct ScriptContexts<T: Context> {
17-
pub(crate) contexts: HashMap<ContextId, T>,
17+
pub struct ScriptContexts<P: IntoScriptPluginParams> {
18+
pub(crate) contexts: HashMap<ContextId, P::C>,
1819
}
1920

20-
impl<T: Context> Default for ScriptContexts<T> {
21+
impl<P: IntoScriptPluginParams> Default for ScriptContexts<P> {
2122
fn default() -> Self {
2223
Self {
2324
contexts: Default::default(),
@@ -26,15 +27,15 @@ impl<T: Context> Default for ScriptContexts<T> {
2627
}
2728

2829
static CONTEXT_ID_COUNTER: AtomicU32 = AtomicU32::new(0);
29-
impl<T: Context> ScriptContexts<T> {
30+
impl<P: IntoScriptPluginParams> ScriptContexts<P> {
3031
pub fn new() -> Self {
3132
Self {
3233
contexts: HashMap::new(),
3334
}
3435
}
3536

3637
/// Allocates a new ContextId and inserts the context into the map
37-
pub fn insert(&mut self, ctxt: T) -> ContextId {
38+
pub fn insert(&mut self, ctxt: P::C) -> ContextId {
3839
let id = CONTEXT_ID_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
3940
self.contexts.insert(id, ctxt);
4041
id
@@ -45,26 +46,27 @@ impl<T: Context> ScriptContexts<T> {
4546
CONTEXT_ID_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
4647
}
4748

48-
pub fn remove(&mut self, id: ContextId) -> Option<T> {
49+
pub fn remove(&mut self, id: ContextId) -> Option<P::C> {
4950
self.contexts.remove(&id)
5051
}
5152
}
5253

5354
/// Initializer run once after creating a context but before executing it for the first time
54-
pub type ContextInitializer<C> = fn(&ScriptId, &mut C) -> Result<(), ScriptError>;
55+
pub type ContextInitializer<P: IntoScriptPluginParams> =
56+
fn(&ScriptId, &mut P::C) -> Result<(), ScriptError>;
5557
/// Initializer run every time before executing or loading a script
56-
pub type ContextPreHandlingInitializer<C> =
57-
fn(&ScriptId, Entity, &mut C) -> Result<(), ScriptError>;
58+
pub type ContextPreHandlingInitializer<P: IntoScriptPluginParams> =
59+
fn(&ScriptId, Entity, &mut P::C) -> Result<(), ScriptError>;
5860

5961
#[derive(Resource)]
60-
pub struct ContextLoadingSettings<C: Context, R: Runtime> {
61-
pub loader: Option<ContextBuilder<C, R>>,
62-
pub assigner: Option<ContextAssigner<C>>,
63-
pub context_initializers: Vec<ContextInitializer<C>>,
64-
pub context_pre_handling_initializers: Vec<ContextPreHandlingInitializer<C>>,
62+
pub struct ContextLoadingSettings<P: IntoScriptPluginParams> {
63+
pub loader: Option<ContextBuilder<P>>,
64+
pub assigner: Option<ContextAssigner<P>>,
65+
pub context_initializers: Vec<ContextInitializer<P>>,
66+
pub context_pre_handling_initializers: Vec<ContextPreHandlingInitializer<P>>,
6567
}
6668

67-
impl<C: Context, R: Runtime> Default for ContextLoadingSettings<C, R> {
69+
impl<P: IntoScriptPluginParams> Default for ContextLoadingSettings<P> {
6870
fn default() -> Self {
6971
Self {
7072
loader: None,
@@ -75,7 +77,7 @@ impl<C: Context, R: Runtime> Default for ContextLoadingSettings<C, R> {
7577
}
7678
}
7779

78-
impl<C: Context, R: Runtime> Clone for ContextLoadingSettings<C, R> {
80+
impl<P: IntoScriptPluginParams> Clone for ContextLoadingSettings<P> {
7981
fn clone(&self) -> Self {
8082
Self {
8183
loader: self.loader.clone(),
@@ -87,27 +89,27 @@ impl<C: Context, R: Runtime> Clone for ContextLoadingSettings<C, R> {
8789
}
8890

8991
/// A strategy for loading and reloading contexts
90-
pub struct ContextBuilder<C: Context, R: Runtime> {
92+
pub struct ContextBuilder<P: IntoScriptPluginParams> {
9193
pub load: fn(
9294
script: &ScriptId,
9395
content: &[u8],
94-
&[ContextInitializer<C>],
95-
&[ContextPreHandlingInitializer<C>],
96+
&[ContextInitializer<P>],
97+
&[ContextPreHandlingInitializer<P>],
9698
&mut World,
97-
runtime: &mut R,
98-
) -> Result<C, ScriptError>,
99+
runtime: &mut P::R,
100+
) -> Result<P::C, ScriptError>,
99101
pub reload: fn(
100102
script: &ScriptId,
101103
new_content: &[u8],
102-
context: &mut C,
103-
&[ContextInitializer<C>],
104-
&[ContextPreHandlingInitializer<C>],
104+
context: &mut P::C,
105+
&[ContextInitializer<P>],
106+
&[ContextPreHandlingInitializer<P>],
105107
&mut World,
106-
&mut R,
108+
&mut P::R,
107109
) -> Result<(), ScriptError>,
108110
}
109111

110-
impl<C: Context, R: Runtime> Clone for ContextBuilder<C, R> {
112+
impl<P: IntoScriptPluginParams> Clone for ContextBuilder<P> {
111113
fn clone(&self) -> Self {
112114
Self {
113115
load: self.load,
@@ -117,23 +119,23 @@ impl<C: Context, R: Runtime> Clone for ContextBuilder<C, R> {
117119
}
118120

119121
/// A strategy for assigning contexts to new and existing but re-loaded scripts as well as for managing old contexts
120-
pub struct ContextAssigner<C: Context> {
122+
pub struct ContextAssigner<P: IntoScriptPluginParams> {
121123
/// Assign a context to the script, if script is `None`, this is a new script, otherwise it is an existing script with a context inside `contexts`.
122124
/// Returning None means the script should be assigned a new context
123125
pub assign: fn(
124126
old_script: Option<&Script>,
125127
script_id: &ScriptId,
126128
new_content: &[u8],
127-
contexts: &ScriptContexts<C>,
129+
contexts: &ScriptContexts<P>,
128130
) -> Option<ContextId>,
129131

130132
/// Handle the removal of the script, if any clean up in contexts is necessary perform it here.
131133
/// This will also be called, when a script is assigned a contextId on reload different from the previous one
132134
/// the context_id in that case will be the old context_id and the one stored in the script will be the old one
133-
pub remove: fn(context_id: ContextId, script: &Script, contexts: &mut ScriptContexts<C>),
135+
pub remove: fn(context_id: ContextId, script: &Script, contexts: &mut ScriptContexts<P>),
134136
}
135137

136-
impl<C: Context> Default for ContextAssigner<C> {
138+
impl<P: IntoScriptPluginParams> Default for ContextAssigner<P> {
137139
fn default() -> Self {
138140
Self {
139141
assign: |old, _, _, _| old.map(|s| s.context_id),
@@ -142,7 +144,7 @@ impl<C: Context> Default for ContextAssigner<C> {
142144
}
143145
}
144146

145-
impl<C: Context> Clone for ContextAssigner<C> {
147+
impl<P: IntoScriptPluginParams> Clone for ContextAssigner<P> {
146148
fn clone(&self) -> Self {
147149
Self {
148150
assign: self.assign,

crates/bevy_mod_scripting_core/src/event.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,29 +53,34 @@ impl CallbackLabel {
5353
#[macro_export]
5454
macro_rules! callback_labels {
5555
($($name:ident => $label:expr),*) => {
56-
pub enum CallbackLabels {
57-
$($name),*
58-
}
5956

60-
impl IntoCallbackLabel for CallbackLabels {
61-
fn into_callback_label() -> CallbackLabel {
62-
match self {
63-
$(CallbackLabels::$name => $label.into()),*
57+
$(
58+
pub struct $name;
59+
impl IntoCallbackLabel for $name {
60+
fn into_callback_label() -> CallbackLabel {
61+
$label.into()
6462
}
6563
}
66-
}
64+
)*
6765
};
6866
}
6967

7068
pub trait IntoCallbackLabel {
7169
fn into_callback_label() -> CallbackLabel;
7270
}
7371

72+
impl<T: IntoCallbackLabel> From<T> for CallbackLabel {
73+
fn from(_: T) -> Self {
74+
T::into_callback_label()
75+
}
76+
}
77+
7478
impl From<&str> for CallbackLabel {
7579
fn from(s: &str) -> Self {
7680
Self::new_lossy(s)
7781
}
7882
}
83+
7984
impl From<String> for CallbackLabel {
8085
fn from(s: String) -> Self {
8186
Self::from(s.as_str())

crates/bevy_mod_scripting_core/src/handler.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,30 @@ use crate::{
66
prelude::{ScriptError, ScriptValue},
77
runtime::Runtime,
88
script::ScriptId,
9+
IntoScriptPluginParams,
910
};
1011

1112
pub trait Args: Clone + Send + Sync + 'static {}
1213
impl<T: Clone + Send + Sync + 'static> Args for T {}
1314

14-
pub type HandlerFn<C, R> = fn(
15+
pub type HandlerFn<P: IntoScriptPluginParams> = fn(
1516
args: Vec<ScriptValue>,
1617
entity: Entity,
1718
script_id: &ScriptId,
1819
callback: &CallbackLabel,
19-
context: &mut C,
20-
pre_handling_initializers: &[ContextPreHandlingInitializer<C>],
21-
runtime: &mut R,
20+
context: &mut P::C,
21+
pre_handling_initializers: &[ContextPreHandlingInitializer<P>],
22+
runtime: &mut P::R,
2223
world: &mut World,
2324
) -> Result<(), ScriptError>;
2425

2526
/// A resource that holds the settings for the callback handler for a specific combination of type parameters
2627
#[derive(Resource)]
27-
pub struct CallbackSettings<C: Context, R: Runtime> {
28-
pub callback_handler: Option<HandlerFn<C, R>>,
28+
pub struct CallbackSettings<P: IntoScriptPluginParams> {
29+
pub callback_handler: Option<HandlerFn<P>>,
2930
}
3031

31-
impl<C: Context, R: Runtime> Default for CallbackSettings<C, R> {
32+
impl<P: IntoScriptPluginParams> Default for CallbackSettings<P> {
3233
fn default() -> Self {
3334
Self {
3435
callback_handler: None,

0 commit comments

Comments
 (0)