Cleanups.

This commit is contained in:
Relintai 2024-04-28 12:47:32 +02:00
parent 80d98eb678
commit dadbb6ba5d
25 changed files with 404 additions and 819 deletions

View File

@ -1,7 +1,6 @@
Introduction to the animation features # Introduction to the animation features
======================================
The `AnimationPlayer` node allows you to create anything The `AnimationPlayer` node allows you to create anything
from simple to complex animations. from simple to complex animations.
@ -18,8 +17,7 @@ Node transforms, sprites, UI elements, particles, visibility and color
of materials, and so on. You can also modify values of script variables of materials, and so on. You can also modify values of script variables
and call any function. and call any function.
Create an AnimationPlayer node ## Create an AnimationPlayer node
------------------------------
To use the animation tools we first have to create an To use the animation tools we first have to create an
`AnimationPlayer` node. `AnimationPlayer` node.
@ -28,25 +26,22 @@ The AnimationPlayer node type is the data container for your animations.
One AnimationPlayer node can hold multiple animations, that can One AnimationPlayer node can hold multiple animations, that can
automatically transition to one another. automatically transition to one another.
.. figure:: img/animation_create_animationplayer.png) ![The AnimationPlayer node](img/animation_create_animationplayer.png)
:alt: The AnimationPlayer node
The AnimationPlayer node The AnimationPlayer node
After creating one click on the AnimationPlayer node in the Node tab to After creating one click on the AnimationPlayer node in the Node tab to
open the Animation Panel at the bottom of the viewport. open the Animation Panel at the bottom of the viewport.
.. figure:: img/animation_animation_panel.png) ![The animation panel position](img/animation_animation_panel.png)
:alt: The animation panel position
The animation panel position The animation panel position
It consists of four parts: It consists of four parts:
.. figure:: img/animation_animation_panel_overview.png) ![The animation panel](img/animation_animation_panel_overview.png)
:alt: The animation panel
The animation panel The animation panel
- Animation controls (i.e. add, load, save, and delete animations) - Animation controls (i.e. add, load, save, and delete animations)
- The tracks listing - The tracks listing
@ -54,69 +49,59 @@ It consists of four parts:
- The timeline and track controls, where you can zoom the timeline and - The timeline and track controls, where you can zoom the timeline and
edit tracks for example. edit tracks for example.
Computer animation relies on keyframes ## Computer animation relies on keyframes
--------------------------------------
A keyframe defines the value of a property at a certain point in time. A keyframe defines the value of a property at a certain point in time.
Diamond shapes represent keyframes in the timeline. A line between two Diamond shapes represent keyframes in the timeline. A line between two
keyframes indicates that the value hasn't changed. keyframes indicates that the value hasn't changed.
.. figure:: img/animation_keyframes.png) ![Keyframes in Pandemonium](img/animation_keyframes.png)
:alt: Keyframes in Pandemonium
Keyframes in Pandemonium Keyframes in Pandemonium
The engine interpolates values between keyframes, resulting in a gradual The engine interpolates values between keyframes, resulting in a gradual
change in values over time. change in values over time.
.. figure:: img/animation_illustration.png) ![Two keyframes are all it takes to obtain a smooth motion](img/animation_illustration.png)
:alt: Two keyframes are all it takes to obtain a smooth motion
Two keyframes are all it takes to obtain a smooth motion Two keyframes are all it takes to obtain a smooth motion
The timeline lets you insert keyframes and change their timing. It also The timeline lets you insert keyframes and change their timing. It also
defines how long the animation is. defines how long the animation is.
.. figure:: img/animation_timeline.png) ![The timeline in the animation panel](img/animation_timeline.png)
:alt: The timeline in the animation panel
The timeline in the animation panel The timeline in the animation panel
Each line of the Animation Panel is an animation track. Normal and Each line of the Animation Panel is an animation track. Normal and
Transform tracks reference node properties. Their name or id is a path Transform tracks reference node properties. Their name or id is a path
to the node and the affected property. to the node and the affected property.
.. figure:: img/animation_normal_track.png) ![Example of Normal animation tracks](img/animation_normal_track.png)
:alt: Example of Normal animation tracks
Example of Normal animation tracks Example of Normal animation tracks
Tip: Tip:
If you animate the wrong property, you can edit a track's path anytime. If you animate the wrong property, you can edit a track's path anytime.
Double click on it and type the new path. Play the animation using the Double click on it and type the new path. Play the animation using the
"Play from beginning" button |Play from beginning| (or pressing "Play from beginning" button |Play from beginning| (or pressing
:kbd:`Shift + D` on keyboard) to see the changes instantly. :kbd:`Shift + D` on keyboard) to see the changes instantly.
Tutorial: Creating a simple animation ## Tutorial: Creating a simple animation
-------------------------------------
Scene setup ### Scene setup
~~~~~~~~~~~
For this tutorial, we'll create a Sprite node with an AnimationPlayer as For this tutorial, we'll create a Sprite node with an AnimationPlayer as
its child. We will animate the sprite to move between two points on the screen. its child. We will animate the sprite to move between two points on the screen.
.. figure:: img/animation_animation_player_tree.png) ![Our scene setup](img/animation_animation_player_tree.png)
:alt: Our scene setup
Our scene setup Our scene setup
Warning: Warning:
AnimationPlayer inherits from Node instead of Node2D or Spatial, which means AnimationPlayer inherits from Node instead of Node2D or Spatial, which means
that the child nodes will not inherit the transform from the parent nodes that the child nodes will not inherit the transform from the parent nodes
due to a bare Node being present in the hierarchy. due to a bare Node being present in the hierarchy.
@ -134,21 +119,18 @@ animation editor. From the list select "New" (|Add
Animation|) to add a new animation. And Enter a name for the animation in the Animation|) to add a new animation. And Enter a name for the animation in the
dialog box. dialog box.
.. figure:: img/animation_create_new_animation.png) ![Add a new animation](img/animation_create_new_animation.png)
:alt: Add a new animation
Add a new animation Add a new animation
Adding a track ### Adding a track
~~~~~~~~~~~~~~
To add a new track for our sprite, select it and take a look in the To add a new track for our sprite, select it and take a look in the
toolbar: toolbar:
.. figure:: img/animation_convenience_buttons.png) ![Convenience buttons](img/animation_convenience_buttons.png)
:alt: Convenience buttons
Convenience buttons Convenience buttons
These switches and buttons allow you to add keyframes for the selected These switches and buttons allow you to add keyframes for the selected
node's location, rotation, and scale respectively. node's location, rotation, and scale respectively.
@ -162,13 +144,11 @@ property, Pandemonium asks whether it should set it up for us. Click **Create**.
This creates a new track and our first keyframe at the beginning of This creates a new track and our first keyframe at the beginning of
the timeline: the timeline:
.. figure:: img/animation_track.png) ![The sprite track](img/animation_track.png)
:alt: The sprite track
The sprite track The sprite track
The second keyframe ### The second keyframe
~~~~~~~~~~~~~~~~~~~
Now we need to set the destination where our sprite should be headed and Now we need to set the destination where our sprite should be headed and
how much time it takes to get there. how much time it takes to get there.
@ -177,10 +157,9 @@ Let's say, we want it to take 2 seconds to go to the other point. By
default the animation is set to last only 1 second, so change this in default the animation is set to last only 1 second, so change this in
the timeline controls in animation panel's lower panel to 2. the timeline controls in animation panel's lower panel to 2.
.. figure:: img/animation_set_length.png) ![Animation length](img/animation_set_length.png)
:alt: Animation length
Animation length Animation length
Click on the timeline header near the 2-second mark and move the sprite Click on the timeline header near the 2-second mark and move the sprite
to the target destination on the right side. to the target destination on the right side.
@ -188,45 +167,39 @@ to the target destination on the right side.
Again, click the key button in the toolbar. This creates our second Again, click the key button in the toolbar. This creates our second
keyframe. keyframe.
Run the animation ### Run the animation
~~~~~~~~~~~~~~~~~
Click on the "Play from beginning" (|Play from beginning|) button. Click on the "Play from beginning" (|Play from beginning|) button.
Yay! Our animation runs: Yay! Our animation runs:
.. figure:: img/animation_simple.gif) ![The animation](img/animation_simple.gif)
:alt: The animation
The animation The animation
Back and forth ### Back and forth
~~~~~~~~~~~~~~
Pandemonium has an additional feature here. Like said before, Pandemonium has an additional feature here. Like said before,
Pandemonium always calculates the frames between two keyframes. In a loop, the Pandemonium always calculates the frames between two keyframes. In a loop, the
first keyframe is also the last keyframe, if no keyframe is specified at first keyframe is also the last keyframe, if no keyframe is specified at
the end. the end.
.. figure:: img/animation_loop.png) ![Animation loop](img/animation_loop.png)
:alt: Animation loop
Animation loop Animation loop
If you set the animation length to 4 seconds now, the animation moves If you set the animation length to 4 seconds now, the animation moves
back and forth. You can change this behavior if you change the track's back and forth. You can change this behavior if you change the track's
loop mode. This is covered in the next chapter. loop mode. This is covered in the next chapter.
Track settings ### Track settings
~~~~~~~~~~~~~~
Each track has a settings panel at the end, where you can set the update Each track has a settings panel at the end, where you can set the update
mode, the track interpolation, and the loop mode. mode, the track interpolation, and the loop mode.
.. figure:: img/animation_track_settings.png) ![Track settings](img/animation_track_settings.png)
:alt: Track settings
Track settings Track settings
The update mode of a track tells Pandemonium when to update the property The update mode of a track tells Pandemonium when to update the property
values. This can be: values. This can be:
@ -243,10 +216,9 @@ values. This can be:
could use the Capture mode to move a node that's located anywhere could use the Capture mode to move a node that's located anywhere
to a specific location. to a specific location.
.. figure:: img/animation_track_rate.png) ![Track mode](img/animation_track_rate.png)
:alt: Track mode
Track mode Track mode
In normal animations, you usually use "Continuous". The other types are In normal animations, you usually use "Continuous". The other types are
used to script complex animations. used to script complex animations.
@ -260,10 +232,9 @@ the keyframes. These interpolation modes are supported:
- Cubic: Set the value based on a cubic function calculation between - Cubic: Set the value based on a cubic function calculation between
the two keyframes the two keyframes
.. figure:: img/animation_track_interpolation.png) ![Track interpolation](img/animation_track_interpolation.png)
:alt: Track interpolation
Track interpolation Track interpolation
Cubic interpolation leads to a more natural movement, where the Cubic interpolation leads to a more natural movement, where the
animation is slower at a keyframe and faster between keyframes. This is animation is slower at a keyframe and faster between keyframes. This is
@ -273,10 +244,9 @@ of a robotic movement.
Pandemonium supports two loop modes, which affect the animation if it's set to Pandemonium supports two loop modes, which affect the animation if it's set to
loop: loop:
.. figure:: img/animation_track_loop_modes.png) ![Loop modes](img/animation_track_loop_modes.png)
:alt: Loop modes
Loop modes Loop modes
- Clamp loop interpolation: When this is selected, the animation stops - Clamp loop interpolation: When this is selected, the animation stops
after the last keyframe for this track. When the first keyframe is after the last keyframe for this track. When the first keyframe is
@ -285,8 +255,7 @@ loop:
animation after the last keyframe to reach the values of the first animation after the last keyframe to reach the values of the first
keyframe again. keyframe again.
Keyframes for other properties ## Keyframes for other properties
------------------------------
Pandemonium doesn't restrict you to only edit transform properties. Every Pandemonium doesn't restrict you to only edit transform properties. Every
property can be used as a track where you can set keyframes. property can be used as a track where you can set keyframes.
@ -296,22 +265,19 @@ a small keyframe button for all the sprite's properties. Click on
this button and Pandemonium automatically adds a track and keyframe to the this button and Pandemonium automatically adds a track and keyframe to the
current animation. current animation.
.. figure:: img/animation_properties_keyframe.png) ![Keyframes for other properties](img/animation_properties_keyframe.png)
:alt: Keyframes for other properties
Keyframes for other properties Keyframes for other properties
Edit keyframes ## Edit keyframes
--------------
For advanced use and to edit keyframes in detail, You can click on them For advanced use and to edit keyframes in detail, You can click on them
to bring up the keyframe editor in the inspector. You can use this to to bring up the keyframe editor in the inspector. You can use this to
directly edit its values. directly edit its values.
.. figure:: img/animation_keyframe_editor_key.png) ![Keyframe editor editing a key](img/animation_keyframe_editor_key.png)
:alt: Keyframe editor editing a key
Keyframe editor editing a key Keyframe editor editing a key
Additionally, you can also edit the easing value for this keyframe by Additionally, you can also edit the easing value for this keyframe by
clicking and dragging the easing setting. This tells Pandemonium, how to change clicking and dragging the easing setting. This tells Pandemonium, how to change
@ -320,8 +286,7 @@ the property values when it reaches this keyframe.
You usually tweak your animations this way, when the movement doesn't You usually tweak your animations this way, when the movement doesn't
"look right". "look right".
Advanced: Call Method tracks ## Advanced: Call Method tracks
----------------------------
Pandemonium's animation engine doesn't stop here. If you're already Pandemonium's animation engine doesn't stop here. If you're already
comfortable with Pandemonium's scripting language comfortable with Pandemonium's scripting language
@ -350,18 +315,16 @@ controls.
Select "Add Call Method Track" from the list of possible track types. Select "Add Call Method Track" from the list of possible track types.
.. figure:: img/animation_add_call_method_track.png) ![Add Call Method Track](img/animation_add_call_method_track.png)
:alt: Add Call Method Track
Add Call Method Track Add Call Method Track
Select the `AudioStreamPlayer` node in the selection Select the `AudioStreamPlayer` node in the selection
window. Pandemonium adds the track with the reference to the node. window. Pandemonium adds the track with the reference to the node.
.. figure:: img/animation_select_audiostreamplayer.png) ![Select AudioStreamPlayer](img/animation_select_audiostreamplayer.png)
:alt: Select AudioStreamPlayer
Select AudioStreamPlayer Select AudioStreamPlayer
Right click the timeline where Pandemonium should play the sample and Right click the timeline where Pandemonium should play the sample and
click the "Insert Key" option. This will bring up a list of methods click the "Insert Key" option. This will bring up a list of methods
@ -379,12 +342,17 @@ click on the keyframe and use the keyframe settings in the inspector.
![](img/animation_call_method_keyframe.png) ![](img/animation_call_method_keyframe.png)
.. |Play from beginning| image:: img/animation_play_from_beginning.png) ![Play from beginning](img/animation_play_from_beginning.png)
.. |Add Animation| image:: img/animation_add.png)
.. |Add track| image:: img/animation_add_track.png)
Using RESET tracks Play from beginning
------------------
![Add Animation](img/animation_add.png)
Add Animation
![Add track](img/animation_add_track.png)
## Using RESET tracks
You can set up a special *RESET* animation to contain the "default pose". You can set up a special *RESET* animation to contain the "default pose".
This is used to ensure that the default pose is restored when you save This is used to ensure that the default pose is restored when you save

View File

