Skip to content

Commit

Permalink
deploy: 40e7cca
Browse files Browse the repository at this point in the history
  • Loading branch information
mrDIMAS committed Oct 19, 2023
1 parent 23fc342 commit 99e9ba3
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 130 deletions.
12 changes: 9 additions & 3 deletions fyrox/editor/property_editors.html
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ <h3 id="enumerations"><a class="header" href="#enumerations">Enumerations</a></h
following example shows a typical usage:</p>
<pre><pre class="playground"><code class="language-rust no_run"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span><span class="boring">extern crate fyrox;
</span><span class="boring">extern crate strum_macros;
</span><span class="boring">extern crate strum;
</span>use fyrox::{
core::reflect::prelude::*,
gui::inspector::editors::{
Expand All @@ -247,8 +250,10 @@ <h3 id="enumerations"><a class="header" href="#enumerations">Enumerations</a></h
</span><span class="boring"> property_editors: PropertyEditorDefinitionContainer,
</span><span class="boring">}
</span>
#[derive(Reflect, Debug, AsRefStr, EnumString, EnumVariantNames, Clone)]
#[derive(Reflect, Default, Debug, AsRefStr, EnumString, EnumVariantNames, Clone)]
enum MyEnum {
#[default]
Baz,
Foo(u32),
Bar { baz: String, foobar: u32 },
}
Expand All @@ -267,6 +272,7 @@ <h3 id="inheritable-properties"><a class="header" href="#inheritable-properties"
this fact requires you to register an appropriate property editor for this:</p>
<pre><pre class="playground"><code class="language-rust no_run"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span><span class="boring">extern crate fyrox;
</span>use fyrox::{
core::{reflect::prelude::*, variable::InheritableVariable},
gui::inspector::editors::{
Expand Down Expand Up @@ -317,7 +323,7 @@ <h3 id="inheritable-properties"><a class="header" href="#inheritable-properties"
<h3 id="collections"><a class="header" href="#collections">Collections</a></h3>
<p>If you have a vector of some custom structure (<code>Vec&lt;MyStruct&gt;</code>), then you also need to register a property editor for
it:</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
<pre><pre class="playground"><code class="language-rust no_run"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span><span class="boring">extern crate fyrox;
</span>use fyrox::{
Expand All @@ -336,7 +342,7 @@ <h3 id="collections"><a class="header" href="#collections">Collections</a></h3>
</span><span class="boring"> property_editors: PropertyEditorDefinitionContainer,
</span><span class="boring">}
</span>
#[derive(Reflect, Debug)]
#[derive(Reflect, Clone, Debug, Default)]
struct MyStruct {
foo: u32,
bar: String,
Expand Down
2 changes: 1 addition & 1 deletion fyrox/resources/custom.html
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ <h2 id="example"><a class="header" href="#example">Example</a></h2>
<span class="boring">
</span><span class="boring"> fn create_instance(
</span><span class="boring"> &amp;self,
</span><span class="boring"> override_scene: Handle&lt;Scene&gt;,
</span><span class="boring"> scene_path: Option&lt;&amp;str&gt;,
</span><span class="boring"> context: PluginContext,
</span><span class="boring"> ) -&gt; Box&lt;dyn Plugin&gt; {
</span><span class="boring"> todo!()
Expand Down
4 changes: 2 additions & 2 deletions fyrox/scripting/executor.html
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ <h1 id="executor"><a class="header" href="#executor">Executor</a></h1>
<p>Executor is a simple wrapper that drives your game plugins, it is intended to be used for production builds of your game.
The editor runs the executor in separate process when you're entering the play mode. Basically, there is no significant
difference between running the game from the editor, or running it as a separate application. The main difference is that
the editor passes <code>override_scene</code> parameter for the executor when entering the play mode.</p>
the editor passes <code>scene_path</code> parameter for the executor when entering the play mode.</p>
<h2 id="usage"><a class="header" href="#usage">Usage</a></h2>
<p>Executor is meant to be a part of your project's workspace, its typical look could something like this:</p>
<pre><pre class="playground"><code class="language-rust no_run"><span class="boring">extern crate fyrox;
Expand All @@ -192,7 +192,7 @@ <h2 id="usage"><a class="header" href="#usage">Usage</a></h2>
</span><span class="boring">impl PluginConstructor for GameConstructor {
</span><span class="boring"> fn create_instance(
</span><span class="boring"> &amp;self,
</span><span class="boring"> _override_scene: Handle&lt;Scene&gt;,
</span><span class="boring"> _scene_path: Option&lt;&amp;str&gt;,
</span><span class="boring"> _context: PluginContext,
</span><span class="boring"> ) -&gt; Box&lt;dyn Plugin&gt; {
</span><span class="boring"> todo!()
Expand Down
130 changes: 73 additions & 57 deletions fyrox/scripting/plugin.html
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ <h2 id="structure"><a class="header" href="#structure">Structure</a></h2>
plugin::{Plugin, PluginConstructor, PluginContext, PluginRegistrationContext},
scene::{Scene, SceneLoader},
};
use std::path::Path;

pub struct GameConstructor;

Expand All @@ -212,10 +213,10 @@ <h2 id="structure"><a class="header" href="#structure">Structure</a></h2>

fn create_instance(
&amp;self,
override_scene: Handle&lt;Scene&gt;,
scene_path: Option&lt;&amp;str&gt;,
context: PluginContext,
) -&gt; Box&lt;dyn Plugin&gt; {
Box::new(Game::new(override_scene, context))
Box::new(Game::new(scene_path, context))
}
}

Expand All @@ -224,25 +225,14 @@ <h2 id="structure"><a class="header" href="#structure">Structure</a></h2>
}

impl Game {
pub fn new(override_scene: Handle&lt;Scene&gt;, context: PluginContext) -&gt; Self {
let scene = if override_scene.is_some() {
override_scene
} else {
// Load a scene from file if there is no override scene specified.
let scene = block_on(
block_on(SceneLoader::from_file(
&quot;data/scene.rgs&quot;,
context.serialization_context.clone(),
context.resource_manager.clone()
))
.unwrap()
.finish(&amp;context.resource_manager),
);

context.scenes.add(scene)
};

Self { scene }
pub fn new(scene_path: Option&lt;&amp;str&gt;, context: PluginContext) -&gt; Self {
context
.async_scene_loader
.request(scene_path.unwrap_or(&quot;data/scene.rgs&quot;));

Self {
scene: Handle::NONE
}
}
}

Expand Down Expand Up @@ -272,30 +262,52 @@ <h2 id="structure"><a class="header" href="#structure">Structure</a></h2>
) {
// Handle UI events here.
}

fn on_scene_loaded(&amp;mut self, _path: &amp;Path, scene: Handle&lt;Scene&gt;, context: &amp;mut PluginContext) {
if self.scene.is_some() {
context.scenes.remove(self.scene);
}

self.scene = scene;
}
}
<span class="boring">}</span></code></pre></pre>
<p>There are two major parts - <code>GameConstructor</code> and <code>Game</code> itself. <code>GameConstructor</code> implements <code>PluginConstructor</code> and it
is responsible for script registration (<code>fn register</code>) and creating the actual game instance (<code>fn create_instance</code>).</p>
<ul>
<li><code>register</code> - called once on start allowing you to register your scripts. <strong>Important:</strong> You must register all your
scripts here, otherwise the engine (and the editor) will know nothing about them.</li>
scripts here, otherwise the engine (and the editor) will know nothing about them. Also, you should register loaders for
your custom resources here. See <a href="../resources/custom.html">Custom Resource chapter</a> more info. </li>
<li><code>create_instance</code> - called once, allowing you to create actual game instance. It is guaranteed to be called once, but
<em>where</em> it is called is implementation-defined. For example, the editor will <strong>not</strong> call this method, it does not
create any game instance. The method has <code>override_scene</code> parameter, in short it is a handle to a scene that must be
used by your game instead of any other scenes. It is described in <a href="#editor-and-plugins">Editor and Plugins</a> section down
below.</li>
create any game instance. The method has <code>scene_path</code> parameter, in short it is a path to a scene that is currently
opened in the editor (it will be <code>None</code> if either there's no opened scene or your game was started outside the editor).
It is described in <a href="#editor-and-plugins">Editor and Plugins</a> section down below.</li>
</ul>
<p>The game structure (<code>struct Game</code>) implements a <code>Plugin</code> trait which can execute actual game logic in one of its methods:</p>
<ul>
<li><code>on_deinit</code> - it is called when the game is about to shut down. Can be used for any clean up, for example logging that
the game has closed.</li>
<li><code>update</code> - it is called each frame at a stable rate (usually 60 Hz) after the plugin is created and fully initialized.
It is the main place where you should put <em>object-independent</em> game logic, any other logic should be added via scripts.</li>
<li><code>update</code> - it is called each frame at a stable rate (usually 60 Hz, but can be configured in the Executor) after the
plugin is created and fully initialized. It is the main place where you should put <em>object-independent</em> game logic (such
as user interface handling, global application state management, etc.), any other logic should be added via scripts.</li>
<li><code>on_os_event</code> - it is called when the main application window receives an event from the operating system, it can be
any event such as keyboard, mouse, game pad events or any other events. Please note that as for <code>update</code> method, you
should put here only <em>object-independent</em> logic. Scripts can catch window events too.</li>
should put here only <em>object-independent</em> logic. Scripts can catch OS events too.</li>
<li><code>on_ui_message</code> - it is called when there is a message from the user interface, it should be used to react to user
actions (like pressed buttons, etc.)</li>
<li><code>on_graphics_context_initialized</code> - it is called when a graphics context was successfully initialized. This method could
be used to access the renderer (to change its quality settings, for instance). You can also access a main window instance
and change its properties (such as title, size, resolution, etc.).</li>
<li><code>on_graphics_context_destroyed</code> - it is called when the current graphics context was destroyed. It could happen on a
small number of platforms, such as Android. Such platforms usually have some sort of suspension mode, in which you are
not allowed to render graphics, to have a &quot;window&quot;, etc.</li>
<li><code>before_rendering</code> - it is called when the engine is about to render a new frame. This method is useful to perform
offscreen rendering (for example - <a href="../ui/rendering.html#offscreen-rendering">user interface</a>).</li>
<li><code>on_scene_begin_loading</code> - it is called when the engine starts to load a game scene. This method could be used to
show a progress bar or some sort of loading screen, etc.</li>
<li><code>on_scene_loaded</code> - it is called when the engine successfully loaded a game scene. This method could be used to add
custom logic to do something with a newly loaded scene.</li>
</ul>
<h2 id="control-flow"><a class="header" href="#control-flow">Control Flow</a></h2>
<p>Some plugin methods provide access to <code>ControlFlow</code> variable, its main usage in the plugin is to give you ability to
Expand All @@ -317,10 +329,9 @@ <h2 id="plugin-context"><a class="header" href="#plugin-context">Plugin Context<
</span><span class="boring">fn main() {
</span><span class="boring">extern crate fyrox;
</span><span class="boring">use fyrox::{
</span><span class="boring"> engine::{SerializationContext},
</span><span class="boring"> engine::{SerializationContext, GraphicsContext, PerformanceStatistics, AsyncSceneLoader, ScriptProcessor},
</span><span class="boring"> asset::manager::ResourceManager,
</span><span class="boring"> gui::UserInterface,
</span><span class="boring"> renderer::Renderer,
</span><span class="boring"> scene::SceneContainer,
</span><span class="boring"> window::Window,
</span><span class="boring">};
Expand All @@ -329,21 +340,28 @@ <h2 id="plugin-context"><a class="header" href="#plugin-context">Plugin Context<
pub scenes: &amp;'a mut SceneContainer,
pub resource_manager: &amp;'a ResourceManager,
pub user_interface: &amp;'a mut UserInterface,
pub renderer: &amp;'a mut Renderer,
pub graphics_context: &amp;'a mut GraphicsContext,
pub dt: f32,
pub lag: &amp;'b mut f32,
pub serialization_context: &amp;'a Arc&lt;SerializationContext&gt;,
pub window: &amp;'a Window,
pub performance_statistics: &amp;'a PerformanceStatistics,
pub elapsed_time: f32,
pub script_processor: &amp;'a ScriptProcessor,
pub async_scene_loader: &amp;'a mut AsyncSceneLoader,
}
<span class="boring">}</span></code></pre></pre>
<p>Amount of time (in seconds) that passed from creation of the engine. Keep in mind, that
this value is <strong>not</strong> guaranteed to match real time. A user can change delta time with
which the engine &quot;ticks&quot; and this delta time affects elapsed time.</p>
<ul>
<li><code>scenes</code> - a scene container, could be used to manage game scenes - add, remove, borrow. An example of scene loading
is given in the previous code snippet in <code>Game::new()</code> method.</li>
<li><code>resource_manager</code> - is used to load external resources (scenes, models, textures, animations, sound buffers, etc.) from
different sources (disk, network storage on WebAssembly, etc.)</li>
<li><code>user_interface</code> - use it to create user interface for your game, the interface is scene-independent and will remain
the same even if there are multiple scenes created.</li>
<li><code>renderer</code> - can be used to add custom rendering techniques, change quality settings, etc.</li>
<li><code>graphics_context</code> - a reference to the graphics_context, it contains a reference to the window and the current renderer.
It could be <code>GraphicsContext::Uninitialized</code> if your application is suspended (possible only on Android).</li>
<li><code>dt</code> - a time passed since the last frame. The actual value is implementation-defined, but on current implementation it
is equal to 1/60 of a second and does not change event if the frame rate is changing (the engine stabilizes update rate
for the logic).</li>
Expand All @@ -352,7 +370,15 @@ <h2 id="plugin-context"><a class="header" href="#plugin-context">Plugin Context<
is to be able to reset <code>lag</code> when you're doing some heavy calculations in a game loop (i.e. loading a new level) so the
engine won't try to &quot;catch up&quot; with all the time that was spent in heavy calculation.</li>
<li><code>serialization_context</code> - it can be used to register scripts and custom scene nodes constructors at runtime.</li>
<li><code>window</code> - main application window, you can use it to change title, screen resolution, etc.</li>
<li><code>performance_statistics</code> - performance statistics from the last frame. To get a rendering performance statistics, use
<code>Renderer::get_statistics</code> method, that could be obtained from the renderer instance in the current graphics context.</li>
<li><code>elapsed_time</code> - amount of time (in seconds) that passed from creation of the engine. Keep in mind, that this value
is <strong>not</strong> guaranteed to match real time. A user can change delta time with which the engine &quot;ticks&quot; and this delta time
affects elapsed time.</li>
<li><code>script_processor</code> - a reference to the current script processor instance, which could be used to access a list of
scenes that supports scripts.</li>
<li><code>async_scene_loader</code> - a reference to the current asynchronous scene loader instance. It could be used to request
a new scene to be loaded.</li>
</ul>
<h2 id="editor-and-plugins"><a class="header" href="#editor-and-plugins">Editor and Plugins</a></h2>
<p>When you're running your game from the editor, it starts the game as a separate process and if there's a scene opened
Expand All @@ -365,38 +391,28 @@ <h2 id="editor-and-plugins"><a class="header" href="#editor-and-plugins">Editor
</span><span class="boring"> plugin::PluginContext,
</span><span class="boring"> scene::{Scene, SceneLoader},
</span><span class="boring">};
</span><span class="boring">use std::path::Path;
</span><span class="boring">
</span><span class="boring">struct Foo {
</span><span class="boring"> scene: Handle&lt;Scene&gt;,
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Foo {
</span>pub fn new(override_scene: Handle&lt;Scene&gt;, context: PluginContext) -&gt; Self {
let scene = if override_scene.is_some() {
override_scene
} else {
// Load a scene from file if there is no override scene specified.
let scene = block_on(
block_on(SceneLoader::from_file(
&quot;data/scene.rgs&quot;,
context.serialization_context.clone(),
context.resource_manager.clone(),
))
.unwrap()
.finish(&amp;context.resource_manager),
);

context.scenes.add(scene)
};

Self { scene }
</span>pub fn new(scene_path: Option&lt;&amp;str&gt;, context: PluginContext) -&gt; Self {
context
.async_scene_loader
.request(scene_path.unwrap_or(&quot;data/scene.rgs&quot;));

Self {
scene: Handle::NONE
}
}
<span class="boring">}
</span><span class="boring">}</span></code></pre></pre>
<p>The <code>override_scene</code> parameter is a handle to a scene instance that is currently opened in the editor, your game
plugin must handle this parameter and use provided scene, otherwise the run from the editor will not have the edited
scene. If the parameter is undefined (equals to <code>Handle::NONE</code>), then there is no scene loaded in the editor or the
game was run outside the editor.</p>
<p>The <code>scene_path</code> parameter is a path to a scene that is currently opened in the editor, your game should use it if you
need to load a currently selected scene of the editor in your game. However, it is not strictly necessary - you may
desire to start your game from a specific scene all the time, even when the game starts from the editor. If the parameter
is <code>None</code>, then there is no scene loaded in the editor or the game was run outside the editor.</p>

</main>

Expand Down
2 changes: 1 addition & 1 deletion fyrox/scripting/script.html
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ <h2 id="script-registration"><a class="header" href="#script-registration">Scrip
context.serialization_context.script_constructors.add::&lt;MyScript&gt;(&quot;My Script&quot;);
}
<span class="boring">
</span><span class="boring"> fn create_instance(&amp;self, _override_scene: Handle&lt;Scene&gt;, _context: PluginContext) -&gt; Box&lt;dyn Plugin&gt; {
</span><span class="boring"> fn create_instance(&amp;self, _scene_path: Option&lt;&amp;str&gt;, _context: PluginContext) -&gt; Box&lt;dyn Plugin&gt; {
</span><span class="boring"> todo!()
</span><span class="boring"> }
</span><span class="boring"> }
Expand Down
Loading

0 comments on commit 99e9ba3

Please sign in to comment.