diff --git a/fyrox-impl/src/engine/mod.rs b/fyrox-impl/src/engine/mod.rs index 9359f6561..650974c13 100644 --- a/fyrox-impl/src/engine/mod.rs +++ b/fyrox-impl/src/engine/mod.rs @@ -31,10 +31,6 @@ pub mod task; mod hotreload; mod wasm_utils; -use crate::engine::input::InputState; -use crate::renderer::ui_renderer::UiRenderInfo; -use crate::resource::gltf::material::GLTF_SHADER; -use crate::scene::skybox::SkyBoxKind; use crate::{ asset::{ event::ResourceEvent, @@ -44,6 +40,7 @@ use crate::{ }, core::{ algebra::Vector2, + err, futures::{executor::block_on, future::join_all}, instant, log::Log, @@ -51,18 +48,21 @@ use crate::{ reflect::Reflect, task::TaskPool, variable::try_inherit_properties, - SafeLock, + visitor::error::VisitError, + warn, SafeLock, }, - engine::{error::EngineError, task::TaskPoolHandler}, + engine::{error::EngineError, input::InputState, task::TaskPoolHandler}, event::Event, graph::{BaseSceneGraph, NodeMapping, SceneGraph}, graphics::error::FrameworkError, gui::{ constructor::WidgetConstructorContainer, - font::{loader::FontLoader, Font, BUILT_IN_FONT}, + font::{ + loader::FontLoader, Font, BOLD_ITALIC, BUILT_IN_BOLD, BUILT_IN_FONT, BUILT_IN_ITALIC, + }, loader::UserInterfaceLoader, style::{self, resource::StyleLoader, Style}, - UiContainer, UiUpdateSwitches, UserInterface, + RenderMode, UiContainer, UiUpdateSwitches, UserInterface, }, material::{ self, @@ -74,9 +74,10 @@ use crate::{ dylib::DyLibDynamicPlugin, DynamicPlugin, Plugin, PluginContainer, PluginContext, PluginRegistrationContext, }, - renderer::Renderer, + renderer::{ui_renderer::UiRenderInfo, Renderer}, resource::{ curve::{loader::CurveLoader, CurveResourceState}, + gltf::material::GLTF_SHADER, model::{loader::ModelLoader, Model, ModelResource}, texture::{ self, loader::TextureLoader, CompressionOptions, Texture, TextureImportOptions, @@ -92,6 +93,7 @@ use crate::{ constructor::{new_node_constructor_container, NodeConstructorContainer}, Node, }, + skybox::SkyBoxKind, sound::SoundEngine, tilemap::{ brush::{TileMapBrush, TileMapBrushLoader}, @@ -100,6 +102,7 @@ use crate::{ }, Scene, SceneContainer, SceneLoader, }, + script::ScriptResult, script::{ constructor::ScriptConstructorContainer, DynamicTypeId, PluginsRefMut, RoutingStrategy, Script, ScriptContext, ScriptDeinitContext, ScriptMessage, ScriptMessageContext, @@ -109,16 +112,12 @@ use crate::{ }; use fxhash::{FxHashMap, FxHashSet}; use fyrox_animation::AnimationTracksData; -use fyrox_core::visitor::error::VisitError; -use fyrox_core::warn; use fyrox_graphics::server::SharedGraphicsServer; use fyrox_graphics_gl::server::GlGraphicsServer; use fyrox_sound::{ buffer::{loader::SoundBufferLoader, SoundBuffer}, renderer::hrtf::{HrirSphereLoader, HrirSphereResourceData}, }; -use fyrox_ui::font::{BOLD_ITALIC, BUILT_IN_BOLD, BUILT_IN_ITALIC}; -use fyrox_ui::RenderMode; use std::{ any::TypeId, cell::Cell, @@ -634,7 +633,7 @@ impl ScriptMessageDispatcher { input_state, }; - process_node_scripts(&mut context, &mut |s, ctx| { + process_node_scripts("on_message", &mut context, &mut |s, ctx| { s.on_message(&mut *payload, ctx) }) } @@ -662,9 +661,11 @@ impl ScriptMessageDispatcher { }; if receivers.contains(&node) { - process_node_scripts(&mut context, &mut |s, ctx| { - s.on_message(&mut *payload, ctx) - }); + process_node_scripts( + "on_message", + &mut context, + &mut |s, ctx| s.on_message(&mut *payload, ctx), + ); } node = parent; @@ -689,9 +690,11 @@ impl ScriptMessageDispatcher { }; if receivers.contains(&node) { - process_node_scripts(&mut context, &mut |s, ctx| { - s.on_message(&mut *payload, ctx) - }); + process_node_scripts( + "on_message", + &mut context, + &mut |s, ctx| s.on_message(&mut *payload, ctx), + ); } } } @@ -714,7 +717,7 @@ impl ScriptMessageDispatcher { input_state, }; - process_node_scripts(&mut context, &mut |s, ctx| { + process_node_scripts("on_message", &mut context, &mut |s, ctx| { s.on_message(&mut *payload, ctx) }); } @@ -864,16 +867,19 @@ impl ScriptProcessor { context.script_index = script_index; process_node_script( + "on_init", script_index, &mut context, &mut |script, context| { if !script.initialized { - script.on_init(context); + script.on_init(context)?; script.initialized = true; } // `on_start` must be called even if the script was initialized. start_queue.push_back((handle, script_index)); + + Ok(()) }, ); } @@ -900,14 +906,17 @@ impl ScriptProcessor { context.script_index = script_index; process_node_script( + "on_start", script_index, &mut context, &mut |script, context| { if script.initialized && !script.started { - script.on_start(context); + let result = script.on_start(context); script.started = true; - update_queue.push_back((handle, script_index)); + result + } else { + Ok(()) } }, ); @@ -930,9 +939,12 @@ impl ScriptProcessor { context.handle = handle; context.script_index = script_index; - process_node_script(script_index, &mut context, &mut |script, context| { - script.on_update(context); - }); + process_node_script( + "on_update", + script_index, + &mut context, + &mut |script, context| script.on_update(context), + ); } } @@ -986,7 +998,9 @@ impl ScriptProcessor { // `on_deinit` could also spawn new nodes, but we won't take those into account on // this frame. They'll be correctly handled on next frame. - script.on_deinit(&mut context); + if let Err(error) = script.on_deinit(&mut context) { + err!("An error occurred during on_deinit call. Reason: {error}"); + } } } @@ -1013,9 +1027,11 @@ impl ScriptProcessor { let handle_node = context.scene.graph.handle_from_index(node_index); context.node_handle = handle_node; - process_node_scripts(&mut context, &mut |script, context| { + process_node_scripts("on_deinit", &mut context, &mut |script, context| { if script.initialized { script.on_deinit(context) + } else { + Ok(()) } }); } @@ -1183,9 +1199,9 @@ pub struct EngineInitParams { pub task_pool: Arc, } -fn process_node_script(index: usize, context: &mut C, func: &mut T) -> bool +fn process_node_script(caller_name: &str, index: usize, context: &mut C, func: &mut T) -> bool where - T: FnMut(&mut Script, &mut C), + T: FnMut(&mut Script, &mut C) -> ScriptResult, C: UniversalScriptContext, { let Ok(node) = context.node() else { @@ -1206,7 +1222,9 @@ where return false; }; - func(&mut script, context); + if let Err(error) = func(&mut script, context) { + err!("An error occurred during {caller_name} call. Reason: {error}"); + } match context.node() { Ok(node) => { @@ -1232,16 +1250,16 @@ where true } -fn process_node_scripts(context: &mut C, func: &mut T) +fn process_node_scripts(caller_name: &str, context: &mut C, func: &mut T) where - T: FnMut(&mut Script, &mut C), + T: FnMut(&mut Script, &mut C) -> ScriptResult, C: UniversalScriptContext, { let mut index = 0; loop { context.set_script_index(index); - if !process_node_script(index, context, func) { + if !process_node_script(caller_name, index, context, func) { return; } @@ -1251,6 +1269,7 @@ where } pub(crate) fn process_scripts( + caller_name: &str, scene: &mut Scene, scene_handle: Handle, plugins: &mut [PluginContainer], @@ -1265,7 +1284,7 @@ pub(crate) fn process_scripts( input_state: &InputState, mut func: T, ) where - T: FnMut(&mut Script, &mut ScriptContext), + T: FnMut(&mut Script, &mut ScriptContext) -> ScriptResult, { let mut context = ScriptContext { dt, @@ -1287,7 +1306,7 @@ pub(crate) fn process_scripts( for node_index in 0..context.scene.graph.capacity() { context.handle = context.scene.graph.handle_from_index(node_index); - process_node_scripts(&mut context, &mut func); + process_node_scripts(caller_name, &mut context, &mut func); } } @@ -2407,6 +2426,7 @@ impl Engine { let scene = &mut self.scenes[scene_handle]; if *scene.enabled { process_scripts( + "on_os_event", scene, scene_handle, &mut self.plugins, @@ -2421,7 +2441,9 @@ impl Engine { &self.input_state, |script, context| { if script.initialized && script.started { - script.on_os_event(event, context); + script.on_os_event(event, context) + } else { + Ok(()) } }, ) @@ -2932,6 +2954,7 @@ impl Drop for Engine { #[cfg(test)] mod test { use crate::engine::ApplicationLoopController; + use crate::script::ScriptResult; use crate::{ asset::manager::ResourceManager, core::{ @@ -3003,7 +3026,7 @@ mod test { } impl ScriptTrait for MyScript { - fn on_init(&mut self, ctx: &mut ScriptContext) { + fn on_init(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Initialized(Source::from_ctx(ctx))) .unwrap(); @@ -3014,9 +3037,11 @@ mod test { })) .build(&mut ctx.scene.graph); assert_eq!(handle, Handle::new(2, 1)); + + Ok(()) } - fn on_start(&mut self, ctx: &mut ScriptContext) { + fn on_start(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Started(Source::from_ctx(ctx))) .unwrap(); @@ -3027,15 +3052,19 @@ mod test { })) .build(&mut ctx.scene.graph); assert_eq!(handle, Handle::new(3, 1)); + + Ok(()) } - fn on_deinit(&mut self, ctx: &mut ScriptDeinitContext) { + fn on_deinit(&mut self, ctx: &mut ScriptDeinitContext) -> ScriptResult { self.sender .send(Event::Destroyed(Source::from_deinit_ctx(ctx))) .unwrap(); + + Ok(()) } - fn on_update(&mut self, ctx: &mut ScriptContext) { + fn on_update(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Updated(Source::from_ctx(ctx))) .unwrap(); @@ -3049,6 +3078,8 @@ mod test { self.spawned = true; } + + Ok(()) } } @@ -3061,28 +3092,32 @@ mod test { } impl ScriptTrait for MySubScript { - fn on_init(&mut self, ctx: &mut ScriptContext) { + fn on_init(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Initialized(Source::from_ctx(ctx))) .unwrap(); + Ok(()) } - fn on_start(&mut self, ctx: &mut ScriptContext) { + fn on_start(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Started(Source::from_ctx(ctx))) .unwrap(); + Ok(()) } - fn on_deinit(&mut self, ctx: &mut ScriptDeinitContext) { + fn on_deinit(&mut self, ctx: &mut ScriptDeinitContext) -> ScriptResult { self.sender .send(Event::Destroyed(Source::from_deinit_ctx(ctx))) .unwrap(); + Ok(()) } - fn on_update(&mut self, ctx: &mut ScriptContext) { + fn on_update(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Updated(Source::from_ctx(ctx))) .unwrap(); + Ok(()) } } @@ -3215,15 +3250,16 @@ mod test { } impl ScriptTrait for ScriptListeningToMessages { - fn on_start(&mut self, ctx: &mut ScriptContext) { + fn on_start(&mut self, ctx: &mut ScriptContext) -> ScriptResult { ctx.message_dispatcher.subscribe_to::(ctx.handle); + Ok(()) } fn on_message( &mut self, message: &mut dyn ScriptMessagePayload, ctx: &mut ScriptMessageContext, - ) { + ) -> ScriptResult { let typed_message = message.downcast_ref::().unwrap(); match self.index { 0 => { @@ -3250,6 +3286,8 @@ mod test { } self.index += 1; + + Ok(()) } } @@ -3260,7 +3298,7 @@ mod test { } impl ScriptTrait for ScriptSendingMessages { - fn on_update(&mut self, ctx: &mut ScriptContext) { + fn on_update(&mut self, ctx: &mut ScriptContext) -> ScriptResult { match self.index { 0 => ctx.message_sender.send_global(MyMessage::Foo(123)), 1 => ctx @@ -3269,6 +3307,8 @@ mod test { _ => (), } self.index += 1; + + Ok(()) } } @@ -3345,7 +3385,7 @@ mod test { } impl ScriptTrait for ScriptSpawningAsyncTasks { - fn on_start(&mut self, ctx: &mut ScriptContext) { + fn on_start(&mut self, ctx: &mut ScriptContext) -> ScriptResult { ctx.task_pool.spawn_script_task( ctx.scene_handle, ctx.handle, @@ -3355,7 +3395,8 @@ mod test { assert_eq!(result, 123u32); script.num = Some(result); }, - ) + ); + Ok(()) } } @@ -3444,31 +3485,35 @@ mod test { } impl ScriptTrait for ScriptThatDeletesItself { - fn on_init(&mut self, ctx: &mut ScriptContext) { + fn on_init(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Initialized(Source::from_ctx(ctx))) .unwrap(); + Ok(()) } - fn on_start(&mut self, ctx: &mut ScriptContext) { + fn on_start(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Started(Source::from_ctx(ctx))) .unwrap(); + Ok(()) } - fn on_deinit(&mut self, ctx: &mut ScriptDeinitContext) { + fn on_deinit(&mut self, ctx: &mut ScriptDeinitContext) -> ScriptResult { self.sender .send(Event::Destroyed(Source::from_deinit_ctx(ctx))) .unwrap(); + Ok(()) } - fn on_update(&mut self, ctx: &mut ScriptContext) { + fn on_update(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Updated(Source::from_ctx(ctx))) .unwrap(); let node = &mut ctx.scene.graph[ctx.handle]; node.remove_script(ctx.script_index); + Ok(()) } } @@ -3482,13 +3527,14 @@ mod test { } impl ScriptTrait for ScriptThatAddsScripts { - fn on_init(&mut self, ctx: &mut ScriptContext) { + fn on_init(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Initialized(Source::from_ctx(ctx))) .unwrap(); + Ok(()) } - fn on_start(&mut self, ctx: &mut ScriptContext) { + fn on_start(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Started(Source::from_ctx(ctx))) .unwrap(); @@ -3499,18 +3545,24 @@ mod test { sender: self.sender.clone(), }); } + + Ok(()) } - fn on_deinit(&mut self, ctx: &mut ScriptDeinitContext) { + fn on_deinit(&mut self, ctx: &mut ScriptDeinitContext) -> ScriptResult { self.sender .send(Event::Destroyed(Source::from_deinit_ctx(ctx))) .unwrap(); + + Ok(()) } - fn on_update(&mut self, ctx: &mut ScriptContext) { + fn on_update(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Updated(Source::from_ctx(ctx))) .unwrap(); + + Ok(()) } } @@ -3524,28 +3576,32 @@ mod test { } impl ScriptTrait for SimpleScript { - fn on_init(&mut self, ctx: &mut ScriptContext) { + fn on_init(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Initialized(Source::from_ctx(ctx))) .unwrap(); + Ok(()) } - fn on_start(&mut self, ctx: &mut ScriptContext) { + fn on_start(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Started(Source::from_ctx(ctx))) .unwrap(); + Ok(()) } - fn on_deinit(&mut self, ctx: &mut ScriptDeinitContext) { + fn on_deinit(&mut self, ctx: &mut ScriptDeinitContext) -> ScriptResult { self.sender .send(Event::Destroyed(Source::from_deinit_ctx(ctx))) .unwrap(); + Ok(()) } - fn on_update(&mut self, ctx: &mut ScriptContext) { + fn on_update(&mut self, ctx: &mut ScriptContext) -> ScriptResult { self.sender .send(Event::Updated(Source::from_ctx(ctx))) .unwrap(); + Ok(()) } } diff --git a/fyrox-impl/src/engine/task.rs b/fyrox-impl/src/engine/task.rs index ee8b572da..34b923b8d 100644 --- a/fyrox-impl/src/engine/task.rs +++ b/fyrox-impl/src/engine/task.rs @@ -176,6 +176,7 @@ impl TaskPoolHandler { /// # script::{ScriptContext, ScriptTrait}, /// # }; /// # use fyrox_core::uuid_provider; + /// # use fyrox_impl::script::ScriptResult; /// # /// #[derive(Reflect, Visit, Default, Debug, Clone)] /// struct MyScript; @@ -184,7 +185,7 @@ impl TaskPoolHandler { /// # uuid_provider!(MyScript = "f5ded79e-6101-4e23-b20d-48cbdb25d87a"); /// /// impl ScriptTrait for MyScript { - /// fn on_start(&mut self, ctx: &mut ScriptContext) { + /// fn on_start(&mut self, ctx: &mut ScriptContext) -> ScriptResult { /// ctx.task_pool.spawn_script_task( /// ctx.scene_handle, /// ctx.handle, @@ -204,6 +205,7 @@ impl TaskPoolHandler { /// } /// }, /// ); + /// Ok(()) /// } /// } /// ``` diff --git a/fyrox-impl/src/script/mod.rs b/fyrox-impl/src/script/mod.rs index 7aee6e026..13b854bc1 100644 --- a/fyrox-impl/src/script/mod.rs +++ b/fyrox-impl/src/script/mod.rs @@ -22,35 +22,33 @@ //! Script is used to add custom logic to scene nodes. See [ScriptTrait] for more info. -use crate::engine::input::InputState; use crate::{ asset::manager::ResourceManager, core::{ log::Log, - pool::Handle, - reflect::{FieldRef, Reflect, ReflectArray, ReflectList}, + pool::{Handle, PoolError}, + reflect::{FieldMut, FieldRef, Reflect, ReflectArray, ReflectList}, type_traits::ComponentProvider, uuid::Uuid, visitor::{Visit, VisitResult, Visitor}, TypeUuidProvider, }, - engine::{task::TaskPoolHandler, GraphicsContext, ScriptMessageDispatcher}, + engine::{input::InputState, task::TaskPoolHandler, GraphicsContext, ScriptMessageDispatcher}, event::Event, gui::UiContainer, plugin::{Plugin, PluginContainer}, - scene::{base::NodeScriptMessage, node::Node, Scene}, + scene::{base::NodeScriptMessage, graph::GraphError, node::Node, Scene}, }; -use fyrox_core::pool::PoolError; -use fyrox_core::reflect::FieldMut; pub use fyrox_core_derive::ScriptMessagePayload; use fyrox_graph::BaseSceneGraph; use std::{ any::{Any, TypeId}, - fmt::{Debug, Formatter}, + fmt::{Debug, Display, Formatter}, ops::{Deref, DerefMut}, str::FromStr, sync::mpsc::Sender, }; + pub mod constructor; pub(crate) trait UniversalScriptContext { @@ -336,7 +334,7 @@ pub struct ScriptContext<'a, 'b, 'c> { /// # use fyrox_impl::{ /// # core::{reflect::prelude::*, type_traits::prelude::*, visitor::prelude::*}, /// # plugin::Plugin, - /// # script::{ScriptContext, ScriptTrait}, + /// # script::{ScriptContext, ScriptTrait, ScriptResult}, /// # }; /// # /// #[derive(Visit, Reflect, Default, Debug)] @@ -352,10 +350,12 @@ pub struct ScriptContext<'a, 'b, 'c> { /// struct MyScript {} /// /// impl ScriptTrait for MyScript { - /// fn on_update(&mut self, ctx: &mut ScriptContext) { + /// fn on_update(&mut self, ctx: &mut ScriptContext) -> ScriptResult { /// let game = ctx.plugins.get::(); /// /// println!("Player name is: {}", game.player_name); + /// + /// Ok(()) /// } /// } /// ``` @@ -598,6 +598,58 @@ impl UniversalScriptContext for ScriptDeinitContext<'_, '_, '_> { } } +pub type AnyScriptError = Box; + +pub enum ScriptError { + GraphError(GraphError), + PoolError(PoolError), + AnyError(AnyScriptError), +} + +impl From for ScriptError { + fn from(value: GraphError) -> Self { + Self::GraphError(value) + } +} + +impl From for ScriptError { + fn from(value: PoolError) -> Self { + Self::PoolError(value) + } +} + +impl From for ScriptError { + fn from(value: AnyScriptError) -> Self { + Self::AnyError(value) + } +} + +impl std::error::Error for ScriptError {} + +impl Display for ScriptError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + ScriptError::GraphError(err) => { + write!(f, "{}", err) + } + ScriptError::PoolError(err) => { + write!(f, "{}", err) + } + ScriptError::AnyError(err) => { + write!(f, "{}", err) + } + } + } +} + +impl Debug for ScriptError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self) + } +} + +pub type ScriptResult = Result<(), ScriptError>; + /// Script is a set predefined methods that are called on various stages by the engine. It is used to add /// custom behaviour to game entities. pub trait ScriptTrait: BaseScript + ComponentProvider { @@ -610,16 +662,25 @@ pub trait ScriptTrait: BaseScript + ComponentProvider { /// loaded the instance. Internal flag will tell the engine that the script is initialized and this /// method **will not** be called. This is intentional design decision to be able to create save files /// in games. If you need a method that will be called in any case, use [`ScriptTrait::on_start`]. - fn on_init(&mut self, #[allow(unused_variables)] ctx: &mut ScriptContext) {} + fn on_init(&mut self, #[allow(unused_variables)] ctx: &mut ScriptContext) -> ScriptResult { + Ok(()) + } /// The method is called after [`ScriptTrait::on_init`], but in separate pass, which means that all /// script instances are already initialized. However, if implementor of this method creates a new /// node with a script, there will be a second pass of initialization. The method is guaranteed to /// be called once. - fn on_start(&mut self, #[allow(unused_variables)] ctx: &mut ScriptContext) {} + fn on_start(&mut self, #[allow(unused_variables)] ctx: &mut ScriptContext) -> ScriptResult { + Ok(()) + } /// The method is called when the script is about to be destroyed. It is guaranteed to be called last. - fn on_deinit(&mut self, #[allow(unused_variables)] ctx: &mut ScriptDeinitContext) {} + fn on_deinit( + &mut self, + #[allow(unused_variables)] ctx: &mut ScriptDeinitContext, + ) -> ScriptResult { + Ok(()) + } /// Called when there is an event from the OS. The method allows you to "listen" for events /// coming from the main window of your game. It could be used to react to pressed keys, mouse movements, @@ -628,13 +689,16 @@ pub trait ScriptTrait: BaseScript + ComponentProvider { &mut self, #[allow(unused_variables)] event: &Event<()>, #[allow(unused_variables)] ctx: &mut ScriptContext, - ) { + ) -> ScriptResult { + Ok(()) } /// Performs a single update tick of the script. The method may be called multiple times per frame, but it is guaranteed /// that the rate of call is stable and by default it will be called 60 times per second, but can be changed by using /// [`crate::engine::executor::Executor::set_desired_update_rate`] method. - fn on_update(&mut self, #[allow(unused_variables)] ctx: &mut ScriptContext) {} + fn on_update(&mut self, #[allow(unused_variables)] ctx: &mut ScriptContext) -> ScriptResult { + Ok(()) + } /// Allows you to react to certain script messages. It could be used for communication between scripts; to /// bypass borrowing issues. If you need to receive messages of a particular type, you must subscribe to a type @@ -645,7 +709,7 @@ pub trait ScriptTrait: BaseScript + ComponentProvider { /// core::{reflect::prelude::*, uuid::Uuid, visitor::prelude::*, type_traits::prelude::*}, /// core::TypeUuidProvider, /// script::ScriptTrait, - /// script::{ScriptContext, ScriptMessageContext, ScriptMessagePayload}, + /// script::{ScriptContext, ScriptMessageContext, ScriptResult, ScriptMessagePayload}, /// }; /// /// struct Message; @@ -660,19 +724,21 @@ pub trait ScriptTrait: BaseScript + ComponentProvider { /// # } /// /// impl ScriptTrait for MyScript { - /// fn on_start(&mut self, ctx: &mut ScriptContext) { + /// fn on_start(&mut self, ctx: &mut ScriptContext) -> ScriptResult { /// // Subscription is mandatory to receive any message of the type! - /// ctx.message_dispatcher.subscribe_to::(ctx.handle) + /// ctx.message_dispatcher.subscribe_to::(ctx.handle); + /// Ok(()) /// } /// /// fn on_message( /// &mut self, /// message: &mut dyn ScriptMessagePayload, /// ctx: &mut ScriptMessageContext, - /// ) { + /// ) -> ScriptResult { /// if let Some(message) = message.downcast_ref::() { /// // Do something. /// } + /// Ok(()) /// } /// } /// ``` @@ -680,7 +746,8 @@ pub trait ScriptTrait: BaseScript + ComponentProvider { &mut self, #[allow(unused_variables)] message: &mut dyn ScriptMessagePayload, #[allow(unused_variables)] ctx: &mut ScriptMessageContext, - ) { + ) -> ScriptResult { + Ok(()) } } diff --git a/fyrox-scripts/src/camera.rs b/fyrox-scripts/src/camera.rs index d843e8501..ca5545fec 100644 --- a/fyrox-scripts/src/camera.rs +++ b/fyrox-scripts/src/camera.rs @@ -21,6 +21,8 @@ //! Flying camera controller script is used to create flying cameras, that can be rotated via mouse and moved via keyboard keys. //! See [`FlyingCameraController`] docs for more info and usage examples. +use fyrox::graph::BaseSceneGraph; +use fyrox::script::ScriptResult; use fyrox::{ core::{ algebra::{UnitQuaternion, UnitVector3, Vector3}, @@ -203,7 +205,7 @@ impl_component_provider!(FlyingCameraController); uuid_provider!(FlyingCameraController = "8d9e2feb-8c61-482c-8ba4-b0b13b201113"); impl ScriptTrait for FlyingCameraController { - fn on_os_event(&mut self, event: &Event<()>, context: &mut ScriptContext) { + fn on_os_event(&mut self, event: &Event<()>, context: &mut ScriptContext) -> ScriptResult { match event { Event::WindowEvent { event: WindowEvent::KeyboardInput { event, .. }, @@ -234,12 +236,14 @@ impl ScriptTrait for FlyingCameraController { } _ => {} } + + Ok(()) } - fn on_update(&mut self, context: &mut ScriptContext) { + fn on_update(&mut self, context: &mut ScriptContext) -> ScriptResult { let mut new_velocity = Vector3::default(); - let this = &mut context.scene.graph[context.handle]; + let this = context.scene.graph.try_get_node_mut(context.handle)?; if self.move_forward { new_velocity += this.look_vector(); @@ -290,5 +294,7 @@ impl ScriptTrait for FlyingCameraController { ) * yaw, ) .offset(*self.velocity); + + Ok(()) } }