Skip to content

Commit be48926

Browse files
authored
feat: add script asset path to function call context (#493)
1 parent aef9c2a commit be48926

File tree

8 files changed

+70
-30
lines changed

8 files changed

+70
-30
lines changed

crates/bevy_mod_scripting_bindings/src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ impl DisplayWithTypeInfo for InteropError {
577577
} => {
578578
write!(
579579
f,
580-
"Error {} in function {} on {}: {}",
580+
"Error {}\n in function {} on {}:\n {}",
581581
context
582582
.clone()
583583
.unwrap_or(FunctionCallContext::new(Language::Unknown)),

crates/bevy_mod_scripting_bindings/src/function/script_function.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,18 @@ impl std::fmt::Display for FunctionCallContext {
5353
f.write_str("in language: ")?;
5454
self.language.fmt(f)?;
5555
if let Some(context) = &self.location_context {
56+
if let Some(script_name) = &context.script_name {
57+
f.write_str(", in script: ")?;
58+
script_name.fmt(f)?;
59+
}
60+
5661
f.write_str(", at line: ")?;
5762
context.line.fmt(f)?;
58-
f.write_str(", at column: ")?;
59-
context.col.fmt(f)?;
63+
64+
if let Some(col) = &context.col {
65+
f.write_str(", at column: ")?;
66+
col.fmt(f)?;
67+
}
6068
}
6169
Ok(())
6270
}
@@ -66,10 +74,12 @@ impl std::fmt::Display for FunctionCallContext {
6674
#[debug_with_type_info(bms_display_path = "bevy_mod_scripting_display")]
6775
/// Describes a location within a script
6876
pub struct LocationContext {
77+
/// The name of the script the function call originates from
78+
pub script_name: Option<String>,
6979
/// The line number
7080
pub line: u32,
7181
/// The column number
72-
pub col: u32,
82+
pub col: Option<u32>,
7383
}
7484

7585
impl FunctionCallContext {

crates/bevy_mod_scripting_core/src/pipeline/machines.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,10 @@ impl<P: IntoScriptPluginParams> ScriptMachine<P> {
229229
match &mut self.internal_state {
230230
MachineExecutionState::Initialized(machine_state) => {
231231
debug!(
232-
"State '{}' entered. For script: {}",
232+
"State '{}' entered. For script: {}, {:?}",
233233
machine_state.state_name(),
234-
self.context.attachment
234+
self.context.attachment,
235+
self.context.attachment.script(),
235236
);
236237

237238
if let Some(listeners) = listeners.get(&machine_state.as_ref().type_id()) {
@@ -517,7 +518,8 @@ impl<P: IntoScriptPluginParams> MachineState<P> for ContextAssigned<P> {
517518
let contexts = world.get_resource_or_init::<ScriptContext<P>>();
518519
let mut contexts_guard = contexts.write();
519520

520-
match contexts_guard.insert(attachment.clone(), self.context.clone()) {
521+
// drop any strong handles
522+
match contexts_guard.insert(attachment.clone().into_weak(), self.context.clone()) {
521523
Ok(_) => {}
522524
Err(_) => {
523525
drop(contexts_guard);

crates/bevy_mod_scripting_core/src/pipeline/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use crate::{
2929
OnLoadedListener, OnReloadedListener, OnUnloadedForReloadListener,
3030
OnUnloadedForUnloadListener,
3131
},
32-
script::{ScriptContext, ScriptId},
32+
script::ScriptContext,
3333
};
3434

3535
mod hooks;

crates/bevy_mod_scripting_core/src/pipeline/start.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,10 @@ impl StrongScriptHandle {
3838
handle: Handle<ScriptAsset>,
3939
assets: &mut Assets<ScriptAsset>,
4040
) -> Option<Self> {
41-
assets.get_strong_handle(handle.id()).map(Self)
42-
}
43-
44-
/// Upgrades an asset Id pointing to a script to a strong handle if the asset hasn't been dropped
45-
pub fn upgrade(id: ScriptId, assets: &mut Assets<ScriptAsset>) -> Option<Self> {
46-
assets.get_strong_handle(id).map(Self)
41+
match handle {
42+
s @ Handle::Strong(_) => Some(Self(s)),
43+
_ => assets.get_strong_handle(handle.id()).map(Self),
44+
}
4745
}
4846

4947
/// Returns a reference to the strong handle inside
@@ -122,12 +120,14 @@ pub fn process_attachments<P: IntoScriptPluginParams>(
122120
let contexts = contexts.read();
123121
events.read().for_each(|wrapper| {
124122
let attachment_event = wrapper.event();
125-
let id = attachment_event.0.script().id();
126-
let context = Context {
123+
let id = attachment_event.0.script();
124+
let mut context = Context {
127125
attachment: attachment_event.0.clone(),
128126
blackboard: Default::default(),
129127
};
130-
if let Some(strong_handle) = StrongScriptHandle::upgrade(id, &mut assets) {
128+
if let Some(strong_handle) = StrongScriptHandle::from_assets(id, &mut assets) {
129+
// we want the loading process to have access to asset paths, we will weaken the handle at the end.
130+
*context.attachment.script_mut() = strong_handle.0.clone();
131131
let content = strong_handle.get(&assets);
132132
if let Some(existing_context) = contexts.get_context(&attachment_event.0) {
133133
machines.queue_machine(
@@ -193,8 +193,8 @@ pub fn process_asset_modifications<P: IntoScriptPluginParams>(
193193
affected_attachments
194194
.into_iter()
195195
.for_each(|(attachment, existing_context)| {
196-
let id = attachment.script().id();
197-
if let Some(strong_handle) = StrongScriptHandle::upgrade(id, &mut assets) {
196+
let id = attachment.script();
197+
if let Some(strong_handle) = StrongScriptHandle::from_assets(id, &mut assets) {
198198
let content = strong_handle.get(&assets);
199199
machines.queue_machine(
200200
Context {

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

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use bevy_mod_scripting_bindings::{
1111
use bevy_platform::collections::HashMap;
1212
use mlua::{FromLua, IntoLua, Value, Variadic};
1313

14-
use crate::IntoMluaError;
14+
use crate::{IntoMluaError, LuaContextAppData};
1515

1616
use super::reference::LuaReflectReference;
1717

@@ -142,10 +142,16 @@ impl IntoLua for LuaScriptValue {
142142
ScriptValue::Error(script_error) => return Err(mlua::Error::external(script_error)),
143143
ScriptValue::Function(function) => lua
144144
.create_function(move |lua, args: Variadic<LuaScriptValue>| {
145-
let loc = lua.inspect_stack(1).map(|debug| LocationContext {
146-
line: debug.curr_line().try_into().unwrap_or_default(),
147-
col: 0,
148-
});
145+
let loc = {
146+
profiling::scope!("function call context");
147+
lua.inspect_stack(1).map(|debug| LocationContext {
148+
line: debug.curr_line().try_into().unwrap_or_default(),
149+
col: None,
150+
script_name: lua.app_data_ref::<LuaContextAppData>().and_then(|v| {
151+
v.last_loaded_script_name.as_ref().map(|n| n.to_string())
152+
}),
153+
})
154+
};
149155
let out = function
150156
.call(
151157
args.into_iter().map(Into::into),
@@ -158,10 +164,16 @@ impl IntoLua for LuaScriptValue {
158164
.into_lua(lua)?,
159165
ScriptValue::FunctionMut(function) => lua
160166
.create_function(move |lua, args: Variadic<LuaScriptValue>| {
161-
let loc = lua.inspect_stack(0).map(|debug| LocationContext {
162-
line: debug.curr_line() as u32,
163-
col: 0,
164-
});
167+
let loc = {
168+
profiling::scope!("function call context");
169+
lua.inspect_stack(1).map(|debug| LocationContext {
170+
line: debug.curr_line().try_into().unwrap_or_default(),
171+
col: None,
172+
script_name: lua.app_data_ref::<LuaContextAppData>().and_then(|v| {
173+
v.last_loaded_script_name.as_ref().map(|n| n.to_string())
174+
}),
175+
})
176+
};
165177
let out = function
166178
.call(
167179
args.into_iter().map(Into::into),

crates/languages/bevy_mod_scripting_lua/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use ::{
1010
bevy_ecs::{entity::Entity, world::World},
1111
};
1212
use bevy_app::App;
13+
use bevy_asset::AssetPath;
1314
use bevy_ecs::world::{Mut, WorldId};
1415
use bevy_log::trace;
1516
use bevy_mod_scripting_asset::{Language, ScriptAsset};
@@ -275,6 +276,13 @@ fn load_lua_content_into_context(
275276
Ok(())
276277
}
277278

279+
/// App data which can be retrieved via [`mlua::Lua::app_data_ref`], containing some metadata about scripts present
280+
#[derive(Default, Debug)]
281+
pub struct LuaContextAppData {
282+
/// the asset path of the script loaded last if this is a shared context, or the only script if it's not.
283+
pub last_loaded_script_name: Option<AssetPath<'static>>,
284+
}
285+
278286
#[profiling::function]
279287
/// Load a lua context from a script
280288
pub fn lua_context_load(
@@ -287,6 +295,10 @@ pub fn lua_context_load(
287295
#[cfg(not(feature = "unsafe_lua_modules"))]
288296
let mut context = LuaContext(Lua::new());
289297

298+
context.set_app_data(LuaContextAppData {
299+
last_loaded_script_name: context_key.script().path().cloned(),
300+
});
301+
290302
load_lua_content_into_context(&mut context, context_key, content, world_id)?;
291303
Ok(context)
292304
}

crates/testing_crates/script_integration_test_harness/src/scenario.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use bevy_mod_scripting_core::{
3232
handler::event_handler,
3333
script::{ContextPolicy, ScriptComponent, ScriptContext},
3434
};
35+
use bevy_mod_scripting_display::DisplayProxy;
3536
use bevy_mod_scripting_script::ScriptAttachment;
3637
use test_utils::test_data::setup_integration_test;
3738

@@ -593,7 +594,7 @@ impl ScenarioStep {
593594
return Err(anyhow!("Failed to load script: {e}"));
594595
}
595596

596-
info!("Script '{}' loaded successfully", script.id());
597+
info!("Script '{}' loaded successfully", script.display());
597598
}
598599
ScenarioStep::SetupHandler { schedule, label } => {
599600
match label.to_string().as_str() {
@@ -629,7 +630,10 @@ impl ScenarioStep {
629630
.id();
630631

631632
context.entities.insert(name.to_string(), entity);
632-
info!("Spawned entity '{entity}' with script '{}'", script.id());
633+
info!(
634+
"Spawned entity '{entity}' with script '{}'",
635+
script.display()
636+
);
633637
}
634638
ScenarioStep::EmitScriptCallbackEvent { event } => {
635639
app.world_mut().send_event(event.clone());

0 commit comments

Comments
 (0)