@ -1,10 +1,8 @@
Cutout animation # Cutout animation
================
What is it? ### What is it?
~~~~~~~~~~~
Traditionally, `cutout animation ( https://en.wikipedia.org/wiki/Cutout_animation )` Traditionally, `cutout animation ( https://en.wikipedia.org/wiki/Cutout_animation )`
is a type of `stop motion animation ( https://en.wikipedia.org/wiki/Stop_motion )` is a type of `stop motion animation ( https://en.wikipedia.org/wiki/Stop_motion )`
@ -23,8 +21,7 @@ In video games, this technique has also become popular. Examples of
this are `Paper Mario ( https://en.wikipedia.org/wiki/Super_Paper_Mario )` or this are `Paper Mario ( https://en.wikipedia.org/wiki/Super_Paper_Mario )` or
`Rayman Origins ( https://en.wikipedia.org/wiki/Rayman_Origins )` . `Rayman Origins ( https://en.wikipedia.org/wiki/Rayman_Origins )` .
Cutout animation in Pandemonium ### Cutout animation in Pandemonium
~~~~~~~~~~~~~~~~~~~~~~~~~
Pandemonium provides tools for working with cutout rigs, and is ideal for the workflow: Pandemonium provides tools for working with cutout rigs, and is ideal for the workflow:
@ -50,8 +47,7 @@ Pandemonium provides tools for working with cutout rigs, and is ideal for the wo
And much more! And much more!
Making of GBot ### Making of GBot
~~~~~~~~~~~~~~
For this tutorial, we will use as demo content the pieces of the For this tutorial, we will use as demo content the pieces of the
`GBot ( https://www.youtube.com/watch?v=S13FrWuBMx4&list=UUckpus81gNin1aV8WSffRKw )` `GBot ( https://www.youtube.com/watch?v=S13FrWuBMx4&list=UUckpus81gNin1aV8WSffRKw )`
@ -61,8 +57,7 @@ character, created by Andreas Esau.
Get your assets: :download:`gbot_resources.zip (files/gbot_resources.zip )`. Get your assets: :download:`gbot_resources.zip (files/gbot_resources.zip )`.
Setting up the rig ### Setting up the rig
~~~~~~~~~~~~~~~~~~
Create an empty Node2D as root of the scene, we will work under it: Create an empty Node2D as root of the scene, we will work under it:
@ -92,8 +87,7 @@ the rotation pivot:
![](img/tuto_cutout4.png) ![](img/tuto_cutout4.png)
Adjusting the pivot ### Adjusting the pivot
~~~~~~~~~~~~~~~~~~~
The pivot can be adjusted by changing the *offset* property in the The pivot can be adjusted by changing the *offset* property in the
Sprite: Sprite:
@ -128,8 +122,7 @@ Note:
You can also fix depth ordering problems by adjusting the Z property You can also fix depth ordering problems by adjusting the Z property
of any node inheriting from Node2D. of any node inheriting from Node2D.
RemoteTransform2D node ### RemoteTransform2D node
~~~~~~~~~~~~~~~~~~~~~~
The `RemoteTransform2D` node transforms nodes The `RemoteTransform2D` node transforms nodes
somewhere else in the hierarchy. This node applies its own transform (including somewhere else in the hierarchy. This node applies its own transform (including
@ -150,8 +143,7 @@ animations by adjusting the `RemoteTransform2D` transforms:
![](img/tutovec_torso4.gif) ![](img/tutovec_torso4.gif)
Completing the skeleton ### Completing the skeleton
~~~~~~~~~~~~~~~~~~~~~~~
Complete the skeleton by following the same steps for the rest of the Complete the skeleton by following the same steps for the rest of the
parts. The resulting scene should look similar to this: parts. The resulting scene should look similar to this:
@ -170,8 +162,7 @@ For simple objects and rigs this is fine, but there are limitations:
To solve these problems we'll use Pandemonium's skeletons. To solve these problems we'll use Pandemonium's skeletons.
Skeletons ### Skeletons
~~~~~~~~~
In Pandemonium there is a helper to create "bones" between nodes. The bone-linked In Pandemonium there is a helper to create "bones" between nodes. The bone-linked
nodes are called skeletons. nodes are called skeletons.
@ -229,8 +220,7 @@ sense soon.
Now that the whole figure is rigged, the next step is setting up the IK Now that the whole figure is rigged, the next step is setting up the IK
chains. IK chains allow for more natural control of extremities. chains. IK chains allow for more natural control of extremities.
IK chains ### IK chains
~~~~~~~~~
IK stands for inverse kinematics. It's a convenient technique for animating the IK stands for inverse kinematics. It's a convenient technique for animating the
position of hands, feet and other extremities of rigs like the one we've made. position of hands, feet and other extremities of rigs like the one we've made.
@ -261,15 +251,13 @@ adjust its position.
![](img/tutovec_torso5.gif) ![](img/tutovec_torso5.gif)
Animation tips ### Animation tips
~~~~~~~~~~~~~~
The following section will be a collection of tips for creating animation for The following section will be a collection of tips for creating animation for
your cutout rigs. For more information on how the animation system in Pandemonium your cutout rigs. For more information on how the animation system in Pandemonium
works, see `doc_introduction_animation`. works, see `doc_introduction_animation`.
Setting keyframes and excluding properties ## Setting keyframes and excluding properties
------------------------------------------
Special contextual elements appear in the top toolbar when the animation editor Special contextual elements appear in the top toolbar when the animation editor
window is open: window is open:
@ -291,8 +279,7 @@ You can use the toggle buttons to have only rotation information added when you
add a new keyframe. This way, you can avoid adding unwanted scale keyframes add a new keyframe. This way, you can avoid adding unwanted scale keyframes
which would disrupt the existing scale animation. which would disrupt the existing scale animation.
Creating a rest pose ## Creating a rest pose
~~~~~~~~~~~~~~~~~~~~
Think of a rest pose as a default pose that your cutout rig should be set to Think of a rest pose as a default pose that your cutout rig should be set to
when no other pose is active in your game. Create a rest pose as follows: when no other pose is active in your game. Create a rest pose as follows:
@ -313,8 +300,7 @@ your game by playing the "rest" animation you've created.
![](img/tuto_cutout21.png) ![](img/tuto_cutout21.png)
Modifying rotation only ### Modifying rotation only
~~~~~~~~~~~~~~~~~~~~~~~
When animating a cutout rig, often it's only the rotation of the nodes that When animating a cutout rig, often it's only the rotation of the nodes that
needs to change. needs to change.
@ -328,15 +314,13 @@ toggle active most of the time:
This will avoid the creation of unwanted animation tracks for position This will avoid the creation of unwanted animation tracks for position
and scale. and scale.
Keyframing IK chains ### Keyframing IK chains
~~~~~~~~~~~~~~~~~~~~
When editing IK chains, it's not necessary to select the whole chain to When editing IK chains, it's not necessary to select the whole chain to
add keyframes. Selecting the endpoint of the chain and inserting a add keyframes. Selecting the endpoint of the chain and inserting a
keyframe will automatically insert keyframes for all other parts of the chain too. keyframe will automatically insert keyframes for all other parts of the chain too.
Visually move a sprite behind its parent ### Visually move a sprite behind its parent
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sometimes it is necessary to have a node change its visual depth relative to Sometimes it is necessary to have a node change its visual depth relative to
its parent node during an animation. Think of a character facing the camera, its parent node during an animation. Think of a character facing the camera,
@ -351,8 +335,7 @@ and/or RemoteTransform2D nodes. They provide overlapping functionality.
![](img/tuto_cutout23.png) ![](img/tuto_cutout23.png)
Setting easing curves for multiple keys ### Setting easing curves for multiple keys
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To apply the same easing curve to multiple keyframes at once: To apply the same easing curve to multiple keyframes at once:
@ -363,8 +346,7 @@ To apply the same easing curve to multiple keyframes at once:
![](img/tuto_cutout24.png) ![](img/tuto_cutout24.png)
2D Skeletal deform ### 2D Skeletal deform
~~~~~~~~~~~~~~~~~~
Skeletal deform can be used to augment a cutout rig, allowing single pieces to Skeletal deform can be used to augment a cutout rig, allowing single pieces to
deform organically (e.g. antennae that wobble as an insect character walks). deform organically (e.g. antennae that wobble as an insect character walks).

View File

@ -1,10 +1,8 @@
2D skeletons # 2D skeletons
============
Introduction ## Introduction
------------
When working with 3D, skeletal deforms are common for characters and creatures When working with 3D, skeletal deforms are common for characters and creatures
and most 3D modelling applications support it. For 2D, as this function is not and most 3D modelling applications support it. For 2D, as this function is not
@ -26,8 +24,7 @@ that there are many advantages to it:
The following tutorial will, then, explain 2D skeletal deformations. The following tutorial will, then, explain 2D skeletal deformations.
Setup ## Setup
-----
See also: See also:
@ -48,8 +45,7 @@ for putting the different pieces together.
![](img/gBot_complete.png) ![](img/gBot_complete.png)
Creating the polygons ## reating the polygons
---------------------
Create a new scene for your model (if it's going to be an animated character, Create a new scene for your model (if it's going to be an animated character,
you may want to use a `KinematicBody2D`). For ease of use, an empty 2D node is you may want to use a `KinematicBody2D`). For ease of use, an empty 2D node is
@ -108,8 +104,7 @@ wrong pieces. Rearrange the order of the nodes to fix this:
And there you go! It was definitely much easier than in the cutout tutorial. And there you go! It was definitely much easier than in the cutout tutorial.
Creating the skeleton ## Creating the skeleton
---------------------
Create a `Skeleton2D` node as a child of the root node. This will be the base Create a `Skeleton2D` node as a child of the root node. This will be the base
of our skeleton: of our skeleton:
@ -151,8 +146,7 @@ want (which is very handy for animating):
The warnings will go away. If you modify the skeleton (add/remove bones) you The warnings will go away. If you modify the skeleton (add/remove bones) you
will need to set the rest pose again. will need to set the rest pose again.
Deforming the polygons ## Deforming the polygons
----------------------
Select the previously created polygons and assign the skeleton node to their Select the previously created polygons and assign the skeleton node to their
`Skeleton` property. This will ensure that they can eventually be deformed by `Skeleton` property. This will ensure that they can eventually be deformed by
@ -205,8 +199,7 @@ when drawing the polygon. They don't always bend the way you would expect. To
solve this, you need to set hints in the geometry to clarify how you expect it solve this, you need to set hints in the geometry to clarify how you expect it
to deform. to deform.
Internal vertices ## Internal vertices
-----------------
Open the UV menu for each bone again and go to the *Points* section. Add some Open the UV menu for each bone again and go to the *Points* section. Add some
internal vertices in the regions where you expect the geometry to bend: internal vertices in the regions where you expect the geometry to bend:

View File

@ -1,10 +1,8 @@
Using AnimationTree # Using AnimationTree
===================
Introduction ## Introduction
------------
With `AnimationPlayer`, Pandemonium has one of the most flexible animation systems that you can find in any game engine. With `AnimationPlayer`, Pandemonium has one of the most flexible animation systems that you can find in any game engine.
The ability to animate almost any property in any node or resource, as well as having dedicated transform, bezier, The ability to animate almost any property in any node or resource, as well as having dedicated transform, bezier,
@ -15,8 +13,7 @@ However, the support for blending those animations via `AnimationPlayer` is rela
`AnimationTree` is a new node introduced in Pandemonium 3.1 to deal with advanced transitions. `AnimationTree` is a new node introduced in Pandemonium 3.1 to deal with advanced transitions.
It supersedes the ancient `AnimationTreePlayer`, while adding a huge amount of features and flexibility. It supersedes the ancient `AnimationTreePlayer`, while adding a huge amount of features and flexibility.
Creating an AnimationTree ## Creating an AnimationTree
-------------------------
Before starting, it must be made clear that an `AnimationTree` node does not contain its own animations. Before starting, it must be made clear that an `AnimationTree` node does not contain its own animations.
Instead, it uses animations contained in an `AnimationPlayer` node. This way, you can edit your animations (or import them from a 3D scene) Instead, it uses animations contained in an `AnimationPlayer` node. This way, you can edit your animations (or import them from a 3D scene)
@ -36,8 +33,7 @@ This is how it's done in the `Third Person Shooter demo ( https://github.com/pan
A new scene was created for the player with a `KinematicBody` as root. Inside this scene, the original `.dae` (Collada) file was instantiated A new scene was created for the player with a `KinematicBody` as root. Inside this scene, the original `.dae` (Collada) file was instantiated
and an `AnimationTree` node was created. and an `AnimationTree` node was created.
Creating a tree ## Creating a tree
---------------
There are three main types of nodes that can be used in `AnimationTree`: There are three main types of nodes that can be used in `AnimationTree`:
@ -55,8 +51,7 @@ To set a root node in `AnimationTree`, a few types are available:
* `AnimationNodeBlendSpace2D`: Allows placing root nodes in a 2D blend space. Control the blend position in 2D to mix between multiple animations. * `AnimationNodeBlendSpace2D`: Allows placing root nodes in a 2D blend space. Control the blend position in 2D to mix between multiple animations.
* `AnimationNodeBlendSpace1D`: Simplified version of the above (1D). * `AnimationNodeBlendSpace1D`: Simplified version of the above (1D).
Blend tree ## Blend tree
----------
An `AnimationNodeBlendTree` can contain both root and regular nodes used for blending. Nodes are added to the graph from a menu: An `AnimationNodeBlendTree` can contain both root and regular nodes used for blending. Nodes are added to the graph from a menu:
@ -72,8 +67,7 @@ This will simply play back the animation. Make sure that the `AnimationTree` is
Following is a short description of available nodes: Following is a short description of available nodes:
Blend2 / Blend3 #### Blend2 / Blend3
^^^^^^^^^^^^^^^
These nodes will blend between two or three inputs by a user-specified blend value: These nodes will blend between two or three inputs by a user-specified blend value:
@ -86,15 +80,13 @@ This is very useful for layering animations on top of each other.
![](img/animtree6.png) ![](img/animtree6.png)
OneShot #### OneShot
^^^^^^^
This node will execute a sub-animation and return once it finishes. Blend times for fading in and out can be customized, as well as filters. This node will execute a sub-animation and return once it finishes. Blend times for fading in and out can be customized, as well as filters.
![](img/animtree6b.gif) ![](img/animtree6b.gif)
Seek #### Seek
^^^^
This node can be used to cause a seek command to happen to any sub-children of the animation graph. Use this node type to play an `Animation` from the start or a certain playback position inside the `AnimationNodeBlendTree`. This node can be used to cause a seek command to happen to any sub-children of the animation graph. Use this node type to play an `Animation` from the start or a certain playback position inside the `AnimationNodeBlendTree`.
@ -114,18 +106,15 @@ gdscript GDScript
anim_tree["parameters/Seek/seek_position"] = 12.0 anim_tree["parameters/Seek/seek_position"] = 12.0
``` ```
TimeScale #### TimeScale
^^^^^^^^^
Allows scaling the speed of the animation (or reverse it) in any children nodes. Setting it to 0 will pause the animation. Allows scaling the speed of the animation (or reverse it) in any children nodes. Setting it to 0 will pause the animation.
Transition #### Transition
^^^^^^^^^^
Very simple state machine (when you don't want to cope with a `StateMachine` node). Animations can be connected to the outputs and transition times can be specified. Very simple state machine (when you don't want to cope with a `StateMachine` node). Animations can be connected to the outputs and transition times can be specified.
BlendSpace2D #### BlendSpace2D
^^^^^^^^^^^^
`BlendSpace2D` is a node to do advanced blending in two dimensions. Points are added to a two-dimensional space and then a position `BlendSpace2D` is a node to do advanced blending in two dimensions. Points are added to a two-dimensional space and then a position
can be controlled to determine blending: can be controlled to determine blending:
@ -148,13 +137,11 @@ This mode can be changed in the *Blend* menu:
![](img/animtree10.png) ![](img/animtree10.png)
BlendSpace1D #### BlendSpace1D
^^^^^^^^^^^^
This is similar to 2D blend spaces, but in one dimension (so triangles are not needed). This is similar to 2D blend spaces, but in one dimension (so triangles are not needed).
StateMachine #### StateMachine
^^^^^^^^^^^^
This node acts as a state machine with root nodes as states. Root nodes can be created and connected via lines. States are connected via *Transitions*, This node acts as a state machine with root nodes as states. Root nodes can be created and connected via lines. States are connected via *Transitions*,
which are connections with special properties. Transitions are uni-directional, but two can be used to connect in both directions. which are connections with special properties. Transitions are uni-directional, but two can be used to connect in both directions.
@ -182,8 +169,7 @@ Transitions also have a few properties. Click any transition and it will be disp
* *Disabled* toggles disabling this transition (when disabled, it will not be used during travel or auto advance). * *Disabled* toggles disabling this transition (when disabled, it will not be used during travel or auto advance).
Root motion ## Root motion
-----------
When working with 3D animations, a popular technique is for animators to use the root skeleton bone to give motion to the rest of the skeleton. When working with 3D animations, a popular technique is for animators to use the root skeleton bone to give motion to the rest of the skeleton.
This allows animating characters in a way where steps actually match the floor below. It also allows precise interaction with objects during cinematics. This allows animating characters in a way where steps actually match the floor below. It also allows precise interaction with objects during cinematics.
@ -209,8 +195,7 @@ character and animations (this node is disabled by default during the game).
![](img/animtree15.gif) ![](img/animtree15.gif)
Controlling from code ## Controlling from code
---------------------
After building the tree and previewing it, the only question remaining is "How is all this controlled from code?". After building the tree and previewing it, the only question remaining is "How is all this controlled from code?".
@ -242,8 +227,7 @@ gdscript GDScript
``` ```
State machine travel ## State machine travel
--------------------
One of the nice features in Pandemonium's `StateMachine` implementation is the ability to travel. The graph can be instructed to go from the One of the nice features in Pandemonium's `StateMachine` implementation is the ability to travel. The graph can be instructed to go from the
current state to another one, while visiting all the intermediate ones. This is done via the A\* algorithm. current state to another one, while visiting all the intermediate ones. This is done via the A\* algorithm.

View File

@ -1,12 +1,10 @@
Playing videos # Playing videos
==============
Pandemonium supports video playback with the `VideoPlayer` node. Pandemonium supports video playback with the `VideoPlayer` node.
Supported playback formats ## Supported playback formats
--------------------------
The only supported format in core is **Ogg Theora** (not to be confused with Ogg The only supported format in core is **Ogg Theora** (not to be confused with Ogg
Vorbis audio). It's possible for extensions to bring support for additional Vorbis audio). It's possible for extensions to bring support for additional
@ -31,8 +29,7 @@ Note:
imported in Pandemonium. However, not all files with `.ogg` or `.ogx` imported in Pandemonium. However, not all files with `.ogg` or `.ogx`
extensions are videos - some of them may only contain audio. extensions are videos - some of them may only contain audio.
Setting up VideoPlayer ## Setting up VideoPlayer
----------------------------
1. Create a VideoPlayer node using the Create New Node dialog. 1. Create a VideoPlayer node using the Create New Node dialog.
2. Select the VideoPlayer node in the scene tree dock, go to the inspector 2. Select the VideoPlayer node in the scene tree dock, go to the inspector
@ -46,8 +43,7 @@ Setting up VideoPlayer
`play()` on the VideoPlayer node in a script to start playback when `play()` on the VideoPlayer node in a script to start playback when
desired. desired.
Handling resizing and different aspect ratios #### Handling resizing and different aspect ratios
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default in Pandemonium 4.0, the VideoPlayer will automatically be resized to match By default in Pandemonium 4.0, the VideoPlayer will automatically be resized to match
the video's resolution. You can make it follow usual `Control` sizing the video's resolution. You can make it follow usual `Control` sizing
@ -86,8 +82,7 @@ See also:
See `doc_multiple_resolutions` for more tips on supporting multiple See `doc_multiple_resolutions` for more tips on supporting multiple
aspect ratios in your project. aspect ratios in your project.
Displaying a video on a 3D surface #### Displaying a video on a 3D surface
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Using a VideoPlayer node as a child of a `Viewport` node, Using a VideoPlayer node as a child of a `Viewport` node,
it's possible to display any 2D node on a 3D surface. For example, this can be it's possible to display any 2D node on a 3D surface. For example, this can be
@ -118,8 +113,7 @@ See `doc_viewports` and the
`GUI in 3D demo ( https://github.com/Relintai/pandemonium_engine-demo-projects/tree/master/viewport/gui_in_3d )` `GUI in 3D demo ( https://github.com/Relintai/pandemonium_engine-demo-projects/tree/master/viewport/gui_in_3d )`
for more information on setting this up. for more information on setting this up.
Video decoding conditions and recommended resolutions ## Video decoding conditions and recommended resolutions
-----------------------------------------------------
Video decoding is performed on the CPU, as GPUs don't have hardware acceleration Video decoding is performed on the CPU, as GPUs don't have hardware acceleration
for decoding Theora videos. Modern desktop CPUs can decode Ogg Theora videos at for decoding Theora videos. Modern desktop CPUs can decode Ogg Theora videos at
@ -137,8 +131,7 @@ To ensure your videos decode smoothly on varied hardware:
between 720p and 1080p videos on a mobile device is usually not that between 720p and 1080p videos on a mobile device is usually not that
noticeable. noticeable.
Playback limitations ## Playback limitations
--------------------
There are several limitations with the current implementation of video playback in Pandemonium: There are several limitations with the current implementation of video playback in Pandemonium:
@ -156,8 +149,7 @@ There are several limitations with the current implementation of video playback
Recommended Theora encoding settings ## Recommended Theora encoding settings
------------------------------------
A word of advice is to **avoid relying on built-in Ogg Theora exporters** (most of the time). A word of advice is to **avoid relying on built-in Ogg Theora exporters** (most of the time).
There are 2 reasons you may want to favor using an external program to encode your video: There are 2 reasons you may want to favor using an external program to encode your video:
@ -193,8 +185,7 @@ Note:
You can check this by running `ffmpeg` without any arguments, then looking You can check this by running `ffmpeg` without any arguments, then looking
at the `configuration:` line in the command output. at the `configuration:` line in the command output.
Balancing quality and file size #### Balancing quality and file size
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The **video quality** level (`-q:v`) must be between `1` and `10`. Quality The **video quality** level (`-q:v`) must be between `1` and `10`. Quality
`6` is a good compromise between quality and file size. If encoding at a high `6` is a good compromise between quality and file size. If encoding at a high
@ -213,8 +204,7 @@ valuable if your input file already uses lossy audio compression. See
for a table listing Ogg Vorbis audio quality presets and their respective for a table listing Ogg Vorbis audio quality presets and their respective
variable bitrates. variable bitrates.
FFmpeg: Convert while preserving original video resolution #### FFmpeg: Convert while preserving original video resolution
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following command converts the video while keeping its original resolution. The following command converts the video while keeping its original resolution.
The video and audio's bitrate will be variable to maximize quality while saving The video and audio's bitrate will be variable to maximize quality while saving
@ -225,8 +215,7 @@ static scenes).
ffmpeg -i input.mp4 -q:v 6 -q:a 6 output.ogv ffmpeg -i input.mp4 -q:v 6 -q:a 6 output.ogv
``` ```
FFmpeg: Resize the video then convert it #### FFmpeg: Resize the video then convert it
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following command resizes a video to be 720 pixels tall (720p), while The following command resizes a video to be 720 pixels tall (720p), while
preserving its existing aspect ratio. This helps decrease the file size preserving its existing aspect ratio. This helps decrease the file size

View File

@ -1,10 +1,8 @@
Using InputEvent # Using InputEvent
================
What is it? ## What is it?
-----------
Managing input is usually complex, no matter the OS or platform. To ease Managing input is usually complex, no matter the OS or platform. To ease
this a little, a special built-in type is provided, `InputEvent`. this a little, a special built-in type is provided, `InputEvent`.
@ -39,8 +37,7 @@ gdscript GDScript
# Move right. # Move right.
``` ```
How does it work? ## How does it work?
-----------------
Every input event is originated from the user/player (though it's Every input event is originated from the user/player (though it's
possible to generate an InputEvent and feed them back to the engine, possible to generate an InputEvent and feed them back to the engine,
@ -100,8 +97,7 @@ specialized child nodes to handle and consume particular events, while
their ancestors, and ultimately the scene root, can provide more their ancestors, and ultimately the scene root, can provide more
generalized behavior if needed. generalized behavior if needed.
Anatomy of an InputEvent ## Anatomy of an InputEvent
------------------------
`InputEvent` is just a base built-in type, it does not represent `InputEvent` is just a base built-in type, it does not represent
anything and only contains some basic information, such as event ID anything and only contains some basic information, such as event ID
@ -109,40 +105,31 @@ anything and only contains some basic information, such as event ID
There are several specialized types of InputEvent, described in the table below: There are several specialized types of InputEvent, described in the table below:
+-------------------------------------------------------------------+--------------------+-----------------------------------------+
| Event | Type Index | Description | | Event | Type Index | Description |
+-------------------------------------------------------------------+--------------------+-----------------------------------------+ |-----------------------------|--------------------|-----------------------------------------|
| `InputEvent` | NONE | Empty Input Event. | | `InputEvent` | NONE | Empty Input Event. |
+-------------------------------------------------------------------+--------------------+-----------------------------------------+
| `InputEventKey` | KEY | Contains a scancode and Unicode value, | | `InputEventKey` | KEY | Contains a scancode and Unicode value, |
| | | as well as modifiers. | | | | as well as modifiers. |
+-------------------------------------------------------------------+--------------------+-----------------------------------------+
| `InputEventMouseButton` | MOUSE_BUTTON | Contains click information, such as | | `InputEventMouseButton` | MOUSE_BUTTON | Contains click information, such as |
| | | button, modifiers, etc. | | | | button, modifiers, etc. |
+-------------------------------------------------------------------+--------------------+-----------------------------------------+
| `InputEventMouseMotion` | MOUSE_MOTION | Contains motion information, such as | | `InputEventMouseMotion` | MOUSE_MOTION | Contains motion information, such as |
| | | relative, absolute positions and speed. | | | | relative, absolute positions and speed. |
+-------------------------------------------------------------------+--------------------+-----------------------------------------+
| `InputEventJoypadMotion` | JOYSTICK_MOTION | Contains Joystick/Joypad analog axis | | `InputEventJoypadMotion` | JOYSTICK_MOTION | Contains Joystick/Joypad analog axis |
| | | information. | | | | information. |
+-------------------------------------------------------------------+--------------------+-----------------------------------------+
| `InputEventJoypadButton` | JOYSTICK_BUTTON | Contains Joystick/Joypad button | | `InputEventJoypadButton` | JOYSTICK_BUTTON | Contains Joystick/Joypad button |
| | | information. | | | | information. |
+-------------------------------------------------------------------+--------------------+-----------------------------------------+
| `InputEventScreenTouch` | SCREEN_TOUCH | Contains multi-touch press/release | | `InputEventScreenTouch` | SCREEN_TOUCH | Contains multi-touch press/release |
| | | information. (only available on mobile | | | | information. (only available on mobile |
| | | devices) | | | | devices) |
+-------------------------------------------------------------------+--------------------+-----------------------------------------+
| `InputEventScreenDrag` | SCREEN_DRAG | Contains multi-touch drag information. | | `InputEventScreenDrag` | SCREEN_DRAG | Contains multi-touch drag information. |
| | | (only available on mobile devices) | | | | (only available on mobile devices) |
+-------------------------------------------------------------------+--------------------+-----------------------------------------+
| `InputEventAction` | SCREEN_ACTION | Contains a generic action. These events | | `InputEventAction` | SCREEN_ACTION | Contains a generic action. These events |
| | | are often generated by the programmer | | | | are often generated by the programmer |
| | | as feedback. (more on this below) | | | | as feedback. (more on this below) |
+-------------------------------------------------------------------+--------------------+-----------------------------------------+
Actions
------- ## Actions
An InputEvent may or may not represent a pre-defined action. Actions are An InputEvent may or may not represent a pre-defined action. Actions are
useful because they abstract the input device when programming the game useful because they abstract the input device when programming the game
@ -174,8 +161,7 @@ gdscript GDScript
Input.parse_input_event(ev) Input.parse_input_event(ev)
```` ````
InputMap ## InputMap
--------
Customizing and re-mapping input from code is often desired. If your Customizing and re-mapping input from code is often desired. If your
whole workflow depends on actions, the `InputMap` singleton is whole workflow depends on actions, the `InputMap` singleton is

View File

@ -1,10 +1,8 @@
Input examples # Input examples
==============
Introduction ## Introduction
------------
In this tutorial, you'll learn how to use Pandemonium's `InputEvent` In this tutorial, you'll learn how to use Pandemonium's `InputEvent`
system to capture player input. There are many different types of input your system to capture player input. There are many different types of input your
@ -17,8 +15,7 @@ Note:
For a detailed overview of how Pandemonium's input event system works, For a detailed overview of how Pandemonium's input event system works,
see `doc_inputevent`. see `doc_inputevent`.
Events versus polling ## Events versus polling
---------------------
Sometimes you want your game to respond to a certain input event - pressing Sometimes you want your game to respond to a certain input event - pressing
the "jump" button, for example. For other situations, you might want something the "jump" button, for example. For other situations, you might want something
@ -49,8 +46,7 @@ you do.
For the remainder of this tutorial, we'll focus on capturing individual For the remainder of this tutorial, we'll focus on capturing individual
events in `input()`. events in `input()`.
Input events ## Input events
------------
Input events are objects that inherit from `InputEvent`. Input events are objects that inherit from `InputEvent`.
Depending on the event type, the object will contain specific properties Depending on the event type, the object will contain specific properties
@ -108,8 +104,7 @@ gdscript GDScript
print("mouse button event at ", event.position) print("mouse button event at ", event.position)
``` ```
InputMap ## InputMap
--------
The `InputMap` is the most flexible way to handle a The `InputMap` is the most flexible way to handle a
variety of inputs. You use this by creating named input *actions*, to which variety of inputs. You use this by creating named input *actions*, to which
@ -120,8 +115,7 @@ the InputMap tab:
![](img/inputs_inputmap.png) ![](img/inputs_inputmap.png)
Capturing actions ### Capturing actions
~~~~~~~~~~~~~~~~~
Once you've defined your actions, you can process them in your scripts using Once you've defined your actions, you can process them in your scripts using
`is_action_pressed()` and `is_action_released()` by passing the name of `is_action_pressed()` and `is_action_released()` by passing the name of
@ -135,8 +129,7 @@ gdscript GDScript
print("my_action occurred!") print("my_action occurred!")
``` ```
Keyboard events ## Keyboard events
---------------
Keyboard events are captured in `InputEventKey`. Keyboard events are captured in `InputEventKey`.
While it's recommended to use input actions instead, there may be cases where While it's recommended to use input actions instead, there may be cases where
@ -170,8 +163,7 @@ Warning:
`this Gamedev Stack Exchange question ( https://gamedev.stackexchange.com/a/109002 )` `this Gamedev Stack Exchange question ( https://gamedev.stackexchange.com/a/109002 )`
for more information. for more information.
Keyboard modifiers ### Keyboard modifiers
~~~~~~~~~~~~~~~~~~
Modifier properties are inherited from Modifier properties are inherited from
`InputEventWithModifiers`. This allows `InputEventWithModifiers`. This allows
@ -195,16 +187,14 @@ Tip:
See `@GlobalScope_KeyList ( enum_@GlobalScope_KeyList )` for a list of scancode See `@GlobalScope_KeyList ( enum_@GlobalScope_KeyList )` for a list of scancode
constants. constants.
Mouse events ## Mouse events
------------
Mouse events stem from the `InputEventMouse` class, and Mouse events stem from the `InputEventMouse` class, and
are separated into two types: `InputEventMouseButton` are separated into two types: `InputEventMouseButton`
and `InputEventMouseMotion`. Note that this and `InputEventMouseMotion`. Note that this
means that all mouse events will contain a `position` property. means that all mouse events will contain a `position` property.
Mouse buttons ### Mouse buttons
~~~~~~~~~~~~~
Capturing mouse buttons is very similar to handling key events. `@GlobalScope_ButtonList ( enum_@GlobalScope_ButtonList )` Capturing mouse buttons is very similar to handling key events. `@GlobalScope_ButtonList ( enum_@GlobalScope_ButtonList )`
contains a list of `BUTTON_*` constants for each possible button, which will contains a list of `BUTTON_*` constants for each possible button, which will
@ -223,8 +213,7 @@ gdscript GDScript
print("Wheel up") print("Wheel up")
``` ```
Mouse motion ### Mouse motion
~~~~~~~~~~~~
`InputEventMouseMotion` events occur whenever `InputEventMouseMotion` events occur whenever
the mouse moves. You can find the move's distance with the `relative` the mouse moves. You can find the move's distance with the `relative`
@ -258,8 +247,7 @@ gdscript GDScript
$Sprite.position = event.position $Sprite.position = event.position
``` ```
Touch events ## Touch events
------------
If you are using a touchscreen device, you can generate touch events. If you are using a touchscreen device, you can generate touch events.
`InputEventScreenTouch` is equivalent to `InputEventScreenTouch` is equivalent to

View File

@ -1,24 +1,20 @@
Mouse and input coordinates # Mouse and input coordinates
===========================
About ## About
-----
The reason for this small tutorial is to clear up many common mistakes The reason for this small tutorial is to clear up many common mistakes
about input coordinates, obtaining mouse position and screen resolution, about input coordinates, obtaining mouse position and screen resolution,
etc. etc.
Hardware display coordinates ## Hardware display coordinates
----------------------------
Using hardware coordinates makes sense in the case of writing complex Using hardware coordinates makes sense in the case of writing complex
UIs meant to run on PC, such as editors, MMOs, tools, etc. However, it does UIs meant to run on PC, such as editors, MMOs, tools, etc. However, it does
not make as much sense outside of that scope. not make as much sense outside of that scope.
Viewport display coordinates ## Viewport display coordinates
----------------------------
Pandemonium uses viewports to display content, and viewports can be scaled by Pandemonium uses viewports to display content, and viewports can be scaled by
several options (see `doc_multiple_resolutions` tutorial). Use, then, the several options (see `doc_multiple_resolutions` tutorial). Use, then, the

View File

@ -1,7 +1,6 @@
Customizing the mouse cursor # Customizing the mouse cursor
============================
You might want to change the appearance of the mouse cursor in your game in order to suit the overall design. There are two ways to customize the mouse cursor: You might want to change the appearance of the mouse cursor in your game in order to suit the overall design. There are two ways to customize the mouse cursor:
@ -22,8 +21,7 @@ Note:
If you have to use the "software" approach, consider adding an extrapolation step If you have to use the "software" approach, consider adding an extrapolation step
to better display the actual mouse input. to better display the actual mouse input.
Using project settings ## Using project settings
----------------------
Open project settings, go to Display>Mouse Cursor. You will see Custom Image and Custom Image Hotspot. Open project settings, go to Display>Mouse Cursor. You will see Custom Image and Custom Image Hotspot.
@ -35,8 +33,7 @@ Custom Hotspot is the point in the image that you would like to use as the curso
Note: Note:
The custom image **must** be less than 256x256. The custom image **must** be less than 256x256.
Using a script ## Using a script
--------------
Create a Node and attach the following script. Create a Node and attach the following script.
@ -65,13 +62,11 @@ Note:
Check `Input.set_custom_mouse_cursor()`. Check `Input.set_custom_mouse_cursor()`.
Demo project ## Demo project
------------
Find out more by studying this demo project: Find out more by studying this demo project:
https://github.com/guilhermefelipecgs/custom_hardware_cursor https://github.com/guilhermefelipecgs/custom_hardware_cursor
Cursor list ## Cursor list
-----------
As documented in the `Input` class (see the **CursorShape** enum), there are multiple mouse cursors you can define. Which ones you want to use depends on your use case. As documented in the `Input` class (see the **CursorShape** enum), there are multiple mouse cursors you can define. Which ones you want to use depends on your use case.

View File

@ -1,18 +1,14 @@
# Handling quit requests
Handling quit requests ## Quitting
======================
Quitting
--------
Most platforms have the option to request the application to quit. On Most platforms have the option to request the application to quit. On
desktops, this is usually done with the "x" icon on the window title bar. desktops, this is usually done with the "x" icon on the window title bar.
On Android, the back button is used to quit when on the main screen (and On Android, the back button is used to quit when on the main screen (and
to go back otherwise). to go back otherwise).
Handling the notification ## Handling the notification
-------------------------
On desktop platforms, the `MainLoop` On desktop platforms, the `MainLoop`
has a special `MainLoop.NOTIFICATION_WM_QUIT_REQUEST` notification that is has a special `MainLoop.NOTIFICATION_WM_QUIT_REQUEST` notification that is
@ -51,8 +47,7 @@ gdscript GDScript
get_tree().set_auto_accept_quit(false) get_tree().set_auto_accept_quit(false)
``` ```
Sending your own quit notification ## Sending your own quit notification
----------------------------------
While forcing the application to close can be done by calling `SceneTree.quit`, While forcing the application to close can be done by calling `SceneTree.quit`,
doing so will not send the quit *notification*. This means the function doing so will not send the quit *notification*. This means the function

View File

@ -1,7 +1,6 @@
Controllers, gamepads, and joysticks # Controllers, gamepads, and joysticks
====================================
Pandemonium supports hundreds of controller models thanks to the community-sourced Pandemonium supports hundreds of controller models thanks to the community-sourced
`SDL game controller database ( https://github.com/gabomdq/SDL_GameControllerDB )`. `SDL game controller database ( https://github.com/gabomdq/SDL_GameControllerDB )`.
@ -21,8 +20,7 @@ In this guide, you will learn:
- **How controllers can behave differently from keyboard/mouse input.** - **How controllers can behave differently from keyboard/mouse input.**
- **Troubleshooting issues with controllers in Pandemonium.** - **Troubleshooting issues with controllers in Pandemonium.**
Supporting universal input ## Supporting universal input
--------------------------
Thanks to Pandemonium's input action system, Pandemonium makes it possible to support both Thanks to Pandemonium's input action system, Pandemonium makes it possible to support both
keyboard and controller input without having to write separate code paths. keyboard and controller input without having to write separate code paths.
@ -39,8 +37,7 @@ Note:
action (such as looking around in a first-person game) will require action (such as looking around in a first-person game) will require
different code paths since these have to be handled separately. different code paths since these have to be handled separately.
Which Input singleton method should I use? #### Which Input singleton method should I use?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There are 3 ways to get input in an analog-aware way: There are 3 ways to get input in an analog-aware way:
@ -101,14 +98,12 @@ In Pandemonium versions before 3.4, such as 3.3, `Input.get_vector()` and
`Input.get_axis()` aren't available. Only `Input.get_action_strength()` `Input.get_axis()` aren't available. Only `Input.get_action_strength()`
and `Input.is_action_pressed()` are available in Pandemonium 3.3. and `Input.is_action_pressed()` are available in Pandemonium 3.3.
Differences between keyboard/mouse and controller input ## Differences between keyboard/mouse and controller input
-------------------------------------------------------
If you're used to handling keyboard and mouse input, you may be surprised by how If you're used to handling keyboard and mouse input, you may be surprised by how
controllers handle specific situations. controllers handle specific situations.
Dead zone #### Dead zone
^^^^^^^^^
Unlike keyboards and mice, controllers offer axes with *analog* inputs. The Unlike keyboards and mice, controllers offer axes with *analog* inputs. The
upside of analog inputs is that they offer additional flexibility for actions. upside of analog inputs is that they offer additional flexibility for actions.
@ -135,8 +130,7 @@ in the Project Settings' Input Map tab.
For `Input.get_vector()`, the deadzone can be specified, or otherwise it For `Input.get_vector()`, the deadzone can be specified, or otherwise it
will calculate the average deadzone value from all of the actions in the vector. will calculate the average deadzone value from all of the actions in the vector.
"Echo" events #### "Echo" events
^^^^^^^^^^^^^
Unlike keyboard input, holding down a controller button such as a D-pad Unlike keyboard input, holding down a controller button such as a D-pad
direction will **not** generate repeated input events at fixed intervals (also direction will **not** generate repeated input events at fixed intervals (also
@ -149,25 +143,21 @@ If you want controller buttons to send echo events, you will have to generate
at regular intervals. This can be accomplished at regular intervals. This can be accomplished
with the help of a `Timer` node. with the help of a `Timer` node.
Troubleshooting ## Troubleshooting
---------------
See also: See also:
You can view a list of You can view a list of
`known issues with controller support ( https://github.com/Relintai/pandemonium_engine/issues?q=is%3Aopen+is%3Aissue+label%3Atopic%3Ainput+gamepad )` `known issues with controller support ( https://github.com/Relintai/pandemonium_engine/issues?q=is%3Aopen+is%3Aissue+label%3Atopic%3Ainput+gamepad )`
on GitHub. on GitHub.
My controller isn't recognized by Pandemonium. #### My controller isn't recognized by Pandemonium.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
First, check that your controller is recognized by other applications. You can First, check that your controller is recognized by other applications. You can
use the `Gamepad Tester ( https://gamepad-tester.com/ )` website to confirm that use the `Gamepad Tester ( https://gamepad-tester.com/ )` website to confirm that
your controller is recognized. your controller is recognized.
My controller has incorrectly mapped buttons or axes. #### My controller has incorrectly mapped buttons or axes.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If buttons are incorrectly mapped, this may be due to an erroneous mapping from If buttons are incorrectly mapped, this may be due to an erroneous mapping from
the `SDL game controller database ( https://github.com/gabomdq/SDL_GameControllerDB )`. the `SDL game controller database ( https://github.com/gabomdq/SDL_GameControllerDB )`.
@ -205,19 +195,16 @@ additional controller mappings, you can add them by calling
`Input.add_joy_mapping()` `Input.add_joy_mapping()`
as early as possible in a script's `ready()` function. as early as possible in a script's `ready()` function.
My controller works on a given platform, but not on another platform. #### My controller works on a given platform, but not on another platform.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Linux ### Linux
~~~~~
Prior to Pandemonium 3.3, official Pandemonium binaries were compiled with udev support Prior to Pandemonium 3.3, official Pandemonium binaries were compiled with udev support
but self-compiled binaries were compiled *without* udev support unless but self-compiled binaries were compiled *without* udev support unless
`udev=yes` was passed on the SCons command line. This made controller `udev=yes` was passed on the SCons command line. This made controller
hotplugging support unavailable in self-compiled binaries. hotplugging support unavailable in self-compiled binaries.
HTML5 ### HTML5
~~~~~
HTML5 controller support is often less reliable compared to "native" platforms. HTML5 controller support is often less reliable compared to "native" platforms.
The quality of controller support tends to vary wildly across browsers. As a The quality of controller support tends to vary wildly across browsers. As a

View File

@ -1,7 +1,6 @@
Background loading # Background loading
==================
When switching the main scene of your game (e.g. going to a new When switching the main scene of your game (e.g. going to a new
level), you might want to show a loading screen with some indication level), you might want to show a loading screen with some indication
@ -11,8 +10,7 @@ thread, making your game appear frozen and unresponsive while the resource is be
document discusses the alternative of using the `ResourceInteractiveLoader` class for smoother document discusses the alternative of using the `ResourceInteractiveLoader` class for smoother
load screens. load screens.
ResourceInteractiveLoader ## ResourceInteractiveLoader
-------------------------
The `ResourceInteractiveLoader` class allows you to load a resource in The `ResourceInteractiveLoader` class allows you to load a resource in
stages. Every time the method `poll` is called, a new stage is loaded, stages. Every time the method `poll` is called, a new stage is loaded,
@ -20,13 +18,11 @@ and control is returned to the caller. Each stage is generally a
sub-resource that is loaded by the main resource. For example, if you're sub-resource that is loaded by the main resource. For example, if you're
loading a scene that loads 10 images, each image will be one stage. loading a scene that loads 10 images, each image will be one stage.
Usage ## Usage
-----
Usage is generally as follows Usage is generally as follows
Obtaining a ResourceInteractiveLoader ### Obtaining a ResourceInteractiveLoader
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``` ```
Ref( ResourceInteractiveLoader> ResourceLoader::load_interactive(String p_path); Ref( ResourceInteractiveLoader> ResourceLoader::load_interactive(String p_path);
@ -35,8 +31,7 @@ Obtaining a ResourceInteractiveLoader
This method will give you a ResourceInteractiveLoader that you will use This method will give you a ResourceInteractiveLoader that you will use
to manage the load operation. to manage the load operation.
Polling ### Polling
~~~~~~~
``` ```
Error ResourceInteractiveLoader::poll(); Error ResourceInteractiveLoader::poll();
@ -50,8 +45,7 @@ so it will take several frames to load.
Returns `OK` on no errors, `ERR_FILE_EOF` when loading is finished. Returns `OK` on no errors, `ERR_FILE_EOF` when loading is finished.
Any other return value means there was an error and loading has stopped. Any other return value means there was an error and loading has stopped.
Load progress (optional) ### Load progress (optional)
~~~~~~~~~~~~~~~~~~~~~~~~
To query the progress of the load, use the following methods: To query the progress of the load, use the following methods:
@ -63,8 +57,7 @@ To query the progress of the load, use the following methods:
`get_stage_count` returns the total number of stages to load. `get_stage_count` returns the total number of stages to load.
`get_stage` returns the current stage being loaded. `get_stage` returns the current stage being loaded.
Forcing completion (optional) ### Forcing completion (optional)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``` ```
Error ResourceInteractiveLoader::wait(); Error ResourceInteractiveLoader::wait();
@ -73,8 +66,7 @@ Forcing completion (optional)
Use this method if you need to load the entire resource in the current Use this method if you need to load the entire resource in the current
frame, without any more steps. frame, without any more steps.
Obtaining the resource ### Obtaining the resource
~~~~~~~~~~~~~~~~~~~~~~
``` ```
Ref<Resource> ResourceInteractiveLoader::get_resource(); Ref<Resource> ResourceInteractiveLoader::get_resource();
@ -83,8 +75,7 @@ Obtaining the resource
If everything goes well, use this method to retrieve your loaded If everything goes well, use this method to retrieve your loaded
resource. resource.
Example ## Example
-------
This example demonstrates how to load a new scene. Consider it in the This example demonstrates how to load a new scene. Consider it in the
context of the `doc_singletons_autoload` example. context of the `doc_singletons_autoload` example.
@ -195,20 +186,17 @@ loader.
get_node("/root").add_child(current_scene) get_node("/root").add_child(current_scene)
``` ```
Using multiple threads ## Using multiple threads
----------------------
ResourceInteractiveLoader can be used from multiple threads. A couple of ResourceInteractiveLoader can be used from multiple threads. A couple of
things to keep in mind if you attempt it: things to keep in mind if you attempt it:
Use a semaphore ### Use a semaphore
~~~~~~~~~~~~~~~
While your thread waits for the main thread to request a new resource, While your thread waits for the main thread to request a new resource,
use a `Semaphore` to sleep (instead of a busy loop or anything similar). use a `Semaphore` to sleep (instead of a busy loop or anything similar).
Not blocking main thread during the polling ### Not blocking main thread during the polling
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you have a mutex to allow calls from the main thread to your loader If you have a mutex to allow calls from the main thread to your loader
class, don't lock the main thread while you call `poll` on your loader class. When a class, don't lock the main thread while you call `poll` on your loader class. When a
@ -218,8 +206,7 @@ thread to acquire them. This might cause a deadlock if the main thread
is waiting for your mutex while your thread is waiting to load a is waiting for your mutex while your thread is waiting to load a
resource. resource.
Example class ## Example class
-------------
You can find an example class for loading resources in threads here: You can find an example class for loading resources in threads here:
:download:`resource_queue.gd ( files/resource_queue.gd )`. Usage is as follows: :download:`resource_queue.gd ( files/resource_queue.gd )`. Usage is as follows:
@ -268,8 +255,7 @@ not fully loaded (`is_ready` returns `false`), it will block your thread
and finish the load. If the resource is not on the queue, it will call and finish the load. If the resource is not on the queue, it will call
`ResourceLoader::load` to load it normally and return it. `ResourceLoader::load` to load it normally and return it.
Example: ### Example:
~~~~~~~~
``` ```
# Initialize. # Initialize.

View File

@ -1,14 +1,12 @@
File paths in Pandemonium projects # File paths in Pandemonium projects
============================
This page explains how file paths work inside Pandemonium projects. You will learn how This page explains how file paths work inside Pandemonium projects. You will learn how
to access paths in your projects using the `res://` and `user://` notations, to access paths in your projects using the `res://` and `user://` notations,
and where Pandemonium stores project and editor files on your and your users' systems. and where Pandemonium stores project and editor files on your and your users' systems.
Path separators ## Path separators
---------------
To make supporting multiple platforms easier, Pandemonium uses **UNIX-style path To make supporting multiple platforms easier, Pandemonium uses **UNIX-style path
separators** (forward slash `/`). These work on all platforms, **including separators** (forward slash `/`). These work on all platforms, **including
@ -25,8 +23,7 @@ This makes it possible to work with paths returned by other Windows
applications. We still recommend using only forward slashes in your own code to applications. We still recommend using only forward slashes in your own code to
guarantee that everything will work as intended. guarantee that everything will work as intended.
Accessing files in the project folder (`res://`) ## Accessing files in the project folder (`res://`)
--------------------------------------------------
Pandemonium considers that a project exists in any folder that contains a Pandemonium considers that a project exists in any folder that contains a
`project.pandemonium` text file, even if the file is empty. The folder that contains `project.pandemonium` text file, even if the file is empty. The folder that contains
@ -37,8 +34,7 @@ You can access any file relative to it by writing paths starting with
file `character.png)` located in the project's root folder in code with the file `character.png)` located in the project's root folder in code with the
following path: `res://character.png)`. following path: `res://character.png)`.
Accessing persistent user data (`user://`) ## Accessing persistent user data (`user://`)
--------------------------------------------
To store persistent data files, like the player's save or settings, you want to To store persistent data files, like the player's save or settings, you want to
use `user://` instead of `res://` as your path's prefix. This is because use `user://` instead of `res://` as your path's prefix. This is because
@ -68,21 +64,17 @@ Project Settings:
On desktop platforms, the actual directory paths for `user://` are: On desktop platforms, the actual directory paths for `user://` are:
+---------------------+------------------------------------------------------------------------------+
| Type | Location | | Type | Location |
+=====================+==============================================================================+ |---------------------|--------------------------------------------------------------------------------|
| Default | | Windows: `%APPDATA%\Pandemonium\app_userdata\[project_name]` | | Default | Windows: `%APPDATA%\Pandemonium\app_userdata\[project_name]` |
| | | macOS: `~/Library/Application Support/Pandemonium/app_userdata/[project_name]` | | | macOS: `~/Library/Application Support/Pandemonium/app_userdata/[project_name]` |
| | | Linux: `~/.local/share/pandemonium/app_userdata/[project_name]` | | | Linux: `~/.local/share/pandemonium/app_userdata/[project_name]` |
+---------------------+------------------------------------------------------------------------------+ | Custom dir | Windows: `%APPDATA%\[project_name]` |
| Custom dir | | Windows: `%APPDATA%\[project_name]` | | | macOS: `~/Library/Application Support/[project_name]` |
| | | macOS: `~/Library/Application Support/[project_name]` | | | Linux: `~/.local/share/[project_name]` |
| | | Linux: `~/.local/share/[project_name]` | | Custom dir and name | Windows: `%APPDATA%\[custom_user_dir_name]` |
+---------------------+------------------------------------------------------------------------------+ | | macOS: `~/Library/Application Support/[custom_user_dir_name]` |
| Custom dir and name | | Windows: `%APPDATA%\[custom_user_dir_name]` | | | Linux: `~/.local/share/[custom_user_dir_name]` |
| | | macOS: `~/Library/Application Support/[custom_user_dir_name]` |
| | | Linux: `~/.local/share/[custom_user_dir_name]` |
+---------------------+------------------------------------------------------------------------------+
`[project_name]` is based on the application name defined in the Project Settings, but `[project_name]` is based on the application name defined in the Project Settings, but
you can override it on a per-platform basis using `feature tags ( doc_feature_tags )`. you can override it on a per-platform basis using `feature tags ( doc_feature_tags )`.
@ -94,8 +86,7 @@ On HTML5 exports, `user://` will refer to a virtual filesystem stored on the
device via IndexedDB. (Interaction with the main filesystem can still be performed device via IndexedDB. (Interaction with the main filesystem can still be performed
through the `JavaScript` singleton.) through the `JavaScript` singleton.)
Converting paths to absolute paths or "local" paths ## Converting paths to absolute paths or "local" paths
---------------------------------------------------
You can use `ProjectSettings.globalize_path()` You can use `ProjectSettings.globalize_path()`
to convert a "local" path like `res://path/to/file.txt` to an absolute OS path. to convert a "local" path like `res://path/to/file.txt` to an absolute OS path.
@ -111,27 +102,22 @@ project's root or `user://` folders.
Editor data paths ## Editor data paths
-----------------
The editor uses different paths for editor data, editor settings, and cache, The editor uses different paths for editor data, editor settings, and cache,
depending on the platform. By default, these paths are: depending on the platform. By default, these paths are:
+-----------------+---------------------------------------------------+
| Type | Location | | Type | Location |
+=================+===================================================+ |-----------------|-----------------------------------------------------|
| Editor data | | Windows: `%APPDATA%\Pandemonium\` | | Editor data | Windows: `%APPDATA%\Pandemonium\` |
| | | macOS: `~/Library/Application Support/Pandemonium/` | | | macOS: `~/Library/Application Support/Pandemonium/` |
| | | Linux: `~/.local/share/pandemonium/` | | | Linux: `~/.local/share/pandemonium/` |
+-----------------+---------------------------------------------------+ | Editor settings | Windows: `%APPDATA%\Pandemonium\` |
| Editor settings | | Windows: `%APPDATA%\Pandemonium\` | | | macOS: `~/Library/Application Support/Pandemonium/` |
| | | macOS: `~/Library/Application Support/Pandemonium/` | | | Linux: `~/.config/pandemonium/` |
| | | Linux: `~/.config/pandemonium/` | | Cache | Windows: `%TEMP%\Pandemonium\` |
+-----------------+---------------------------------------------------+ | | macOS: `~/Library/Caches/Pandemonium/` |
| Cache | | Windows: `%TEMP%\Pandemonium\` | | | Linux: `~/.cache/pandemonium/` |
| | | macOS: `~/Library/Caches/Pandemonium/` |
| | | Linux: `~/.cache/pandemonium/` |
+-----------------+---------------------------------------------------+
- **Editor data** contains export templates and project-specific data. - **Editor data** contains export templates and project-specific data.
- **Editor settings** contains the main editor settings configuration file as - **Editor settings** contains the main editor settings configuration file as
@ -153,8 +139,7 @@ Note:
Self-contained mode ### Self-contained mode
~~~~~~~~~~~~~~~~~~~
If you create a file called `._sc_` or `sc_` in the same directory as the If you create a file called `._sc_` or `sc_` in the same directory as the
editor binary (or in `MacOS/Contents/` for a macOS editor .app bundle), Pandemonium editor binary (or in `MacOS/Contents/` for a macOS editor .app bundle), Pandemonium

View File

@ -1,10 +1,8 @@
Saving games # Saving games
============
Introduction ## Introduction
------------
Save games can be complicated. For example, it may be desirable Save games can be complicated. For example, it may be desirable
to store information from multiple objects across multiple levels. to store information from multiple objects across multiple levels.
@ -18,8 +16,7 @@ Note:
If you're looking to save user configuration, you can use the If you're looking to save user configuration, you can use the
`ConfigFile` class for this purpose. `ConfigFile` class for this purpose.
Identify persistent objects ## Identify persistent objects
---------------------------
Firstly, we should identify what objects we want to keep between game Firstly, we should identify what objects we want to keep between game
sessions and what information we want to keep from those objects. For sessions and what information we want to keep from those objects. For
@ -43,8 +40,7 @@ gdscript GDScript
# Now, we can call our save function on each node. # Now, we can call our save function on each node.
``` ```
Serializing ## Serializing
-----------
The next step is to serialize the data. This makes it much easier to The next step is to serialize the data. This makes it much easier to
read from and store to disk. In this case, we're assuming each member of read from and store to disk. In this case, we're assuming each member of
@ -87,8 +83,7 @@ This gives us a dictionary with the style
`{ "variable_name":value_of_variable }`, which will be useful when `{ "variable_name":value_of_variable }`, which will be useful when
loading. loading.
Saving and reading data ## Saving and reading data
-----------------------
As covered in the `doc_filesystem` tutorial, we'll need to open a file As covered in the `doc_filesystem` tutorial, we'll need to open a file
so we can write to it or read from it. Now that we have a way to so we can write to it or read from it. Now that we have a way to
@ -178,8 +173,7 @@ Now we can save and load an arbitrary number of objects laid out
almost anywhere across the scene tree! Each object can store different almost anywhere across the scene tree! Each object can store different
data depending on what it needs to save. data depending on what it needs to save.
Some notes ## Some notes
----------
We have glossed over setting up the game state for loading. It's ultimately up We have glossed over setting up the game state for loading. It's ultimately up
to the project creator where much of this logic goes. to the project creator where much of this logic goes.

View File

@ -1,10 +1,8 @@
Binary serialization API # Binary serialization API
========================
Introduction ## Introduction
------------
Pandemonium has a simple serialization API based on Variant. It's used for Pandemonium has a simple serialization API based on Variant. It's used for
converting data types to an array of bytes efficiently. This API is used converting data types to an array of bytes efficiently. This API is used
@ -12,8 +10,7 @@ in the functions `get_var` and `store_var` of `File`
as well as the packet APIs for `PacketPeer`. This format as well as the packet APIs for `PacketPeer`. This format
is *not* used for binary scenes and resources. is *not* used for binary scenes and resources.
Packet specification ## Packet specification
--------------------
The packet is designed to be always padded to 4 bytes. All values are The packet is designed to be always padded to 4 bytes. All values are
little-endian-encoded. All packets have a 4-byte header representing an little-endian-encoded. All packets have a 4-byte header representing an
@ -27,65 +24,36 @@ two bytes contain flags
flags = val >> 16; flags = val >> 16;
``` ```
+--------+--------------------------+
| Type | Value | | Type | Value |
+========+==========================+ |--------|--------------------------|
| 0 | null | | 0 | null |
+--------+--------------------------+
| 1 | bool | | 1 | bool |
+--------+--------------------------+
| 2 | integer | | 2 | integer |
+--------+--------------------------+
| 3 | float | | 3 | float |
+--------+--------------------------+
| 4 | string | | 4 | string |
+--------+--------------------------+
| 5 | vector2 | | 5 | vector2 |
+--------+--------------------------+
| 6 | rect2 | | 6 | rect2 |
+--------+--------------------------+
| 7 | vector3 | | 7 | vector3 |
+--------+--------------------------+
| 8 | transform2d | | 8 | transform2d |
+--------+--------------------------+
| 9 | plane | | 9 | plane |
+--------+--------------------------+
| 10 | quat | | 10 | quat |
+--------+--------------------------+
| 11 | aabb | | 11 | aabb |
+--------+--------------------------+
| 12 | basis | | 12 | basis |
+--------+--------------------------+
| 13 | transform | | 13 | transform |
+--------+--------------------------+
| 14 | color | | 14 | color |
+--------+--------------------------+
| 15 | node path | | 15 | node path |
+--------+--------------------------+
| 16 | rid | | 16 | rid |
+--------+--------------------------+
| 17 | object | | 17 | object |
+--------+--------------------------+
| 18 | dictionary | | 18 | dictionary |
+--------+--------------------------+
| 19 | array | | 19 | array |
+--------+--------------------------+
| 20 | raw array | | 20 | raw array |
+--------+--------------------------+
| 21 | int array | | 21 | int array |
+--------+--------------------------+
| 22 | real array | | 22 | real array |
+--------+--------------------------+
| 23 | string array | | 23 | string array |
+--------+--------------------------+
| 24 | vector2 array | | 24 | vector2 array |
+--------+--------------------------+
| 25 | vector3 array | | 25 | vector3 array |
+--------+--------------------------+
| 26 | color array | | 26 | color array |
+--------+--------------------------+
| 27 | max | | 27 | max |
+--------+--------------------------+
Following this is the actual packet contents, which varies for each type of Following this is the actual packet contents, which varies for each type of
packet. Note that this assumes Pandemonium is compiled with single-precision floats, packet. Note that this assumes Pandemonium is compiled with single-precision floats,
@ -94,419 +62,293 @@ length of "Float" fields within data structures should be 8, and the offset
should be `(offset - 4) * 2 + 4`. The "float" type itself always uses double should be `(offset - 4) * 2 + 4`. The "float" type itself always uses double
precision. precision.
0: null ### 0: null
~~~~~~~
1: `bool( bool )` ### 1: `bool( bool )`
~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+-----------+---------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+===========+===========================+ |----------|-------|-----------|---------------------------|
| 4 | 4 | Integer | 0 for False, 1 for True | | 4 | 4 | Integer | 0 for False, 1 for True |
+----------+-------+-----------+---------------------------+
2: `int( int )` ### 2: `int( int )`
~~~~~~~~~~~~~~~~~~~~~~~~
If no flags are set (flags == 0), the integer is sent as a 32 bit integer: If no flags are set (flags == 0), the integer is sent as a 32 bit integer:
+----------+-------+-----------+--------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+===========+==========================+ |----------|-------|-----------|--------------------------|
| 4 | 4 | Integer | 32-bit signed integer | | 4 | 4 | Integer | 32-bit signed integer |
+----------+-------+-----------+--------------------------+
If flag `ENCODE_FLAG_64` is set (`flags & 1 == 1`), the integer is sent as If flag `ENCODE_FLAG_64` is set (`flags & 1 == 1`), the integer is sent as
a 64-bit integer: a 64-bit integer:
+----------+-------+-----------+--------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+===========+==========================+ |----------|-------|-----------|--------------------------|
| 4 | 8 | Integer | 64-bit signed integer | | 4 | 8 | Integer | 64-bit signed integer |
+----------+-------+-----------+--------------------------+
3: `float( float )` ### 3: `float( float )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If no flags are set (flags == 0), the float is sent as a 32 bit single precision: If no flags are set (flags == 0), the float is sent as a 32 bit single precision:
+----------+-------+---------+-----------------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+===================================+ |----------|-------|---------|-----------------------------------|
| 4 | 4 | Float | IEEE 754 single-precision float | | 4 | 4 | Float | IEEE 754 single-precision float |
+----------+-------+---------+-----------------------------------+
If flag `ENCODE_FLAG_64` is set (`flags & 1 == 1`), the float is sent as If flag `ENCODE_FLAG_64` is set (`flags & 1 == 1`), the float is sent as
a 64-bit double precision number: a 64-bit double precision number:
+----------+-------+---------+-----------------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+===================================+ |----------|-------|---------|-----------------------------------|
| 4 | 8 | Float | IEEE 754 double-precision float | | 4 | 8 | Float | IEEE 754 double-precision float |
+----------+-------+---------+-----------------------------------+
4: `String( string )` ### 4: `String( string )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+-----------+----------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+===========+============================+ |----------|-------|-----------|----------------------------|
| 4 | 4 | Integer | String length (in bytes) | | 4 | 4 | Integer | String length (in bytes) |
+----------+-------+-----------+----------------------------+
| 8 | X | Bytes | UTF-8 encoded string | | 8 | X | Bytes | UTF-8 encoded string |
+----------+-------+-----------+----------------------------+
This field is padded to 4 bytes. This field is padded to 4 bytes.
5: `Vector2( vector2 )` ### 5: `Vector2( vector2 )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+---------+----------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+================+ |----------|-------|---------|----------------|
| 4 | 4 | Float | X coordinate | | 4 | 4 | Float | X coordinate |
+----------+-------+---------+----------------+
| 8 | 4 | Float | Y coordinate | | 8 | 4 | Float | Y coordinate |
+----------+-------+---------+----------------+
6: `Rect2( rect2 )` ### 6: `Rect2( rect2 )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+---------+----------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+================+ |----------|-------|---------|----------------|
| 4 | 4 | Float | X coordinate | | 4 | 4 | Float | X coordinate |
+----------+-------+---------+----------------+
| 8 | 4 | Float | Y coordinate | | 8 | 4 | Float | Y coordinate |
+----------+-------+---------+----------------+
| 12 | 4 | Float | X size | | 12 | 4 | Float | X size |
+----------+-------+---------+----------------+
| 16 | 4 | Float | Y size | | 16 | 4 | Float | Y size |
+----------+-------+---------+----------------+
7: `Vector3( vector3 )` ### 7: `Vector3( vector3 )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+---------+----------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+================+ |----------|-------|---------|----------------|
| 4 | 4 | Float | X coordinate | | 4 | 4 | Float | X coordinate |
+----------+-------+---------+----------------+
| 8 | 4 | Float | Y coordinate | | 8 | 4 | Float | Y coordinate |
+----------+-------+---------+----------------+
| 12 | 4 | Float | Z coordinate | | 12 | 4 | Float | Z coordinate |
+----------+-------+---------+----------------+
8: `Transform2D( transform2d )` ### 8: `Transform2D( transform2d )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+---------+---------------------------------------------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+===============================================================+ |----------|-------|---------|---------------------------------------------------------------|
| 4 | 4 | Float | The X component of the X column vector, accessed via [0][0] | | 4 | 4 | Float | The X component of the X column vector, accessed via [0][0] |
+----------+-------+---------+---------------------------------------------------------------+
| 8 | 4 | Float | The Y component of the X column vector, accessed via [0][1] | | 8 | 4 | Float | The Y component of the X column vector, accessed via [0][1] |
+----------+-------+---------+---------------------------------------------------------------+
| 12 | 4 | Float | The X component of the Y column vector, accessed via [1][0] | | 12 | 4 | Float | The X component of the Y column vector, accessed via [1][0] |
+----------+-------+---------+---------------------------------------------------------------+
| 16 | 4 | Float | The Y component of the Y column vector, accessed via [1][1] | | 16 | 4 | Float | The Y component of the Y column vector, accessed via [1][1] |
+----------+-------+---------+---------------------------------------------------------------+
| 20 | 4 | Float | The X component of the origin vector, accessed via [2][0] | | 20 | 4 | Float | The X component of the origin vector, accessed via [2][0] |
+----------+-------+---------+---------------------------------------------------------------+
| 24 | 4 | Float | The Y component of the origin vector, accessed via [2][1] | | 24 | 4 | Float | The Y component of the origin vector, accessed via [2][1] |
+----------+-------+---------+---------------------------------------------------------------+
9: `Plane( plane )` ### 9: `Plane( plane )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+---------+---------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+===============+ |----------|-------|---------|---------------|
| 4 | 4 | Float | Normal X | | 4 | 4 | Float | Normal X |
+----------+-------+---------+---------------+
| 8 | 4 | Float | Normal Y | | 8 | 4 | Float | Normal Y |
+----------+-------+---------+---------------+
| 12 | 4 | Float | Normal Z | | 12 | 4 | Float | Normal Z |
+----------+-------+---------+---------------+
| 16 | 4 | Float | Distance | | 16 | 4 | Float | Distance |
+----------+-------+---------+---------------+
10: `Quat( quat )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+---------+---------------+ ### 10: `Quat( quat )`
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+===============+ |----------|-------|---------|---------------|
| 4 | 4 | Float | Imaginary X | | 4 | 4 | Float | Imaginary X |
+----------+-------+---------+---------------+
| 8 | 4 | Float | Imaginary Y | | 8 | 4 | Float | Imaginary Y |
+----------+-------+---------+---------------+
| 12 | 4 | Float | Imaginary Z | | 12 | 4 | Float | Imaginary Z |
+----------+-------+---------+---------------+
| 16 | 4 | Float | Real W | | 16 | 4 | Float | Real W |
+----------+-------+---------+---------------+
11: `AABB( aabb )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+---------+----------------+ ### 11: `AABB( aabb )`
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+================+ |----------|-------|---------|----------------|
| 4 | 4 | Float | X coordinate | | 4 | 4 | Float | X coordinate |
+----------+-------+---------+----------------+
| 8 | 4 | Float | Y coordinate | | 8 | 4 | Float | Y coordinate |
+----------+-------+---------+----------------+
| 12 | 4 | Float | Z coordinate | | 12 | 4 | Float | Z coordinate |
+----------+-------+---------+----------------+
| 16 | 4 | Float | X size | | 16 | 4 | Float | X size |
+----------+-------+---------+----------------+
| 20 | 4 | Float | Y size | | 20 | 4 | Float | Y size |
+----------+-------+---------+----------------+
| 24 | 4 | Float | Z size | | 24 | 4 | Float | Z size |
+----------+-------+---------+----------------+
12: `Basis( basis )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+---------+---------------------------------------------------------------+ ### 12: `Basis( basis )`
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+===============================================================+ |----------|-------|---------|---------------------------------------------------------------|
| 4 | 4 | Float | The X component of the X column vector, accessed via [0][0] | | 4 | 4 | Float | The X component of the X column vector, accessed via [0][0] |
+----------+-------+---------+---------------------------------------------------------------+
| 8 | 4 | Float | The Y component of the X column vector, accessed via [0][1] | | 8 | 4 | Float | The Y component of the X column vector, accessed via [0][1] |
+----------+-------+---------+---------------------------------------------------------------+
| 12 | 4 | Float | The Z component of the X column vector, accessed via [0][2] | | 12 | 4 | Float | The Z component of the X column vector, accessed via [0][2] |
+----------+-------+---------+---------------------------------------------------------------+
| 16 | 4 | Float | The X component of the Y column vector, accessed via [1][0] | | 16 | 4 | Float | The X component of the Y column vector, accessed via [1][0] |
+----------+-------+---------+---------------------------------------------------------------+
| 20 | 4 | Float | The Y component of the Y column vector, accessed via [1][1] | | 20 | 4 | Float | The Y component of the Y column vector, accessed via [1][1] |
+----------+-------+---------+---------------------------------------------------------------+
| 24 | 4 | Float | The Z component of the Y column vector, accessed via [1][2] | | 24 | 4 | Float | The Z component of the Y column vector, accessed via [1][2] |
+----------+-------+---------+---------------------------------------------------------------+
| 28 | 4 | Float | The X component of the Z column vector, accessed via [2][0] | | 28 | 4 | Float | The X component of the Z column vector, accessed via [2][0] |
+----------+-------+---------+---------------------------------------------------------------+
| 32 | 4 | Float | The Y component of the Z column vector, accessed via [2][1] | | 32 | 4 | Float | The Y component of the Z column vector, accessed via [2][1] |
+----------+-------+---------+---------------------------------------------------------------+
| 36 | 4 | Float | The Z component of the Z column vector, accessed via [2][2] | | 36 | 4 | Float | The Z component of the Z column vector, accessed via [2][2] |
+----------+-------+---------+---------------------------------------------------------------+
13: `Transform( transform )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+---------+---------------------------------------------------------------+ ### 13: `Transform( transform )`
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+===============================================================+ |----------|-------|---------|---------------------------------------------------------------|
| 4 | 4 | Float | The X component of the X column vector, accessed via [0][0] | | 4 | 4 | Float | The X component of the X column vector, accessed via [0][0] |
+----------+-------+---------+---------------------------------------------------------------+
| 8 | 4 | Float | The Y component of the X column vector, accessed via [0][1] | | 8 | 4 | Float | The Y component of the X column vector, accessed via [0][1] |
+----------+-------+---------+---------------------------------------------------------------+
| 12 | 4 | Float | The Z component of the X column vector, accessed via [0][2] | | 12 | 4 | Float | The Z component of the X column vector, accessed via [0][2] |
+----------+-------+---------+---------------------------------------------------------------+
| 16 | 4 | Float | The X component of the Y column vector, accessed via [1][0] | | 16 | 4 | Float | The X component of the Y column vector, accessed via [1][0] |
+----------+-------+---------+---------------------------------------------------------------+
| 20 | 4 | Float | The Y component of the Y column vector, accessed via [1][1] | | 20 | 4 | Float | The Y component of the Y column vector, accessed via [1][1] |
+----------+-------+---------+---------------------------------------------------------------+
| 24 | 4 | Float | The Z component of the Y column vector, accessed via [1][2] | | 24 | 4 | Float | The Z component of the Y column vector, accessed via [1][2] |
+----------+-------+---------+---------------------------------------------------------------+
| 28 | 4 | Float | The X component of the Z column vector, accessed via [2][0] | | 28 | 4 | Float | The X component of the Z column vector, accessed via [2][0] |
+----------+-------+---------+---------------------------------------------------------------+
| 32 | 4 | Float | The Y component of the Z column vector, accessed via [2][1] | | 32 | 4 | Float | The Y component of the Z column vector, accessed via [2][1] |
+----------+-------+---------+---------------------------------------------------------------+
| 36 | 4 | Float | The Z component of the Z column vector, accessed via [2][2] | | 36 | 4 | Float | The Z component of the Z column vector, accessed via [2][2] |
+----------+-------+---------+---------------------------------------------------------------+
| 40 | 4 | Float | The X component of the origin vector, accessed via [3][0] | | 40 | 4 | Float | The X component of the origin vector, accessed via [3][0] |
+----------+-------+---------+---------------------------------------------------------------+
| 44 | 4 | Float | The Y component of the origin vector, accessed via [3][1] | | 44 | 4 | Float | The Y component of the origin vector, accessed via [3][1] |
+----------+-------+---------+---------------------------------------------------------------+
| 48 | 4 | Float | The Z component of the origin vector, accessed via [3][2] | | 48 | 4 | Float | The Z component of the origin vector, accessed via [3][2] |
+----------+-------+---------+---------------------------------------------------------------+
14: `Color( color )` ### 14: `Color( color )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+---------+--------------------------------------------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+==============================================================+ |----------|-------|---------|--------------------------------------------------------------|
| 4 | 4 | Float | Red (typically 0..1, can be above 1 for overbright colors) | | 4 | 4 | Float | Red (typically 0..1, can be above 1 for overbright colors) |
+----------+-------+---------+--------------------------------------------------------------+
| 8 | 4 | Float | Green (typically 0..1, can be above 1 for overbright colors) | | 8 | 4 | Float | Green (typically 0..1, can be above 1 for overbright colors) |
+----------+-------+---------+--------------------------------------------------------------+
| 12 | 4 | Float | Blue (typically 0..1, can be above 1 for overbright colors) | | 12 | 4 | Float | Blue (typically 0..1, can be above 1 for overbright colors) |
+----------+-------+---------+--------------------------------------------------------------+
| 16 | 4 | Float | Alpha (0..1) | | 16 | 4 | Float | Alpha (0..1) |
+----------+-------+---------+--------------------------------------------------------------+
15: `NodePath( nodepath )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+-----------+-----------------------------------------------------------------------------------------+ ### 15: `NodePath( nodepath )`
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+===========+=========================================================================================+ |----------|-------|-----------|-----------------------------------------------------------------------------------------|
| 4 | 4 | Integer | String length, or new format (val&0x80000000!=0 and NameCount=val&0x7FFFFFFF) | | 4 | 4 | Integer | String length, or new format (val&0x80000000!=0 and NameCount=val&0x7FFFFFFF) |
+----------+-------+-----------+-----------------------------------------------------------------------------------------+
For old format: #### For old format:
^^^^^^^^^^^^^^^
+----------+-------+---------+------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+=========+========================+ |----------|-------|---------|------------------------|
| 8 | X | Bytes | UTF-8 encoded string | | 8 | X | Bytes | UTF-8 encoded string |
+----------+-------+---------+------------------------+
Padded to 4 bytes. Padded to 4 bytes.
For new format: #### For new format:
^^^^^^^^^^^^^^^
+----------+-------+-----------+-------------------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+===========+=====================================+ |----------|-------|-----------|-------------------------------------|
| 4 | 4 | Integer | Sub-name count | | 4 | 4 | Integer | Sub-name count |
+----------+-------+-----------+-------------------------------------+
| 8 | 4 | Integer | Flags (absolute: val&1 != 0 ) | | 8 | 4 | Integer | Flags (absolute: val&1 != 0 ) |
+----------+-------+-----------+-------------------------------------+
For each Name and Sub-Name For each Name and Sub-Name
+----------+-------+-----------+------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+===========+========================+ |----------|-------|-----------|------------------------|
| X+0 | 4 | Integer | String length | | X+0 | 4 | Integer | String length |
+----------+-------+-----------+------------------------+
| X+4 | X | Bytes | UTF-8 encoded string | | X+4 | X | Bytes | UTF-8 encoded string |
+----------+-------+-----------+------------------------+
Every name string is padded to 4 bytes. Every name string is padded to 4 bytes.
16: `RID( rid )` (unsupported) ### 16: `RID( rid )` (unsupported)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17: `Object( object )` (unsupported) ### 17: `Object( object )` (unsupported)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18: `Dictionary( dictionary )` ### 18: `Dictionary( dictionary )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+-----------+---------------------------------------------------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+===========+=====================================================================+ |----------|-------|-----------|---------------------------------------------------------------------|
| 4 | 4 | Integer | val&0x7FFFFFFF = elements, val&0x80000000 = shared (bool) | | 4 | 4 | Integer | val&0x7FFFFFFF = elements, val&0x80000000 = shared (bool) |
+----------+-------+-----------+---------------------------------------------------------------------+
Then what follows is, for amount of "elements", pairs of key and value, Then what follows is, for amount of "elements", pairs of key and value,
one after the other, using this same format. one after the other, using this same format.
19: `Array( array )` ### 19: `Array( array )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+-----------+---------------------------------------------------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+===========+=====================================================================+ |----------|-------|-----------|---------------------------------------------------------------------|
| 4 | 4 | Integer | val&0x7FFFFFFF = elements, val&0x80000000 = shared (bool) | | 4 | 4 | Integer | val&0x7FFFFFFF = elements, val&0x80000000 = shared (bool) |
+----------+-------+-----------+---------------------------------------------------------------------+
Then what follows is, for amount of "elements", values one after the Then what follows is, for amount of "elements", values one after the
other, using this same format. other, using this same format.
20: `PoolByteArray( poolbytearray )` ### 20: `PoolByteArray( poolbytearray )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------+-------+-----------+------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+===============+=======+===========+========================+ |---------------|-------|-----------|------------------------|
| 4 | 4 | Integer | Array length (Bytes) | | 4 | 4 | Integer | Array length (Bytes) |
+---------------+-------+-----------+------------------------+
| 8..8+length | 1 | Byte | Byte (0..255) | | 8..8+length | 1 | Byte | Byte (0..255) |
+---------------+-------+-----------+------------------------+
The array data is padded to 4 bytes. The array data is padded to 4 bytes.
21: `PoolIntArray( poolintarray )` ### 21: `PoolIntArray( poolintarray )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------+-------+-----------+---------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==================+=======+===========+===========================+ |------------------|-------|-----------|---------------------------|
| 4 | 4 | Integer | Array length (Integers) | | 4 | 4 | Integer | Array length (Integers) |
+------------------+-------+-----------+---------------------------+
| 8..8+length\*4 | 4 | Integer | 32-bit signed integer | | 8..8+length\*4 | 4 | Integer | 32-bit signed integer |
+------------------+-------+-----------+---------------------------+
22: `PoolRealArray( poolrealarray )` ### 22: `PoolRealArray( poolrealarray )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------+-------+-----------+---------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==================+=======+===========+===========================+ |------------------|-------|-----------|---------------------------|
| 4 | 4 | Integer | Array length (Floats) | | 4 | 4 | Integer | Array length (Floats) |
+------------------+-------+-----------+---------------------------+
| 8..8+length\*4 | 4 | Integer | 32-bits IEEE 754 float | | 8..8+length\*4 | 4 | Integer | 32-bits IEEE 754 float |
+------------------+-------+-----------+---------------------------+
23: `PoolStringArray( poolstringarray )` ### 23: `PoolStringArray( poolstringarray )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------+-------+-----------+--------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+===========+==========================+ |----------|-------|-----------|--------------------------|
| 4 | 4 | Integer | Array length (Strings) | | 4 | 4 | Integer | Array length (Strings) |
+----------+-------+-----------+--------------------------+
For each String: For each String:
+----------+-------+-----------+------------------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+==========+=======+===========+========================+ |----------|-------|-----------|------------------------|
| X+0 | 4 | Integer | String length | | X+0 | 4 | Integer | String length |
+----------+-------+-----------+------------------------+
| X+4 | X | Bytes | UTF-8 encoded string | | X+4 | X | Bytes | UTF-8 encoded string |
+----------+-------+-----------+------------------------+
Every string is padded to 4 bytes. Every string is padded to 4 bytes.
24: `PoolVector2Array( poolvector2array )` ### 24: `PoolVector2Array( poolvector2array )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------+-------+-----------+----------------+
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+===================+=======+===========+================+ |-------------------|-------|-----------|----------------|
| 4 | 4 | Integer | Array length | | 4 | 4 | Integer | Array length |
+-------------------+-------+-----------+----------------+
| 8..8+length\*8 | 4 | Float | X coordinate | | 8..8+length\*8 | 4 | Float | X coordinate |
+-------------------+-------+-----------+----------------+
| 8..12+length\*8 | 4 | Float | Y coordinate | | 8..12+length\*8 | 4 | Float | Y coordinate |
+-------------------+-------+-----------+----------------+
25: `PoolVector3Array( poolvector3array )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------------------+-------+-----------+----------------+ ### 25: `PoolVector3Array( poolvector3array )`
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+====================+=======+===========+================+ |--------------------|-------|-----------|----------------|
| 4 | 4 | Integer | Array length | | 4 | 4 | Integer | Array length |
+--------------------+-------+-----------+----------------+
| 8..8+length\*12 | 4 | Float | X coordinate | | 8..8+length\*12 | 4 | Float | X coordinate |
+--------------------+-------+-----------+----------------+
| 8..12+length\*12 | 4 | Float | Y coordinate | | 8..12+length\*12 | 4 | Float | Y coordinate |
+--------------------+-------+-----------+----------------+
| 8..16+length\*12 | 4 | Float | Z coordinate | | 8..16+length\*12 | 4 | Float | Z coordinate |
+--------------------+-------+-----------+----------------+
26: `PoolColorArray( poolcolorarray )`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------------------+-------+-----------+--------------------------------------------------------------+ ### 26: `PoolColorArray( poolcolorarray )`
| Offset | Len | Type | Description | | Offset | Len | Type | Description |
+====================+=======+===========+==============================================================+ |--------------------|-------|-----------|--------------------------------------------------------------|
| 4 | 4 | Integer | Array length | | 4 | 4 | Integer | Array length |
+--------------------+-------+-----------+--------------------------------------------------------------+
| 8..8+length\*16 | 4 | Float | Red (typically 0..1, can be above 1 for overbright colors) | | 8..8+length\*16 | 4 | Float | Red (typically 0..1, can be above 1 for overbright colors) |
+--------------------+-------+-----------+--------------------------------------------------------------+
| 8..12+length\*16 | 4 | Float | Green (typically 0..1, can be above 1 for overbright colors) | | 8..12+length\*16 | 4 | Float | Green (typically 0..1, can be above 1 for overbright colors) |
+--------------------+-------+-----------+--------------------------------------------------------------+
| 8..16+length\*16 | 4 | Float | Blue (typically 0..1, can be above 1 for overbright colors) | | 8..16+length\*16 | 4 | Float | Blue (typically 0..1, can be above 1 for overbright colors) |
+--------------------+-------+-----------+--------------------------------------------------------------+
| 8..20+length\*16 | 4 | Float | Alpha (0..1) | | 8..20+length\*16 | 4 | Float | Alpha (0..1) |
+--------------------+-------+-----------+--------------------------------------------------------------+

View File

@ -1,10 +1,8 @@
High-level multiplayer # High-level multiplayer
======================
High-level vs low-level API ## High-level vs low-level API
---------------------------
The following explains the differences of high- and low-level networking in Pandemonium as well as some fundamentals. If you want to jump in head-first and add networking to your first nodes, skip to `Initializing the network` below. But make sure to read the rest later on! The following explains the differences of high- and low-level networking in Pandemonium as well as some fundamentals. If you want to jump in head-first and add networking to your first nodes, skip to `Initializing the network` below. But make sure to read the rest later on!
@ -54,8 +52,7 @@ Warning:
You can of course experiment, but when you release a networked application, You can of course experiment, but when you release a networked application,
always take care of any possible security concerns. always take care of any possible security concerns.
Mid level abstraction ## Mid level abstraction
---------------------
Before going into how we would like to synchronize a game across the network, it can be helpful to understand how the base network API for synchronization works. Before going into how we would like to synchronize a game across the network, it can be helpful to understand how the base network API for synchronization works.
@ -73,8 +70,7 @@ mobile APIs (for ad hoc WiFi, Bluetooth) or custom device/console-specific netwo
For most common cases, using this object directly is discouraged, as Pandemonium provides even higher level networking facilities. For most common cases, using this object directly is discouraged, as Pandemonium provides even higher level networking facilities.
Yet it is made available in case a game has specific needs for a lower level API. Yet it is made available in case a game has specific needs for a lower level API.
Initializing the network ## Initializing the network
------------------------
The object that controls networking in Pandemonium is the same one that controls everything tree-related: `SceneTree`. The object that controls networking in Pandemonium is the same one that controls everything tree-related: `SceneTree`.
@ -126,8 +122,7 @@ Warning:
using one-click deploy. Otherwise, network communication of any kind will be using one-click deploy. Otherwise, network communication of any kind will be
blocked by Android. blocked by Android.
Managing connections ## Managing connections
--------------------
Some games accept connections at any time, others during the lobby phase. Pandemonium can be requested to no longer accept Some games accept connections at any time, others during the lobby phase. Pandemonium can be requested to no longer accept
connections at any point (see `set_refuse_new_network_connections(bool)` and related methods on `SceneTree`). To manage who connects, Pandemonium provides the following signals in SceneTree: connections at any point (see `set_refuse_new_network_connections(bool)` and related methods on `SceneTree`). To manage who connects, Pandemonium provides the following signals in SceneTree:
@ -156,8 +151,7 @@ player information about other already connected players (e.g. their names, stat
Lobbies can be implemented any way you want, but the most common way is to use a node with the same name across scenes in all peers. Lobbies can be implemented any way you want, but the most common way is to use a node with the same name across scenes in all peers.
Generally, an autoloaded node/singleton is a great fit for this, to always have access to, e.g. "/root/lobby". Generally, an autoloaded node/singleton is a great fit for this, to always have access to, e.g. "/root/lobby".
RPC ## RPC
---
To communicate between peers, the easiest way is to use RPCs (remote procedure calls). This is implemented as a set of functions To communicate between peers, the easiest way is to use RPCs (remote procedure calls). This is implemented as a set of functions
in `Node`: in `Node`:
@ -184,8 +178,7 @@ and if a packet is lost, it's not that bad because a new one will eventually arr
There is also `SceneTree.get_rpc_sender_id()`, which can be used to check which peer (or peer ID) sent an RPC. There is also `SceneTree.get_rpc_sender_id()`, which can be used to check which peer (or peer ID) sent an RPC.
Back to lobby ## Back to lobby
-------------
Let's get back to the lobby. Imagine that each player that connects to the server will tell everyone about it. Let's get back to the lobby. Imagine that each player that connects to the server will tell everyone about it.
@ -274,14 +267,12 @@ With this, lobby management should be more or less explained. Once you have your
extra security to make sure clients don't do anything funny (just validate the info they send from time to time, or before extra security to make sure clients don't do anything funny (just validate the info they send from time to time, or before
game start). For the sake of simplicity and because each game will share different information, this is not shown here. game start). For the sake of simplicity and because each game will share different information, this is not shown here.
Starting the game ## Starting the game
-----------------
Once enough players have gathered in the lobby, the server should probably start the game. This is nothing Once enough players have gathered in the lobby, the server should probably start the game. This is nothing
special in itself, but we'll explain a few nice tricks that can be done at this point to make your life much easier. special in itself, but we'll explain a few nice tricks that can be done at this point to make your life much easier.
Player scenes #### Player scenes
^^^^^^^^^^^^^
In most games, each player will likely have its own scene. Remember that this is a multiplayer game, so in every peer In most games, each player will likely have its own scene. Remember that this is a multiplayer game, so in every peer
you need to instance **one scene for each player connected to it**. For a 4 player game, each peer needs to instance 4 player nodes. you need to instance **one scene for each player connected to it**. For a 4 player game, each peer needs to instance 4 player nodes.
@ -322,8 +313,7 @@ Note:
Depending on when you execute pre_configure_game(), you may need to change any calls to `add_child()` Depending on when you execute pre_configure_game(), you may need to change any calls to `add_child()`
to be deferred via `call_deferred()`, as the SceneTree is locked while the scene is being created (e.g. when `ready()` is being called). to be deferred via `call_deferred()`, as the SceneTree is locked while the scene is being created (e.g. when `ready()` is being called).
Synchronizing game start #### Synchronizing game start
^^^^^^^^^^^^^^^^^^^^^^^^
Setting up players might take different amounts of time for every peer due to lag, different hardware, or other reasons. Setting up players might take different amounts of time for every peer due to lag, different hardware, or other reasons.
To make sure the game will actually start when everyone is ready, pausing the game until all players are ready can be useful: To make sure the game will actually start when everyone is ready, pausing the game until all players are ready can be useful:
@ -358,14 +348,12 @@ When the server gets the OK from all the peers, it can tell them to start, as fo
``` ```
Synchronizing the game ## Synchronizing the game
----------------------
In most games, the goal of multiplayer networking is that the game runs synchronized on all the peers playing it. In most games, the goal of multiplayer networking is that the game runs synchronized on all the peers playing it.
Besides supplying an RPC and remote member variable set implementation, Pandemonium adds the concept of network masters. Besides supplying an RPC and remote member variable set implementation, Pandemonium adds the concept of network masters.
Network master #### Network master
^^^^^^^^^^^^^^
The network master of a node is the peer that has the ultimate authority over it. The network master of a node is the peer that has the ultimate authority over it.
@ -403,8 +391,7 @@ To clarify, here is an example of how this looks in the
![](img/nmms.png) ![](img/nmms.png)
Master and puppet keywords #### Master and puppet keywords
^^^^^^^^^^^^^^^^^^^^^^^^^^
.. FIXME: Clarify the equivalents to the GDScript keywords in C# and Visual Script. .. FIXME: Clarify the equivalents to the GDScript keywords in C# and Visual Script.
@ -473,8 +460,7 @@ This may not make much sense for an area-of-effect case like the bomb, but might
rpc_id(TARGET_PEER_ID, "stun") # Only stun the target peer rpc_id(TARGET_PEER_ID, "stun") # Only stun the target peer
``` ```
Exporting for dedicated servers ## Exporting for dedicated servers
-------------------------------
Once you've made a multiplayer game, you may want to export it to run it on Once you've made a multiplayer game, you may want to export it to run it on
a dedicated server with no GPU available. See a dedicated server with no GPU available. See

View File

@ -1,7 +1,6 @@
Making HTTP requests # Making HTTP requests
====================
The `HTTPRequest` node is the easiest way to make HTTP requests in Pandemonium. The `HTTPRequest` node is the easiest way to make HTTP requests in Pandemonium.
It is backed by the more low-level `HTTPClient`. It is backed by the more low-level `HTTPClient`.
@ -16,8 +15,7 @@ Warning:
using one-click deploy. Otherwise, network communication of any kind will be using one-click deploy. Otherwise, network communication of any kind will be
blocked by Android. blocked by Android.
Preparing scene ## Preparing scene
---------------
Create a new empty scene, add a CanvasLayer as the root node and add a script to it. Then add two child nodes to it: a Button and an HTTPRequest node. You will need to connect the following signals to the CanvasLayer script: Create a new empty scene, add a CanvasLayer as the root node and add a script to it. Then add two child nodes to it: a Button and an HTTPRequest node. You will need to connect the following signals to the CanvasLayer script:
@ -26,8 +24,7 @@ Create a new empty scene, add a CanvasLayer as the root node and add a script to
![](img/rest_api_scene.png) ![](img/rest_api_scene.png)
Scripting ## Scripting
---------
Below is all the code we need to make it work. The URL points to an online API mocker; it returns a pre-defined JSON string, which we will then parse to get access to the data. Below is all the code we need to make it work. The URL points to an online API mocker; it returns a pre-defined JSON string, which we will then parse to get access to the data.
@ -67,8 +64,7 @@ Please note that, for SSL/TLS encryption and thus HTTPS URLs to work, you may ne
Also, when calling APIs using authorization, be aware that someone might analyse and decompile your released application and thus may gain access to any embedded authorization information like tokens, usernames or passwords. Also, when calling APIs using authorization, be aware that someone might analyse and decompile your released application and thus may gain access to any embedded authorization information like tokens, usernames or passwords.
That means it is usually not a good idea to embed things such as database access credentials inside your game. Avoid providing information useful to an attacker whenever possible. That means it is usually not a good idea to embed things such as database access credentials inside your game. Avoid providing information useful to an attacker whenever possible.
Sending data to server ## Sending data to server
----------------------
Until now, we have limited ourselves to requesting data from a server. But what if you need to send data to the server? Here is a common way of doing it: Until now, we have limited ourselves to requesting data from a server. But what if you need to send data to the server? Here is a common way of doing it:

View File

@ -1,7 +1,6 @@
HTTP client class # HTTP client class
=================
`HTTPClient` provides low-level access to HTTP communication. `HTTPClient` provides low-level access to HTTP communication.
For a higher-level interface, you may want to take a look at `HTTPRequest` first, For a higher-level interface, you may want to take a look at `HTTPRequest` first,

View File

@ -1,10 +1,8 @@
SSL certificates # SSL certificates
================
Introduction ## Introduction
------------
It is often desired to use SSL connections for communications to avoid It is often desired to use SSL connections for communications to avoid
"man in the middle" attacks. Pandemonium has a connection wrapper, "man in the middle" attacks. Pandemonium has a connection wrapper,
@ -28,8 +26,7 @@ this when exporting your project.
There are two ways to obtain certificates: There are two ways to obtain certificates:
Approach 1: self signed cert ## Approach 1: self signed cert
----------------------------
The first approach is the simplest: generate a private and public The first approach is the simplest: generate a private and public
key pair and add the public key (in PEM format) to the .crt file. key pair and add the public key (in PEM format) to the .crt file.
@ -41,8 +38,7 @@ this. This approach also **does not require domain validation** nor
requires you to spend a considerable amount of money in purchasing requires you to spend a considerable amount of money in purchasing
certificates from a CA. certificates from a CA.
Approach 2: CA cert ## Approach 2: CA cert
-------------------
The second approach consists of using a certificate authority (CA) The second approach consists of using a certificate authority (CA)
such as Verisign, Geotrust, etc. This is a more cumbersome process, such as Verisign, Geotrust, etc. This is a more cumbersome process,

View File

@ -1,10 +1,8 @@
WebSocket # WebSocket
=========
HTML5 and WebSocket ## HTML5 and WebSocket
-------------------
The WebSocket protocol was standardized in 2011 with the original goal of allowing browsers to create stable and bidirectional connections with a server. The WebSocket protocol was standardized in 2011 with the original goal of allowing browsers to create stable and bidirectional connections with a server.
Before that, browsers used to only support HTTPRequests, which is not well-suited for bidirectional communication. Before that, browsers used to only support HTTPRequests, which is not well-suited for bidirectional communication.
@ -15,8 +13,7 @@ Due to its simplicity, its wide compatibility, and being easier to use than a ra
Pandemonium supports WebSocket in both native and HTML5 exports. Pandemonium supports WebSocket in both native and HTML5 exports.
Using WebSocket in Pandemonium ## Using WebSocket in Pandemonium
------------------------
WebSocket is implemented in Pandemonium via three main classes `WebSocketClient` for more details. WebSocket is implemented in Pandemonium via three main classes `WebSocketClient` for more details.
@ -28,8 +25,7 @@ Warning:
using one-click deploy. Otherwise, network communication of any kind will be using one-click deploy. Otherwise, network communication of any kind will be
blocked by Android. blocked by Android.
Minimal client example #### Minimal client example
^^^^^^^^^^^^^^^^^^^^^^
This example will show you how to create a WebSocket connection to a remote server, and how to send and receive data. This example will show you how to create a WebSocket connection to a remote server, and how to send and receive data.
@ -93,8 +89,7 @@ This will print:
Got data from server: Test packet Got data from server: Test packet
``` ```
Minimal server example #### Minimal server example
^^^^^^^^^^^^^^^^^^^^^^
This example will show you how to create a WebSocket server that listens for remote connections, and how to send and receive data. This example will show you how to create a WebSocket server that listens for remote connections, and how to send and receive data.
@ -161,7 +156,6 @@ This will print (when a client connects) something similar to this:
Got data from client 1348090059: Test packet ... echoing Got data from client 1348090059: Test packet ... echoing
``` ```
Advanced chat demo #### Advanced chat demo
^^^^^^^^^^^^^^^^^^
A more advanced chat demo which optionally uses the multiplayer mid-level abstraction and a high level multiplayer demo are available in the `pandemonium demo projects ( https://github.com/Relintai/pandemonium_engine-demo-projects )` under `networking/websocket_chat` and `networking/websocket_multiplayer`. A more advanced chat demo which optionally uses the multiplayer mid-level abstraction and a high level multiplayer demo are available in the `pandemonium demo projects ( https://github.com/Relintai/pandemonium_engine-demo-projects )` under `networking/websocket_chat` and `networking/websocket_multiplayer`.

View File

@ -1,24 +1,20 @@
WebRTC # WebRTC
======
HTML5, WebSocket, WebRTC ## HTML5, WebSocket, WebRTC
------------------------
One of Pandemonium's great features is its ability to export to the HTML5/WebAssembly platform, allowing your game to run directly in the browser when a user visit your webpage. One of Pandemonium's great features is its ability to export to the HTML5/WebAssembly platform, allowing your game to run directly in the browser when a user visit your webpage.
This is a great opportunity for both demos and full games, but used to come with some limitations. In the area of networking, browsers used to support only HTTPRequests until recently, when first WebSocket and then WebRTC were proposed as standards. This is a great opportunity for both demos and full games, but used to come with some limitations. In the area of networking, browsers used to support only HTTPRequests until recently, when first WebSocket and then WebRTC were proposed as standards.
WebSocket #### WebSocket
^^^^^^^^^
When the WebSocket protocol was standardized in December 2011, it allowed browsers to create stable and bidirectional connections to a WebSocket server. The protocol is quite simple, but a very powerful tool to send push notifications to browsers, and has been used to implement chats, turn-based games, etc. When the WebSocket protocol was standardized in December 2011, it allowed browsers to create stable and bidirectional connections to a WebSocket server. The protocol is quite simple, but a very powerful tool to send push notifications to browsers, and has been used to implement chats, turn-based games, etc.
WebSockets, though, still use a TCP connection, which is good for reliability but not for latency, so not good for real-time applications like VoIP and fast-paced games. WebSockets, though, still use a TCP connection, which is good for reliability but not for latency, so not good for real-time applications like VoIP and fast-paced games.
WebRTC #### WebRTC
^^^^^^
For this reason, since 2010, Google started working on a new technology called WebRTC, which later on, in 2017, became a W3C candidate recommendation. WebRTC is a much more complex set of specifications, and relies on many other technologies behind the scenes (ICE, DTLS, SDP) to provide fast, real-time, and secure communication between two peers. For this reason, since 2010, Google started working on a new technology called WebRTC, which later on, in 2017, became a W3C candidate recommendation. WebRTC is a much more complex set of specifications, and relies on many other technologies behind the scenes (ICE, DTLS, SDP) to provide fast, real-time, and secure communication between two peers.
@ -30,8 +26,7 @@ However, this comes at a price, which is that some media information must be exc
Peers connect to a signaling server (for example a WebSocket server) and send their media information. The server then relays this information to other peers, allowing them to establish the desired direct communication. Once this step is done, peers can disconnect from the signaling server and keep the direct Peer-to-Peer (P2P) connection open. Peers connect to a signaling server (for example a WebSocket server) and send their media information. The server then relays this information to other peers, allowing them to establish the desired direct communication. Once this step is done, peers can disconnect from the signaling server and keep the direct Peer-to-Peer (P2P) connection open.
Using WebRTC in Pandemonium ## Using WebRTC in Pandemonium
---------------------
WebRTC is implemented in Pandemonium via two main classes `WebRTCPeerConnection` for more details. WebRTC is implemented in Pandemonium via two main classes `WebRTCPeerConnection` for more details.
@ -46,8 +41,7 @@ Warning:
using one-click deploy. Otherwise, network communication of any kind will be using one-click deploy. Otherwise, network communication of any kind will be
blocked by Android. blocked by Android.
Minimal connection example #### Minimal connection example
^^^^^^^^^^^^^^^^^^^^^^^^^^
This example will show you how to create a WebRTC connection between two peers in the same application. This example will show you how to create a WebRTC connection between two peers in the same application.
This is not very useful in real life, but will give you a good overview of how a WebRTC connection is set up. This is not very useful in real life, but will give you a good overview of how a WebRTC connection is set up.
@ -104,8 +98,7 @@ This will print:
P2 received: Hi from P2 P2 received: Hi from P2
``` ```
Local signaling example #### Local signaling example
^^^^^^^^^^^^^^^^^^^^^^^
This example expands on the previous one, separating the peers in two different scenes, and using a `singleton ( doc_singletons_autoload )` as a signaling server. This example expands on the previous one, separating the peers in two different scenes, and using a `singleton ( doc_singletons_autoload )` as a signaling server.
@ -212,7 +205,6 @@ This will print something similar to this:
/root/main/@@2 received: Hi from /root/main/@@3 /root/main/@@2 received: Hi from /root/main/@@3
``` ```
Remote signaling with WebSocket #### Remote signaling with WebSocket
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A more advanced demo using WebSocket for signaling peers and `WebRTCMultiplayer` under `networking/webrtc_signaling`. A more advanced demo using WebSocket for signaling peers and `WebRTCMultiplayer` under `networking/webrtc_signaling`.

View File

@ -1,10 +1,8 @@
Audio buses # Audio buses
===========
Introduction ## Introduction
------------
Pandemonium's audio processing code has been written with games in mind, with the aim Pandemonium's audio processing code has been written with games in mind, with the aim
of achieving an optimal balance between performance and sound quality. of achieving an optimal balance between performance and sound quality.
@ -14,8 +12,7 @@ number of effect processors can be added to each bus. Only the hardware of the
device running your game will limit the number of buses and effects that can be device running your game will limit the number of buses and effects that can be
used before performance starts to suffer. used before performance starts to suffer.
Decibel scale ## Decibel scale
-------------
Pandemonium's sound interface is designed to meet the expectations of sound design Pandemonium's sound interface is designed to meet the expectations of sound design
professionals. To this end, it primarily uses the decibel scale. professionals. To this end, it primarily uses the decibel scale.
@ -44,8 +41,7 @@ For those unfamiliar with it, it can be explained with a few facts:
This can take a bit getting used to, but it's friendlier in the end This can take a bit getting used to, but it's friendlier in the end
and will allow you to communicate better with audio professionals. and will allow you to communicate better with audio professionals.
Audio buses ## Audio buses
-----------
Audio buses can be found in the bottom panel of the Pandemonium editor: Audio buses can be found in the bottom panel of the Pandemonium editor:
@ -69,8 +65,7 @@ to the left. This avoids infinite routing loops.
In the above image, the output of *Bus 2* has been routed to the *Master* bus. In the above image, the output of *Bus 2* has been routed to the *Master* bus.
Playback of audio through a bus ## Playback of audio through a bus
-------------------------------
To test passing audio to a bus, create an AudioStreamPlayer node, load an To test passing audio to a bus, create an AudioStreamPlayer node, load an
AudioStream and select a target bus for playback: AudioStream and select a target bus for playback:
@ -84,8 +79,7 @@ See also:
You may also be interested in reading about `doc_audio_streams` now. You may also be interested in reading about `doc_audio_streams` now.
Adding effects ## Adding effects
--------------
Audio buses can contain all sorts of effects. These effects modify the sound in Audio buses can contain all sorts of effects. These effects modify the sound in
one way or another and are applied in order. one way or another and are applied in order.
@ -95,15 +89,13 @@ one way or another and are applied in order.
Try them all out to get a sense of how they alter sound. Here follows a short Try them all out to get a sense of how they alter sound. Here follows a short
description of the available effects: description of the available effects:
Amplify ### Amplify
~~~~~~~
Amplify changes the amplitude of the signal. Some care needs to be taken. Amplify changes the amplitude of the signal. Some care needs to be taken.
Setting the level too high can make the sound clip, which is usually Setting the level too high can make the sound clip, which is usually
undesirable. undesirable.
BandLimit and BandPass ### BandLimit and BandPass
~~~~~~~~~~~~~~~~~~~~~~
These are resonant filters which block frequencies around the *Cutoff* point. These are resonant filters which block frequencies around the *Cutoff* point.
BandPass can be used to simulate sound passing through an old telephone line or BandPass can be used to simulate sound passing through an old telephone line or
@ -111,23 +103,20 @@ megaphone. Modulating the BandPass frequency can simulate the sound of a wah-wah
guitar pedal, think of the guitar in Jimi Hendrix's *Voodoo Child (Slight guitar pedal, think of the guitar in Jimi Hendrix's *Voodoo Child (Slight
Return)*. Return)*.
Capture ### Capture
~~~~~~~
The Capture effect copies the audio frames of the audio bus that it is on into The Capture effect copies the audio frames of the audio bus that it is on into
an internal buffer. This can be used to capture data from the microphone an internal buffer. This can be used to capture data from the microphone
or to transmit audio over the network in real-time. or to transmit audio over the network in real-time.
Chorus ### Chorus
~~~~~~
The Chorus effect duplicates the incoming audio, delays the duplicate slightly The Chorus effect duplicates the incoming audio, delays the duplicate slightly
and uses an LFO to continuously modulate the pitch of the duplicated signal and uses an LFO to continuously modulate the pitch of the duplicated signal
before mixing the duplicated signal(s) and the original together again. This before mixing the duplicated signal(s) and the original together again. This
creates a shimmering effect and adds stereo width to the sound. creates a shimmering effect and adds stereo width to the sound.
Compressor ### Compressor
~~~~~~~~~~
A dynamic range compressor automatically attenuates the level of the incoming A dynamic range compressor automatically attenuates the level of the incoming
signal when its amplitude exceeds a certain threshold. The level of attenuation signal when its amplitude exceeds a certain threshold. The level of attenuation
@ -157,106 +146,88 @@ Note:
than a compressor. than a compressor.
Delay ### Delay
~~~~~
Adds an "echo" effect with a feedback loop. It can be used together Adds an "echo" effect with a feedback loop. It can be used together
with *Reverb* to simulate wide rooms, canyons, etc. where sound bounces with *Reverb* to simulate wide rooms, canyons, etc. where sound bounces
are far apart. are far apart.
Distortion ### Distortion
~~~~~~~~~~
Makes the sound distorted. Pandemonium offers several types of distortion: *overdrive*, Makes the sound distorted. Pandemonium offers several types of distortion: *overdrive*,
*tan* and *bit crushing*. Distortion can be used to simulate sound coming through *tan* and *bit crushing*. Distortion can be used to simulate sound coming through
a low-quality speaker or device. a low-quality speaker or device.
EQ ### EQ
~~
EQ is what all other equalizers inherit from. It can be extended with with Custom EQ is what all other equalizers inherit from. It can be extended with with Custom
scripts to create an equalizer with a custom number of bands. scripts to create an equalizer with a custom number of bands.
EQ6, EQ10, EQ21 ### EQ6, EQ10, EQ21
~~~~~~~~~~~~~~~
Pandemonium provides three equalizers with different numbers of bands. An equalizer on Pandemonium provides three equalizers with different numbers of bands. An equalizer on
the Master bus can be useful to cut frequencies that the device's speakers can't the Master bus can be useful to cut frequencies that the device's speakers can't
reproduce well (e.g. a mobile phone's speakers won't reproduce bass content reproduce well (e.g. a mobile phone's speakers won't reproduce bass content
well). The equalizer effect can be disabled when headphones are plugged in. well). The equalizer effect can be disabled when headphones are plugged in.
Filter ### Filter
~~~~~~
Filter is what all other filters inherit from and should not be used directly. Filter is what all other filters inherit from and should not be used directly.
HighPassFilter ### HighPassFilter
~~~~~~~~~~~~~~
Cuts frequencies below a specific *Cutoff* frequency. Cuts frequencies below a specific *Cutoff* frequency.
HighPassFilter is used to reduce the bass content of a HighPassFilter is used to reduce the bass content of a
signal. signal.
HighShelfFilter ### HighShelfFilter
~~~~~~~~~~~~~~~
Reduces all frequencies above a specific *Cutoff* frequency. Reduces all frequencies above a specific *Cutoff* frequency.
### Limiter
Limiter
~~~~~~~
A limiter is similar to a compressor, but it's less flexible and designed to A limiter is similar to a compressor, but it's less flexible and designed to
prevent a signal's amplitude exceeding a given dB threshold. Adding a limiter to prevent a signal's amplitude exceeding a given dB threshold. Adding a limiter to
the Master bus is a safeguard against clipping. the Master bus is a safeguard against clipping.
LowPassFilter ### LowPassFilter
~~~~~~~~~~~~~
Cuts frequencies above a specific *Cutoff* frequency and can also resonate Cuts frequencies above a specific *Cutoff* frequency and can also resonate
(boost frequencies close to the *Cutoff* frequency). Low pass filters can be (boost frequencies close to the *Cutoff* frequency). Low pass filters can be
used to simulate "muffled" sound. For instance, underwater sounds, sounds used to simulate "muffled" sound. For instance, underwater sounds, sounds
blocked by walls, or distant sounds. blocked by walls, or distant sounds.
LowShelfFilter ### LowShelfFilter
~~~~~~~~~~~~~~
Reduces all frequencies below a specific *Cutoff* frequency. Reduces all frequencies below a specific *Cutoff* frequency.
NotchFilter ### NotchFilter
~~~~~~~~~~~
The opposite of the BandPassFilter, it removes a band of sound from the The opposite of the BandPassFilter, it removes a band of sound from the
frequency spectrum at a given *Cutoff* frequency. frequency spectrum at a given *Cutoff* frequency.
Panner ### Panner
~~~~~~
The Panner allows the stereo balance of a signal to be adjusted between The Panner allows the stereo balance of a signal to be adjusted between
the left and right channels (wear headphones to audition this effect). the left and right channels (wear headphones to audition this effect).
Phaser ### Phaser
~~~~~~
It probably does not make much sense to explain that this effect is formed by It probably does not make much sense to explain that this effect is formed by
two signals being dephased and cancelling each other out. You can make a Darth two signals being dephased and cancelling each other out. You can make a Darth
Vader voice with it, or jet-like sounds. Vader voice with it, or jet-like sounds.
PitchShift ### PitchShift
~~~~~~~~~~
This effect allows the adjustment of the signal's pitch independently of its This effect allows the adjustment of the signal's pitch independently of its
speed. All frequencies can be increased/decreased with minimal effect on speed. All frequencies can be increased/decreased with minimal effect on
transients. PitchShift can be useful to create unusually high or deep voices. transients. PitchShift can be useful to create unusually high or deep voices.
Record ### Record
~~~~~~
The Record effect allows the user to record sound from a microphone. The Record effect allows the user to record sound from a microphone.
Reverb ### Reverb
~~~~~~
Reverb simulates rooms of different sizes. It has adjustable parameters that can Reverb simulates rooms of different sizes. It has adjustable parameters that can
be tweaked to obtain the sound of a specific room. Reverb is commonly outputted be tweaked to obtain the sound of a specific room. Reverb is commonly outputted
@ -264,31 +235,27 @@ from `Areas`
(see `Reverb buses ( doc_audio_streams_reverb_buses )`), or to apply (see `Reverb buses ( doc_audio_streams_reverb_buses )`), or to apply
a "chamber" feel to all sounds. a "chamber" feel to all sounds.
SpectrumAnalyzer ### SpectrumAnalyzer
~~~~~~~~~~~~~~~~
This effect doesn't alter audio, instead, you add this effect to buses you want This effect doesn't alter audio, instead, you add this effect to buses you want
a spectrum analysis of. This would typically be used for audio visualization. A a spectrum analysis of. This would typically be used for audio visualization. A
demo project using this can be found `here ( https://github.com/Relintai/pandemonium_engine-demo-projects/tree/master/audio/spectrum )`. demo project using this can be found `here ( https://github.com/Relintai/pandemonium_engine-demo-projects/tree/master/audio/spectrum )`.
StereoEnhance ### StereoEnhance
~~~~~~~~~~~~~
This effect uses a few algorithms to enhance a signal's stereo spectrum. This effect uses a few algorithms to enhance a signal's stereo spectrum.
Automatic bus disabling ## Automatic bus disabling
-----------------------
There is no need to disable buses manually when not in use. Pandemonium detects There is no need to disable buses manually when not in use. Pandemonium detects
that the bus has been silent for a few seconds and disables it (including that the bus has been silent for a few seconds and disables it (including
all effects). all effects).
.. figure:: img/audio_buses5.png) ![](img/audio_buses5.png)
Disabled buses have a blue VU meter instead of a red-green one. Disabled buses have a blue VU meter instead of a red-green one.
Bus rearrangement ## Bus rearrangement
-----------------
Stream Players use bus names to identify a bus, which allows adding, removing Stream Players use bus names to identify a bus, which allows adding, removing
and moving buses around while the reference to them is kept. However, if a bus and moving buses around while the reference to them is kept. However, if a bus
@ -296,8 +263,7 @@ is renamed, the reference will be lost and the Stream Player will output
to Master. This system was chosen because rearranging buses is a more common to Master. This system was chosen because rearranging buses is a more common
process than renaming them. process than renaming them.
Default bus layout ## Default bus layout
------------------
The default bus layout is automatically saved to the The default bus layout is automatically saved to the
`res://default_bus_layout.tres` file. Custom bus arrangements can be saved `res://default_bus_layout.tres` file. Custom bus arrangements can be saved

View File

@ -1,17 +1,14 @@
Audio streams # Audio streams
=============
Introduction ## Introduction
------------
As you might have already read in `doc_audio_buses`, sound is sent to As you might have already read in `doc_audio_buses`, sound is sent to
each bus via an AudioStreamPlayer node. There are different kinds each bus via an AudioStreamPlayer node. There are different kinds
of AudioStreamPlayers. Each one loads an AudioStream and plays it back. of AudioStreamPlayers. Each one loads an AudioStream and plays it back.
AudioStream ## AudioStream
-----------
An audio stream is an abstract object that emits sound. The sound can come from An audio stream is an abstract object that emits sound. The sound can come from
many places, but is most commonly loaded from the filesystem. Audio files can be many places, but is most commonly loaded from the filesystem. Audio files can be
@ -23,16 +20,14 @@ This one makes a random adjustment to the sound's pitch every time it's
played back. This can be helpful for adding variation to sounds that are played back. This can be helpful for adding variation to sounds that are
played back often. played back often.
AudioStreamPlayer ## AudioStreamPlayer
-----------------
![](img/audio_stream_player.png) ![](img/audio_stream_player.png)
This is the standard, non-positional stream player. It can play to any bus. This is the standard, non-positional stream player. It can play to any bus.
In 5.1 sound setups, it can send audio to stereo mix or front speakers. In 5.1 sound setups, it can send audio to stereo mix or front speakers.
AudioStreamPlayer2D ## AudioStreamPlayer2D
-------------------
![](img/audio_stream_2d.png) ![](img/audio_stream_2d.png)
@ -50,8 +45,7 @@ Note:
![](img/audio_stream_2d_area.png) ![](img/audio_stream_2d_area.png)
AudioStreamPlayer3D ## AudioStreamPlayer3D
-------------------
![](img/audio_stream_3d.png) ![](img/audio_stream_3d.png)
@ -67,8 +61,7 @@ Unlike for 2D, the 3D version of AudioStreamPlayer has a few more advanced optio
Reverb buses ### Reverb buses
~~~~~~~~~~~~
Pandemonium allows for 3D audio streams that enter a specific Area node to send dry Pandemonium allows for 3D audio streams that enter a specific Area node to send dry
and wet audio to separate buses. This is useful when you have several reverb and wet audio to separate buses. This is useful when you have several reverb
@ -89,8 +82,7 @@ reverberation can be heard almost uniformly across the room even though the
source may be far away. Playing around with this parameter can simulate source may be far away. Playing around with this parameter can simulate
that effect. that effect.
Doppler ### Doppler
~~~~~~~
When the relative velocity between an emitter and listener changes, this is When the relative velocity between an emitter and listener changes, this is
perceived as an increase or decrease in the pitch of the emitted sound. perceived as an increase or decrease in the pitch of the emitted sound.

View File

@ -1,10 +1,8 @@
Sync the gameplay with audio and music # Sync the gameplay with audio and music
=======================================
Introduction ## Introduction
------------
In any application or game, sound and music playback will have a slight delay. For games, this delay is often so small that it is negligible. Sound effects will come out a few milliseconds after any play() function is called. For music this does not matter as in most games it does not interact with the gameplay. In any application or game, sound and music playback will have a slight delay. For games, this delay is often so small that it is negligible. Sound effects will come out a few milliseconds after any play() function is called. For music this does not matter as in most games it does not interact with the gameplay.
@ -23,8 +21,7 @@ This is a common tradeoff, so Pandemonium ships with sensible defaults that shou
The problem, in the end, is not this slight delay but synchronizing graphics and audio for games that require it. Beginning with Pandemonium 3.2, some helpers were added to obtain more precise playback timing. The problem, in the end, is not this slight delay but synchronizing graphics and audio for games that require it. Beginning with Pandemonium 3.2, some helpers were added to obtain more precise playback timing.
Using the system clock to sync ## Using the system clock to sync
------------------------------
As mentioned before, If you call `AudioStreamPlayer.play()( AudioStreamPlayer_method_play )`, sound will not begin immediately, but when the audio thread processes the next chunk. As mentioned before, If you call `AudioStreamPlayer.play()( AudioStreamPlayer_method_play )`, sound will not begin immediately, but when the audio thread processes the next chunk.
@ -62,8 +59,7 @@ In the long run, though, as the sound hardware clock is never exactly in sync wi
For a rhythm game where a song begins and ends after a few minutes, this approach is fine (and it's the recommended approach). For a game where playback can last a much longer time, the game will eventually go out of sync and a different approach is needed. For a rhythm game where a song begins and ends after a few minutes, this approach is fine (and it's the recommended approach). For a game where playback can last a much longer time, the game will eventually go out of sync and a different approach is needed.
Using the sound hardware clock to sync ## Using the sound hardware clock to sync
--------------------------------------
Using `AudioStreamPlayer.get_playback_position()( AudioStreamPlayer_method_get_playback_position )` to obtain the current position for the song sounds ideal, but it's not that useful as-is. This value will increment in chunks (every time the audio callback mixed a block of sound), so many calls can return the same value. Added to this, the value will be out of sync with the speakers too because of the previously mentioned reasons. Using `AudioStreamPlayer.get_playback_position()( AudioStreamPlayer_method_get_playback_position )` to obtain the current position for the song sounds ideal, but it's not that useful as-is. This value will increment in chunks (every time the audio callback mixed a block of sound), so many calls can return the same value. Added to this, the value will be out of sync with the speakers too because of the previously mentioned reasons.

View File

@ -1,7 +1,6 @@
Recording with microphone # Recording with microphone
=========================
Pandemonium supports in-game audio recording for Windows, macOS, Linux, Android and Pandemonium supports in-game audio recording for Windows, macOS, Linux, Android and
iOS. iOS.
@ -12,8 +11,7 @@ support for this tutorial:
You will need to enable audio input in the project settings, or you'll just get empty audio files. You will need to enable audio input in the project settings, or you'll just get empty audio files.
The structure of the demo ## The structure of the demo
-------------------------
The demo consists of a single scene. This scene includes two major parts: the The demo consists of a single scene. This scene includes two major parts: the
GUI and the audio. GUI and the audio.