refactored plugin structure

- removed PluginConstructor
This commit is contained in:
Dmitry Stepanov
2024-03-17 11:45:14 +03:00
parent 14044764a3
commit bd5cc70032
14 changed files with 46 additions and 90 deletions
+5 -5
View File
@@ -1,5 +1,6 @@
//! Executor is a small wrapper that manages plugins and scripts for your game.
use crate::plugin::Plugin;
use crate::{
asset::manager::ResourceManager,
core::{
@@ -11,7 +12,6 @@ use crate::{
},
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget},
plugin::PluginConstructor,
utils::translate_event,
window::WindowAttributes,
};
@@ -124,12 +124,12 @@ impl Executor {
self.desired_update_rate
}
/// Adds new plugin constructor to the executor, the plugin will be enabled only on [`Executor::run`].
pub fn add_plugin_constructor<P>(&mut self, plugin: P)
/// Adds new plugin to the executor, the plugin will be enabled only on [`Executor::run`].
pub fn add_plugin<P>(&mut self, plugin: P)
where
P: PluginConstructor + 'static,
P: Plugin + 'static,
{
self.engine.add_plugin_constructor(plugin)
self.engine.add_plugin(plugin)
}
/// Runs the executor - starts your game.
+9 -25
View File
@@ -31,7 +31,7 @@ use crate::{
shader::{loader::ShaderLoader, Shader, ShaderResource, ShaderResourceExtension},
Material,
},
plugin::{Plugin, PluginConstructor, PluginContext, PluginRegistrationContext},
plugin::{Plugin, PluginContext, PluginRegistrationContext},
renderer::{framework::error::FrameworkError, framework::state::GlKind, Renderer},
resource::{
curve::{loader::CurveLoader, CurveResourceState},
@@ -218,23 +218,11 @@ struct SceneLoadingOptions {
/// ```rust
/// use fyrox_impl::{
/// core::{color::Color, log::Log, pool::Handle},
/// plugin::{Plugin, PluginConstructor, PluginContext},
/// plugin::{Plugin, PluginContext},
/// scene::Scene,
/// };
/// use std::path::Path;
///
/// struct GameConstructor;
///
/// impl PluginConstructor for GameConstructor {
/// fn create_instance(
/// &self,
/// scene_path: Option<&str>,
/// context: PluginContext,
/// ) -> Box<dyn Plugin> {
/// Box::new(MyGame::new(scene_path, context))
/// }
/// }
///
/// struct MyGame {
/// scene: Handle<Scene>,
/// }
@@ -433,9 +421,6 @@ pub struct Engine {
#[allow(dead_code)] // Keep engine instance alive.
sound_engine: SoundEngine,
// A set of plugin constructors.
plugin_constructors: Vec<Box<dyn PluginConstructor>>,
// A set of plugins used by the engine.
plugins: Vec<Box<dyn Plugin>>,
@@ -1288,7 +1273,6 @@ impl Engine {
serialization_context,
script_processor: Default::default(),
plugins_enabled: false,
plugin_constructors: Default::default(),
elapsed_time: 0.0,
task_pool: TaskPoolHandler::new(task_pool),
})
@@ -2266,8 +2250,8 @@ impl Engine {
if self.plugins_enabled {
// Create and initialize instances.
for constructor in self.plugin_constructors.iter() {
self.plugins.push(constructor.create_instance(
for plugin in self.plugins.iter_mut() {
plugin.init(
scene_path,
PluginContext {
scenes: &mut self.scenes,
@@ -2284,7 +2268,7 @@ impl Engine {
window_target,
task_pool: &mut self.task_pool,
},
));
);
}
} else {
self.handle_scripts(0.0);
@@ -2312,16 +2296,16 @@ impl Engine {
}
/// Adds new plugin plugin constructor.
pub fn add_plugin_constructor<P>(&mut self, constructor: P)
pub fn add_plugin<P>(&mut self, plugin: P)
where
P: PluginConstructor + 'static,
P: Plugin + 'static,
{
constructor.register(PluginRegistrationContext {
plugin.register(PluginRegistrationContext {
serialization_context: &self.serialization_context,
resource_manager: &self.resource_manager,
});
self.plugin_constructors.push(Box::new(constructor));
self.plugins.push(Box::new(plugin));
}
}
+1 -13
View File
@@ -76,20 +76,8 @@ impl TaskPoolHandler {
/// ## Example
///
/// ```rust ,no_run
/// # use fyrox_impl::plugin::{Plugin, PluginConstructor, PluginContext};
/// # use fyrox_impl::plugin::{Plugin, PluginContext};
/// # use std::{fs::File, io::Read};
/// #
/// struct MyGameConstructor;
///
/// impl PluginConstructor for MyGameConstructor {
/// fn create_instance(
/// &self,
/// _scene_path: Option<&str>,
/// context: PluginContext,
/// ) -> Box<dyn Plugin> {
/// Box::new(MyGame::new(context))
/// }
/// }
///
/// struct MyGame {
/// data: Option<Vec<u8>>,
+9 -4
View File
@@ -1,19 +1,24 @@
//! Dynamic plugins with hot-reloading ability.
use crate::plugin::PluginConstructor;
use crate::plugin::Plugin;
use std::ffi::OsStr;
/// Dynamic plugin, that is loaded from a dynamic library. Usually it is used for hot reloading,
/// it is strongly advised not to use it in production builds, because it is slower than statically
/// linked plugins and it could be unsafe if different compiler versions are used.
pub struct DynamicPlugin {
pub constructor: Box<dyn PluginConstructor>,
/// Loaded plugin.
pub plugin: Box<dyn Plugin>,
// Keep the library loaded.
// Must be last!
#[allow(dead_code)]
lib: libloading::Library,
}
pub type PluginEntryPoint = fn() -> Box<dyn PluginConstructor>;
type PluginEntryPoint = fn() -> Box<dyn Plugin>;
impl DynamicPlugin {
/// Tries to load a plugin from a dynamic library (*.dll on Windows, *.so on Unix).
pub fn load<P>(path: P) -> Result<Self, String>
where
P: AsRef<OsStr>,
@@ -26,7 +31,7 @@ impl DynamicPlugin {
.map_err(|e| e.to_string())?;
Ok(Self {
constructor: entry(),
plugin: entry(),
lib,
})
}
+15 -29
View File
@@ -4,46 +4,20 @@
pub mod dynamic;
use crate::engine::task::TaskPoolHandler;
use crate::{
asset::manager::ResourceManager,
core::pool::Handle,
core::{pool::Handle, visitor::VisitError},
engine::{
AsyncSceneLoader, GraphicsContext, PerformanceStatistics, ScriptProcessor,
SerializationContext,
task::TaskPoolHandler, AsyncSceneLoader, GraphicsContext, PerformanceStatistics,
ScriptProcessor, SerializationContext,
},
event::Event,
gui::{message::UiMessage, UserInterface},
scene::{Scene, SceneContainer},
};
use fyrox_core::visitor::VisitError;
use std::{any::Any, path::Path, sync::Arc};
use winit::event_loop::EventLoopWindowTarget;
/// Plugin constructor is a first step of 2-stage plugin initialization. It is responsible for plugin script
/// registration and for creating actual plugin instance.
///
/// # Details
///
/// Why there is a need in 2-state initialization? The editor requires it, it is interested only in plugin
/// scripts so editor does not create any plugin instances, it just uses [Self::register] to obtain information
/// about scripts.
pub trait PluginConstructor {
/// The method is called when the plugin constructor was just registered in the engine. The main use of the
/// method is to register scripts and custom scene graph nodes in [`SerializationContext`].
fn register(&self, #[allow(unused_variables)] context: PluginRegistrationContext) {}
/// The method is called when the engine creates plugin instances. It allows to create initialized plugin
/// instance.
///
/// ## Arguments
///
/// `scene_path` argument tells you that there's already a scene specified. It is used primarily
/// by the editor, to run your game with a scene you have current opened in the editor. Typical
/// usage would be: `scene_path.unwrap_or("a/path/to/my/default/scene.rgs")`
fn create_instance(&self, scene_path: Option<&str>, context: PluginContext) -> Box<dyn Plugin>;
}
/// Contains plugin environment for the registration stage.
pub struct PluginRegistrationContext<'a> {
/// A reference to serialization context of the engine. See [`SerializationContext`] for more
@@ -191,6 +165,18 @@ impl dyn Plugin {
/// }
/// ```
pub trait Plugin: BasePlugin {
/// The method is called when the plugin constructor was just registered in the engine. The main
/// use of this method is to register scripts and custom scene graph nodes in [`SerializationContext`].
fn register(&self, #[allow(unused_variables)] context: PluginRegistrationContext) {}
/// This method is used to initialize your plugin.
fn init(
&mut self,
#[allow(unused_variables)] scene_path: Option<&str>,
#[allow(unused_variables)] context: PluginContext,
) {
}
/// The method is called before plugin will be disabled. It should be used for clean up, or some
/// additional actions.
fn on_deinit(&mut self, #[allow(unused_variables)] context: PluginContext) {}
Binary file not shown.
@@ -1,55 +0,0 @@
__ROOT__[Fields=0, Children=1]:
Tree[Fields=0, Children=2]:
Nodes[Fields=0, Children=2]:
Records[Fields=1, Children=6]: Length<u32 = 6>,
Item0[Fields=0, Children=1]:
ItemData[Fields=1, Children=1]: Generation<u32 = 1>,
Payload[Fields=1, Children=1]: IsSome<u8 = 1>,
Data[Fields=1, Children=1]: Id<u32 = 1>,
0[Fields=0, Children=1]:
Child[Fields=2, Children=0]: Index<u32 = 5>, Generation<u32 = 1>,
Item1[Fields=0, Children=1]:
ItemData[Fields=1, Children=1]: Generation<u32 = 1>,
Payload[Fields=1, Children=1]: IsSome<u8 = 1>,
Data[Fields=1, Children=1]: Id<u32 = 3>,
0[Fields=0, Children=1]:
Behavior[Fields=1, Children=1]: IsSome<u8 = 1>,
Data[Fields=1, Children=0]: Id<u32 = 1>,
Item2[Fields=0, Children=1]:
ItemData[Fields=1, Children=1]: Generation<u32 = 1>,
Payload[Fields=1, Children=1]: IsSome<u8 = 1>,
Data[Fields=1, Children=1]: Id<u32 = 3>,
0[Fields=0, Children=1]:
Behavior[Fields=1, Children=1]: IsSome<u8 = 1>,
Data[Fields=1, Children=0]: Id<u32 = 2>,
Item3[Fields=0, Children=1]:
ItemData[Fields=1, Children=1]: Generation<u32 = 1>,
Payload[Fields=1, Children=1]: IsSome<u8 = 1>,
Data[Fields=1, Children=1]: Id<u32 = 3>,
0[Fields=0, Children=1]:
Behavior[Fields=1, Children=1]: IsSome<u8 = 1>,
Data[Fields=1, Children=0]: Id<u32 = 3>,
Item4[Fields=0, Children=1]:
ItemData[Fields=1, Children=1]: Generation<u32 = 1>,
Payload[Fields=1, Children=1]: IsSome<u8 = 1>,
Data[Fields=1, Children=1]: Id<u32 = 3>,
0[Fields=0, Children=1]:
Behavior[Fields=1, Children=1]: IsSome<u8 = 1>,
Data[Fields=1, Children=0]: Id<u32 = 4>,
Item5[Fields=0, Children=1]:
ItemData[Fields=1, Children=1]: Generation<u32 = 1>,
Payload[Fields=1, Children=1]: IsSome<u8 = 1>,
Data[Fields=1, Children=1]: Id<u32 = 2>,
0[Fields=0, Children=2]:
Children[Fields=1, Children=4]: Length<u32 = 4>,
Item0[Fields=0, Children=1]:
ItemData[Fields=2, Children=0]: Index<u32 = 1>, Generation<u32 = 1>,
Item1[Fields=0, Children=1]:
ItemData[Fields=2, Children=0]: Index<u32 = 2>, Generation<u32 = 1>,
Item2[Fields=0, Children=1]:
ItemData[Fields=2, Children=0]: Index<u32 = 3>, Generation<u32 = 1>,
Item3[Fields=0, Children=1]:
ItemData[Fields=2, Children=0]: Index<u32 = 4>, Generation<u32 = 1>,
Kind[Fields=1, Children=0]: Id<u32 = 0>,
FreeStack[Fields=1, Children=0]: Length<u32 = 0>,
Root[Fields=2, Children=0]: Index<u32 = 0>, Generation<u32 = 1>,
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.