The Machinery Team: 1 Getting Started

Download as pdf or txt
Download as pdf or txt
You are on page 1of 47

Hi,

Thanks for being a part of this release of The Machinery. We’re excited to share with the
world
what we have cooked up and happy to have you among the people that are trying out the engine.
This document is here to give you a little bit of background and information about what you’re
looking at.

Enjoy!

The Machinery Team

Contents

Getting started
  1.1  License
  1.2  Getting up and running

What is The Machinery?

3  What is in this package?

What we want from you

5  Editor details
  5.1  Logging in
  5.2  The editor
  5.3  Entities
  5.4  Basic editing workflow
  5.5  Creation graphs and asset pipeline
    5.5.1  Importing a DCC asset
    5.5.2  Basic entity rigging, with image and material extraction
    5.5.3  Creation Graphs for dcc_asset import
  5.6  Prototypes
  5.7  Simulation
  5.8  Entity Graphs
  5.9  Physics
    5.9.1  Physics scripting
  5.10  Animation
    5.10.1  Animation state machines
    5.10.2  Missing features
  5.11  Sound
    5.11.1  Missing features
  5.12  Simulate Entry (writing gameplay code in C)
  5.13  Collaboration

6  Extending The Machinery


  6.1  Writing a plugin
    6.1.1  Hot-reloading
    6.1.2  Plugin assets
    6.1.3  Extending the visual scripting language
  6.2  Writing an executable

1 Getting started

To run The Machinery you need:

A 64-bit Windows 10 machine with the latest Vulkan drivers


Or a 64-bit Ubuntu 20.04 Linux machine with the latest Vulkan drivers (ArchLinux
should also work, no guarantees are made for other distros)
And an ourmachinery.com account. Sign up here!

On Linux, you also need to install the following packages for the runtime:

sudo apt-get install libxcb-ewmh2 libxcb-cursor0 libxcb-xrm0 unzip

1.1 License

There are three different licenses that you can use for The Machinery:

The Indie Free license is completely free for indie developers and includes all of The
Machinery, except for the source code.

The Indie Pro license is exactly the same, but also includes the full source code of the
engine and all associated tools. For this version we charge $100 $50 / user / year.

The Business version is aimed towards professional users. It includes the same stuff as
the
Indie Pro version except your support tickets will be prioritized. It sells at $900 $450
/
user / year.

We define as an “indie”, any company who’s yearly revenue or funding is less than $100K/year.
Until
the end of the year 2021, we're offering all the paid licenses at 50 % off. If you buy a paid
license now, you will keep this low price for the next five years.
All of the licenses allow for full royalty-free use of The Machinery. You can build and sell
commercial games, tools, applications, and plugins. For more details, see our pricing
page.

When you download The Machinery, you will be on the Indie Free license. If you do not fall in
the
“indie” category, you can still use this license to evaluate The Machinery, but you need to
buy a
business license to put it into production.

1.2 Getting up and running

Quick steps to get up and running:

1. Download The Machinery at https://ourmachinery.com/download.html.

2. Sign up for an ourmachinery.com account here. (It's free!)

3. Unzip the downloaded zip file to a location of your choosing.

4. Run bin/the-machinery.exe in the downloaded folder to start The Machinery.

5. Login with your ourmachinery.com account at the login screen and approve the EULA.

6. To find some samples to play with go to Help > Download Sample Projects in the
main menu.

7. Pick one of the sample projects (for example Physics), click Get and then Open.

8. Play around with it, try some other samples and read the rest of this document to find out
what
else you can do with The Machinery.

If you get errors that mention Vulkan or if you see weird rendering glitches, make sure to update
your GPU drivers to the latest version. If that doesn't work, post an issue with our issue
tracker
or ping us on
Discord and we will help you.

Here is an introduction video showing these steps:


Introduction to The Machinery

Introduction to The Machinery.

2 What is The Machinery?

The Machinery is a framework for building different kinds of 3D software:


editors, tools,
pipeline components, games, visualizations, simulations, toys,
experiments, etc. You can think
of it as a game engine, but it’s intended use
stretches beyond games, covering a wide range of
applications.

What makes The Machinery special is that it is lightweight and completely


plugin-based. That
means that you are not limited to a single editor and
runtime. Rather, you can mix and match
components as you need (or write your
own) to create your own unique experience. The
Machinery can also be stripped
down and run embedded, as part of a larger application.

3 What is in this package?

In the distribution package you will find this:


Folder Content

headers/
The headers, libraries, and DLLs that make up The
lib/
Machinery SDK.
bin/

bin/the‑machinery.exe The Machinery's main editor.

doc/ SDK documentation.

Sample code that shows how to extend the editor and SDK
samples/ with plugins, as well as how to build new executables on top
of The Machinery.

code/ For reference: code for our utility programs.

bin/simple‑draw.exe A simple drawing program built on top of the SDK.

bin/simple-3d.exe A simple 3D viewport built on top of the SDK.

Our build tool, that can be used to build samples and


bin/tmbuild.exe
plugins.

bin/docgen.exe Our tool for generating documentation.

bin/hash.exe Our tool for generating static hash strings.

bin/localize.exe Our tool for generating localization data.

An executable than can load a The Machinery project and do


bin/runner.exe what Simulate Tab does, but stand-alone. It is copied
whenever you Publish a project from within The Machinery.

utils/.clang-format The clang-format settings we use to format our code.

The pre-commit hook we use in our git repository to auto-


utils/pre-commit
format the code.

utils/enable-full-
A registry file that enables full crash dumps (see below).
dumps.reg

You can use the Download tab inside The Machinery to download sample projects for the
engine.

Here's a list of the sample projects that are available:


Project Description

Animation A sample project that features an animated character.

Creation Graphs Sample use of creation graphs.

Gameplay First
A sample first-person game.
Person

Gameplay
A sample first-person game with intractable entities.
Interaction System

Gameplay Third
A sample third-person game.
Person

Modular Dungeon A sample modular project that lets you compose dungeon scenes
Kit out of modular components.

Physics A sample project that demonstrates the use of physics.

Pong A sample visual scripting and gameplay project.

Ray Tracing: Hello


A sample project showing how to use the ray tracing APIs.
Triangle

Sound A sample project demonstrating sound playback.

All Sample Projects A zip containing all sample projects.

The All Sample Projects download contains all these projects, and also some sample engine
plugins
that can get you started with extending the engine.

Note that some of the content in these projects was created by other people and licensed under
Creative Common or other licenses. See the *-license.txt files in the projects for attribution
and
license information.

The editor that is included allows you to:

Import various types of DCC assets (FBX, GLTF, etc).


Create simple entities/scenes by placing and arranging assets.
Add scripted behaviors to entities using the visual scripting language in the Entity Graphs.
Add physics collision to objects and modify their physical properties.
Import animations and create advanced animation setups as an Animation State Machine.
Import WAV files and play them or place them on entities.
Run and simulate these behaviors using the Simulate tab.
Extend the engine and the editor with your own plugins that implement new editor tabs,
entity components, gameplay code, etc.
Write your own applications, using The Machinery as an SDK.

4 What we want from you

Just a few things:

1. If you have any problems running the software, encounter crashes, etc, report them on our
public
bug tracker as soon as possible. We
will fix bugs as soon as we can and put out an
update. The Machinery will automatically search
for updates and ask if you want to
download them.

2. To produce better bug reports, install the enable-full-dumps.reg registry file. This will
trigger full crash dumps stored in %appdata%\Local\The Machinery\CrashDumps
if the editor
crashes. This together with logs from %appdata%\Local\The
Machinery\Logs will help us diagnose
the issues.

3. If you have other feedback or questions, post them on our


forum. We appreciate candid,
honest opinions.

Note that you need to create a separate login to log in to the forum. (We might unify the logins
in
the future.)

You can also drop in on our Discord Server. You will frequently find
us there, answering
questions. We'll pay special attention on Thursdays.

5 Editor details

Here you will find more details to help you find your way around The Machinery. You don’t
have to
read this all at once, but you can use it as a reference for when you wonder about
something.

5.1 Logging in

When you first run the-machinery.exe, you will encounter a login screen:
Login screen.

To use the editor, you must log in with an Our Machinery account. If you haven't done so
already,
press the Sign Up button to create an account, or go directly to
https://ourmachinery.com/sign-up.html.

(Note that the Our Machinery account is separate from the Forum account, so even if you
already have
a login to our forum, you still need to create an Our Machinery account. We might
unify them at some
point in the future.)

In addition, you also need to agree to our EULA.

5.2 The editor


The editor.

The Editor allows you to import, create, and edit assets. It is based around a
collection of editing
Tabs, each with a specific purpose. You can drag the
tabs around to rearrange them or drag
them out of the window to create a new
window. Use the Tab menu to create new tabs.

Note that you can have multiple tabs of the same type. For example, you can open
multiple Asset
Browser tabs to easily drag assets between them. Tabs docked in
the same window work
together. If you dock a Preview tab in the same
window as an Asset Browser, it will show a
preview of the selected asset in
that browser. You can create multiple windows to view multiple
assets
simultaneously:
A multi-window layout.

Here’s a brief description of the most important tabs:

The Asset Browser shows all the assets in the project.

The Preview shows a preview of the currently selected asset in the asset browser.

The Entity Tree shows a tree view of the entity you are editing. You start editing an entity
by double-clicking it in the asset browser. In the Entity Tree tab, you can see the entity’s
components
and child entities.

The Scene shows an editable graphic view of the edited entity. Components and child
entities
can be manipulated by selecting them and moving them around using the Move,
Rotate, and Scale
gizmos.

The Properties tab shows the properties of the currently selected object in the scene. You
can
modify the properties by editing them in the properties window.

The Console tab shows diagnostic messages from the application.

The Graph tab allows you to edit Entity Graphs and Creation Graphs. Entity Graphs
let
you script entity behaviors using a visual scripting language. The Creation Graphs let you
create resources such as images, materials and meshes.
The Simulate tab lets you “run” or “simulate” a scene.

The Collaboration tab lets you work together with others in the same editing session.

5.3 Entities

The Machinery uses an entity-component based approach as a flexible way of


representing
“objects” living in a “world”.

An entity is an independently existing object. An entity can have a number of


components
associated with it. These components provide the entity with
specific functionality and features.
The components currently available in The
Machinery are:
Component Description

Animation Simple Player Plays individual animations on the entity.

Assigns an Animation State Machine to the entity which


Animation State Machine
can be used to play and blend between animations.

Adds a camera to the entity. The Scene > Camera menu


Camera
option lets you view the scene through this camera.

Used to capture cubemaps to be used for rendering


Cubemap Capture
reflections.

Renders an asset from a DCC tool. For more advanced


Dcc Asset
rendering you would use the Render component.

Used to “rig” an imported DCC Asset as an entity. See


Entity Rigger
below.

Implements a visual scripting language that can be used


Graph
to script entity behaviors without writing code.

Light Adds a light source to the entity.

Represents a dynamic physics body. Entities that have


Physics Body
this component will be affected by gravity.

Represents a physics joint, such as a hinge or a ball


Physics Joint
bearing.

Represents a physics character controller. Used to move a


Physics Mover
character around the physics world.

Represents a physics collision shape. If the entity has a


Physics Shape physics body, this will be a dynamic shape, otherwise a
static shape.

Render Renders models output by a Creation Graph.

Represents a hierarchy of nodes/bones inside an entity.


Scene Tree Entities with skeletons, such as characters have scene
trees.

Sculpt Component used to free-form sculpt with blocks.

Sound Source Component that will play a looping sound on the entity.

Spin Sample component that spins the entity.


Tag Assigns one or more “tags” to an entity, such as “bullet”,
“player”, “enemy”, etc. When implementing gameplay, we
can query for all entities with a certain tag.

Tessellated Plane Sample component that draws a tessellated plane.

Represents the entity’s location in the world (position,


scale, rotation). Any entity that exists at a specific
location in the world should have a Transform
Transform
Component. Note that you can have entities without a
Transform Component. Such entities can for example be
used to represent abstract logical concepts.

Gives the entity a velocity that moves it through the


Velocity
world.

In addition to components, an entity can also have Child Entities. These are
associated entities
that are spawned together with the entity. Using child
entities, you can create complex entities
with deep hierarchies. For example, a
house could be represented as an entity with doors and
windows as child
entities. The door could in turn have a handle as a child entity.

In The Machinery entity system, an entity can't have multiple components of the same type. So
you
can’t for example create an entity with two Transform Components. This is to avoid
confusion
because if you allowed multiple Transform Components it would be tricky to know
which represented
the “actual” transform of the entity.

In cases where you want multiple components (for example, you may want an entity
with
multiple lights) you have to solve it by creating child entities and have
each child entity hold one
of the lights.

Note that The Machinery does not have specific Scene assets. A scene in The
Machinery is just
an entity with a lot of child entities.

5.4 Basic editing workflow

The basic scene editing workflow in The Machinery looks something like this:

1. Import some asset files into the Asset Browser using File > Import… If you don't have
any
models to work with you can find free ones at Sketchfab for example.

2. Organize the files by right-clicking the Asset Browser and choosing New > New Folder
and by
dragging and dropping.
3. Any imported model, for example fbx or gltf, will appear as a dcc_asset.

4. Rig an entity from the dcc_asset by selecting it and clicking Import Assets in the property
panel. This also imports the materials and images inside the dcc_asset.

5. Double click the imported entity to open it for editing.

6. Add components for physics, animation, scripting, etc to the entity.

7. Open a scene entity that you want to place your imported entity inside. A new project has a
scene
entity called world.entity that you can use. Or you can create your own scene entity
by right
clicking in the Asset Browser and choosing New > New Entity.

8. Drag your asset entities into the scene entity to position them in the scene.

9. Use the Move, Rotate, and Scale tools in the Scene tab to arrange the sub-entities.

10. Holding down shift while using the move tools creates object clones.

11. Select entities or components in the Entity Tree and Scene tabs to modify their properties
using the
Properties Tab.

12. Drag and drop in the Entity Tree Tab to re-link entities.

13. Each tool (Move, Rotate and Scale) has tool-specific settings, such as snapping and pivot
point, in
the upper-left corner of the scene tab.

14. Use Scene > Frame Selection and Scene > Frame Scene to focus the
camera on a
specific selected entity, or the entire scene. Or just use the F key.

15. When you are done, use File > Save Project… to save the scene for future
work.

Known issues:

When you drag a tab out of the current window to create a new one, you don’t
get any
visual feedback until the new window is created.

5.5 Creation graphs and asset pipeline

There are lots of things you might want to do to an imported asset coming from a DCC-tool. For
example, extracting images and materials into a representation that can be further tweaked by
your
artists or rigging an entity from the meshes present in the asset. In The Machinery, we
provide full
control over how data enters the engine and what data-processing steps that get
executed, allowing
technical artists to better optimize content and setup custom, game-specific
asset pipelines.

This is handled through Creation Graphs. A Creation Graph is essentially a generic framework
for
processing arbitrary data on the CPUs and GPUs, exposed through a graph front-end view.
While we can
use Creation Graphs for any type of data processing, we will for the rest of this
section be
focusing on how to set up a simple entity from an imported dcc_asset. If you wish to
see other use
cases such as particle systems, sky rendering and sprite sheets, then have a look in
the
creation_graphs sample that we provide.

5.5.1 Importing a DCC asset

You can import an asset by selecting File > Import... in the main menu, pressing Ctrl-I, or
dropping a DCC file on the Asset Browser tab. When you do this, it ends up in our data-model as
a
dcc_asset. A dcc_asset can hold all types of data that was used to build the asset in the
DCC-
tool, such as objects, images, materials, geometry and animation data.

During the import step, The Machinery only runs a bare minimum of data processing, just
enough so
that we can display a visual representation of the asset in the Preview tab. Imports
run in the
background so you can continue to work uninterrupted. When the import finishes the
asset will show
up in the Asset Browser. Note that import of large assets can take a significant
amount of time.
You can monitor the progress of the import operation in the status bar.

5.5.2 Basic entity rigging, with image and material extraction

If you click on a dcc_asset that contains a mesh in the Asset Browser, you will be presented
with importer settings in the Properties tab:
Inspecting a dcc_asset

The Preview tab does just enough to show you what the dcc_asset contains, but what you
probably
want is an entity that contains child entities representing the meshes found inside the
dcc_asset. Also, you probably want it to extract the images and materials from the dcc_asset so
you can continue to tweak those inside The Machinery. There are two ways to do this. Either you
drag
the DCC asset onto the Scene Tab, or you click the Import Asset button. The Import Assets
button will automatically create a prototype Entity Asset in your project, while dropping it into
the scene will rig the entity inside the scene, without creating a prototype.

In either case, we will for our door.dcc_asset get a door.resources directory next to it. This
directory will contain materials and images extracted from the DCC asset. If you prefer dropping
the assets into the scene directly, but also want an entity prototype, then you can check the
Create Prototype on Drop check box.

Each image and material in the resources folder is a Creation Graph, which is responsible for
the
data-processing of those resources. You can inspect these graphs to see what each one does.
They are
described in more detail below.

5.5.3 Creation Graphs for dcc_asset import

In The Machinery, there are no specific asset types for images or materials, instead, we only
have
Creation Graphs (.creation assets). To extract data from a dcc_asset in a creation graph,
the
dcc_asset-plugin exposes a set of helper nodes in the DCC Asset category:
DCC Asset/DCC Image — Takes the source dcc_asset together with the name of the image
as input
and outputs a GPU Image that can be wired into various data processing nodes
(such as mipmap
generation through the Image/Filter Image node) or directly to a
shader node.

DCC Asset/DCC Material — Takes the source dcc_asset together with the name of the
material as
input and outputs all properties of the material model found inside the
dcc_asset. This material
representation is a close match to GLTF 2.0's PBR material
model. Image outputs are references to
other .creation assets which in turn output GPU
Images.

DCC Asset/DCC Mesh — Takes the source dcc_asset together with the name of the mesh as
input
and outputs a GPU Geometry that can be wired to an Output/Draw Call output node
for rendering
together with the minimum and maximum extents of the geometry that can
be wired to an
Output/Bounding Volume output node for culling.

The steps for extracting images and material .creation assets from a dcc_asset involve
deciding
what data-processing should be done to the data before it gets wired to an output node
of the graph.
This can either be done by manually assembling creation graphs for each image
and material, or by
building a generic creation graph for each asset type and use that as a
prototype when running a
batch processing step we refer to as Resource Extraction.

Here's an example of what a generic creation graph prototype for extracting images might look
like:

Simple image processing.

To quickly get up and running we provide a number of pre-authored creation graphs for some of
the
more common operations:

import-image— Operations applied to images imported directly into the editor (not as part
of a
dcc-asset).
dcc-image — Operations applied to images extracted from an imported dcc_asset.

dcc-material — Shader graph setup to represent materials extracted from an imported


dcc_asset.

dcc-mesh — Operations for generating a draw call that reprensents a mesh from an
imported dcc_asset.

drop-image — Operations for generating a draw call to display the image output of another
creation graph in the context of an entity, making it possible to drag-and-drop images into
the
Scene Tab.

These pre-authored creation graphs are shipped as part of our Core project which is
automatically
copied into new projects. How they are used when working with assets is exposed
through the
import_settings asset:

Default Import Settings.


By exposing these settings through an asset it is possible to easily change the default behavior of
how imported assets are treated when placed under a specific folder. It's worth noting that this
is
somewhat of a power-user feature and not something you need to have a detailed
understanding of to get started working with The Machinery.

5.6 Prototypes

The Machinery has a prototype system that allows entity assets to be used inside
other entities.
So you can for example create an entity asset that represents a
room, and then create a house
entity that has a bunch of these room entities
placed into it:

Three Room entities placed to form a House entity.

We call the room asset a prototype, and we call each placed room entity an
instance of that
prototype. Note that prototypes are not special assets, any
entity asset can be used as a
prototype, with instances of it placed in another
entity asset.

In the Entity Tree tab, prototype instances are shown in yellow to distinguish them from locally
owned child entities (which are shown in white).

If you expand an instance you will notice that most of its components and child entities are
grayed
out and can't be selected. This is because they are inherited from the prototype, and the
prototype
controls their values. If the prototype is modified — for example if we scatter some
more props on
the floor — those changes are reflected everywhere the prototype has been
placed. In the example
above, all three room instances would get the scattered objects.

If we want to, however, we can choose to override some of the prototype’s


properties. When we
override a property, we modify its value for this instance
of the prototype only. Other instances
will keep the value from the prototype.

To initiate an override, right-click the component or child entity whose


properties you want to
override and choose Override in the context
menu. In addition to modifying properties, you
can also add or remove components
or child entities on the overridden entity.

If you override the property of some node deep in the hierarchy of the placed entity, all its
parents will automatically get overridden too. Let's modify the position of the barrel in the
front-
most room:

Barrel position overridden.

The overridden entities and components are drawn in blue. We change the x and z components
of the
position to move the barrel. Note how the changed values are shown in white, while the
values that
are inherited from the prototype are shown in gray.

If you look back to the first picture you will see that the Link Component was
automatically
overridden when the prototype was instanced. This is needed
because if we didn’t override the
Link Component, it would use the values from
the prototype, which means all three room
instances would be placed in the same
position.

When we override something on an instance, all the things not explicitly


overridden are still
inherited from the prototype. If we modify the prototype —
for example change the barrel to a
torch — all instances will get the change,
since it was only the x and z positions of the object that
we changed.

The context menus can be used to perform other prototype operations. For example,
you can
Reset properties back to the prototype values. You can also
Propagate the changes you have
made to an overridden component or entity
back to the prototype so that all instances get the
changes. Finally, you can
Remove the overrides and get the instance back to being an exact
replica of
the prototype.

Prototypes can also be used for other things than entities. For example, if you have a graph that
you want to reuse in different places you can create a Graph Asset to hold the graph, and then
instantiate that asset in the various places where you want to use it. Just as with the entity
instances, you can override specific nodes in the graph instance to customize the behavior.

5.7 Simulation

In The Machinery, we make a distinction between simulating and editing. When you are
editing,
you see a static view of the scene. All the runtime behaviors like physics, animation,
destruction,
entity spawning, etc are disabled. (Editing the scene with everything moving
around would be very
tricky.)

In contrast, when you are simulating or running, all the dynamic behaviors are enabled. This
allows you to see the runtime behavior of your entities. If you are building a game, the
simulation
mode would correspond to running the game.

To simulate a scene, open a scene in the Simulate tab.


Simulate tab.

You can use the controls in the tab to pause, play, or restart the simulation or change the
simulation speed. Note that if you haven't added any simulation components to the scene, the
Simulate tab will be just as static as the Scene tab. In order to get something to happen, you
need to add some runtime components.

The Entity Graph gives you a visual scripting language for controlling entity behavior. It will
be
described in the next section.

You can launch the engine in simulation mode from the command line:

the-machinery.exe --load-project project.the_machinery --simulate scene

Here project.the_machinery should be the name of your project file and scene the name of the
entity you want to simulate. This will open a window with just the Simulate tab, simulating the
scene that you specified.

5.8 Entity Graphs


The Entity Graph implements a visual scripting language based on nodes and connections. To
use
it, right-click on an entity to add a Graph Component and then double click on the Graph
Component
to open it in the Graph Editor:

Graph editor.

The visual scripting language uses Events to tick the execution of nodes. For example, the
Tick
Event node will trigger its out connector whenever the application ticks its frame. Connect
its
output event connector to another node to run that node during the application's update.

Nodes that just fetch data and don't have any side-effects are considered “pure”. They don't have
any event connectors and will run automatically whenever their data is needed by one of the
non-pure
nodes. Connect the data connectors with wires to pass data between nodes.

In addition to connecting wires, you can also edit input data on the nodes directly. Click a node
to select it and edit its input data in the properties.

There are a lot of different nodes in the system and I will not attempt to describe all of them.
Instead, here is a simple example that adds a super simple animation to an entity using the
graph
component:
README: Adding a simple behavior

Adding a simple behavior.

For more examples, check out the pong and animation projects in the samples.

5.9 Physics

The Machinery integrates Nvidia's PhysX toolkit and uses it for physics simulation of entities.
This
section will not attempt to describe in detail how physics simulation works, for that we
refer to
the PhysX documentation. We will only talk about how physics is set up in The
Machinery.

The physics simulation system introduces two new assets: Physics Material and Physics
Collision
as well as four new components: Physics Shape Component, Physics Body
Component, Physics
Joint Component, and Physics Mover Component.

A Physics Material asset specifies the physical properties of a physics object: friction (how
“slippery” the object is) and restitution (how “bouncy” the object is). Note that if you don't
assign a material to a physics shape it will get default values for friction and constitution.

A Physics Collision asset describes a collision class. Collision Classes control which physics
shapes collide with each other. For example, a common thing to do is to have a debris class for
small objects and set it up so that debris collide with regular objects, but not with other
debris.
That way, you are not wasting resources on computing collisions between lots of tiny
objects.
(Note that the debris objects still need to collide with regular objects, or they would
just fall
through the world.)
In addition to deciding who collides with who, the collision class also decides which collisions
generate callback events. These events can be handled in the Entity Graph.

If you don't assign a collision class to a physics shape, it will get the Default collision class.

The Physics Shape Component can be added to an entity to give it a collision shape for physics.
Entities with shape components will collide with each other when physics is simulated.

A physics shape can either be specified as geometry (sphere, capsule, plane, box) or it can be
computed from a graphics mesh (convex, mesh). Note that if you use computed geometry, you
must press
the Cook button in the Properties UI to explicitly compute the geometry for the
object.

Convex shape.

If you just give an entity a Physics Shape Component it will become a static physics object.
Other
moving objects can still collide with it, but the object itself won't move.

To create a moving physics object, you need to add a Physics Body Component. The body
component
lets you specify dynamic properties such as damping, mass, and inertia tensor. It
also lets you
specify whether the object should be kinematic or not. A kinematic object is being
moved by
animation. Its movement is not affected by physics, but it can still affect other
physical
objects by colliding with them and pushing them around. In contrast, if the object is not
kinematic it will be completely controlled by physics. If you place it above ground, it will fall
down as soon as you start the simulation.

Note that parameters such as damping and mass do not really affect kinematic objects, since
the
animations will move them the same way, regardless of their mass or damping. However, these
parameters can still be important because gameplay code could at some point change the object
from being kinematic to non-kinematic. If the gameplay code never makes the body non-
kinematic, the
mass doesn't matter.

The Physics Joint Component can be used to add joints to the physics simulation. Joints can tie
together physics bodies in various ways. For example, if you tie together two bodies with a hinge
joint they will swing as if they were connected by a hinge. For a more thorough description of
joints, we refer to the PhysX documentation.

The Physics Mover Component implements a physics-based character controller. If you add it to
an
entity, it will keep the entity's feet on the ground, prevent it from going through walls, etc.
For
an example of how to use the character controller, check out the animation or gameplay
sample
projects.
Note that The Machinery doesn't currently support all the features found in PhysX. The most
glaring omissions are:

D6 joints and joint motors.


Vehicles.

We will add more support going forward.

For an example of how to use physics, see the physics sample project.

5.9.1 Physics scripting

Physics can be scripted using the visual scripting language in the Entity Graph.

We can divide the PhysX scripting nodes into a few categories.

Nodes that query the state of a physics body:

Get Angular Velocity


Get Velocity
Is Joint Broken
Is Kinematic

Nodes that manipulate physics bodies:

Add Force
Add Torque
Break Joint
Push
Set Angular Velocity
Set Kinematic
Set Velocity

Event nodes that get triggered when something happens in the scene:

On Contact Event
On Joint Break Event
On Trigger Event

Nodes that query the world for physics bodies:

Overlap
Raycast
Sweep

Note that the query nodes may return more than one result. They will do that by triggering their
Out event multiple times, each time with one of the result objects. (In the future we might
change
this and have the nodes actually return arrays of objects.)

5.10 Animation

The Animation system lets you play animations on entities. You can also create complicated
animation blends, crossfades, and transitions using an Animation State Machine.

The animation system adds two new assets to The Machinery: Animation Clip and Animation
State
Machine as well as two new components: Animation Simple Player and Animation State
Machine.

To get an animation into The Machinery you first export it from your DCC tool as FBX or
another
suitable file format. Then you import this using File > Import....

An Animation Clip is an asset created from an imported DCC animation asset that adds some
additional data. First, you can set a range of the original animation to use for the clip, so you
can
cut up a long animation into several individual clips. Second, you can specify whether the
animation should loop or not as well as its playback speed. You can use a negative playback
speed to
get a “reverse” animation.

Finally, you can specify a “locomotion” node for the animation. If you do, the delta motion of
that
node will be extracted from the animation and applied to the entity that animation is played
on,
instead of to that bone. This lets an animation “drive” the entity and is useful for things like
walking and running animations. The locomotion node should typically be the root node of the
skeleton. If the root mode is animated and you “don't” specify a locomotion node, the result will
be
that the root node “walks away” from the animation.
locomotion-node

Locomotion node.

The Animation Simple Player Component is a component that you can add to an entity to play
animations on it. The component lets you pick a single animation to play on the entity. This is
useful when you want to play simple animations such as doors opening, coins spinning, flags
waving,
etc. If you want more control over the playback and be able to crossfade and blend
between
animations you should use an Animation State Machine instead.

5.10.1 Animation state machines

The Animation State Machine Asset represents an Animation State Machine. If you double-
click an
Animation State Machine Asset in the Asset Browser, an Animation State Machine
Editor will open:

Animation State Machine Editor

The Animation State Machine (ASM) introduces a number of concepts: Layers, States,
Transitions, Events, Variables, and Blend Sets.

The ASM represents a complex animation setup with multiple animations that can be played on
a
character by dividing it into States. Each state represents something the character is doing
(running, walking, swimming, jumping, etc) and in each state, one particular animation, or a
particular blend of animations is being played. The states are the boxes in the State Graph.
The ASM can change state by taking a Transition from one state to another. The transitions are
represented by arrows in the graph. When the transition is taken, the animation crossfades over
from
the animations in one state to the animations in the other state. The properties of the
transition
specify the crossfade time. Note that even though the crossfade takes some time, the
logical state
transition is immediate. I.e. as soon as the transition is taken, the state machine
will logically
be in the new state.

The transitions are triggered by Events. An event is simply a named thing that can be sent to the
ASM from gameplay code. For example, the gameplay may send a “jump” event and that triggers
the
animation to transition to the “jump” state.

Variables are float values that can be set from gameplay code to affect how the animations play.
The variables can be used in the states to affect their playback. For example, you may create a
variable called run_speed and set the playback Speed of your run state to be run_speed.
That
way, gameplay can control the speed of the animation.

Note that the Speed of a state can be set to a fixed number, a variable, or a mathematical
expression using variables and numbers. (E.g. run_speed * 2.) We have a small expression
language
that we use to evaluate these expressions.

The ASM supports multiple Layers of state graphs. This works similar to image layering in an
application such as Photoshop. Animations in “higher” layers will be played “on top” of
animations
in the lower layers and hide them.

As an example of how to use layering, you could have a bottom layer that controls the player's
basic
locomotion (walking, running, etc). Then you could have a second layer on top of that for
controlling arm movements. That way, you could play a reload animation on the arms while the
legs
are still running. Finally, you could have a top layer to play “hurt” animations when the
player for
example gets hit by a bullet. These hurt animations could then interrupt the reload
animations
whenever the player got hit.

Blend Sets can be used to control the per-bone opacity of animations playing in higher layers.
They simply specify a weight for each bone. In the example above, the animations in the “arm
movement” layer would have opacity 1.0 for all arm bones, but 0.0 for all leg bones. That way,
they
would hide the arm movement from the running animation below, but let the leg
movement show through.

The Animation State Machine Editor has a Tree View to the left that lets you browse all the
layers, states, transitions, events, variables, and blend sets. The State Graph lets you edit the
states and transitions in the current layer. The Properties window lets you set the properties of
the currently selected objects and the Preview shows you a preview of what the animation looks
like. Note that for the preview to work, you must specify a Preview Entity in the properties of
the state machine. This is the entity that will be used to preview the ASM. When you select a
state
in the State Graph, the preview will update to show that state.

In the Preview window, you also find the Motion Mixer. This allows you to send events to the
ASM
and change variables to see how the animation reacts.

The ASM currently supports the following animation states:

Regular State

Plays a regular animation.

Random State

Randomly plays an animation out of a set of options.

Empty State

A state that doesn't play any animation at all. Note that this state is only useful in higher layers.
You can transition to an empty state to “clear” the animation in the layer and let the animations
from
the layers below it shine through.

Blend State

Allows you to make a 1D or 2D blend between animations based on the value of variables. This is
often
used for locomotion. You can use different animations based on the characters running
speed and whether
the character is turning left or right and position them on a map to blend
between them.

Animation Blending

Once you have created an Animation State Machine, you can assign it to a character by giving it
an
Animation State Machine Component.

For an example of how the animation system works, have a look at the mannequin sample
project.

5.10.2 Missing features

Note that the animation system is still under active development. Here are some features that
are
planned for the near future:
Ragdolls.
Animation compression.
Triggers.
More animation states.
Offset State.
Template State.
Expression-based Blend State.
Graph-based Blend State.
Beat transitions.
Constraints.

5.11 Sound

The Machinery comes with a low-level sound system that can import WAV files into the project
and
play them back. The sound system can position sounds in 3D space and mix together 2D
and 3D sounds
for output on a stereo, 5.1, or 7.1 sound system.

You can play a sound by adding a Sound Source Component to an object in the level of by using
one
of the sound playing nodes in the visual scripting language.

5.11.1 Missing features

The sound system is rudimentary. Here are some features that are planned for the future:

Sound streaming
Sound compression
WASAPI backend
React to the user plugging in or unplugging headphones
Hermite-interpolated resampling
Reverb
Directional sound sources
Doppler effect
Multiple listeners
HRTF
High-level sound system
Random sounds
Composite sounds
Streaming sounds
Compressing sounds
5.12 Simulate Entry (writing gameplay code in C)

If you wish to program gameplay using C code, then you need some place where this code
execution
enters. This is provided by the Simulate Entry interface. In order to use it, begin by
implementing
the the interface tm_simulate_entry_i (see simulate_entry.h). Make an object
of the
tm_simulate_entry_i struct like this (see any of the gameplay samples for examples with
more
context):

static tm_simulate_entry_i simulate_entry_i = {

.id = TM_STATIC_HASH("tm_my_game_simulate_entry", 0xe240e2d67a0aa93ULL),

.display_name = TM_LOCALIZE_LATER("My Game Simulate Entry"),

.start = start,

.stop = stop,

.tick = tick,

};

where start(), stop() and tick() are the functions that you want called when the game starts,
ends
and each frame respectively. Make sure that id is unique. When your plugin loads, make
sure to
register this implementation of tm_simulate_entry_i on the
TM_SIMULATE_ENTRY_INTERFACE_NAME
interface name, like so:

tm_add_or_remove_implementation(reg, load, TM_SIMULATE_ENTRY_INTERFACE_NAME,


&simulate_entry_i);

After you've done this, create a Simulate Entry asset in a directory next to one of your scene
entities:
Creating a Simulate Entry asset

When you inspect the the properties of this new Simulate Entry asset, have a look in the
Simulate Entry dropdown menu. Given that you registered your implementation of
tm_simulate_entry_i
correctly, it should appear in this list.

Now, whenever you start simulating a certain entity, such as your main game world, the
Simulate Tab
will look in the directory next to the entity you're simulating and check if there is a
Simulate
Entry asset there. If there is, it will use the referenced tm_simulate_entry_i
implementation in
order to enter into gameplay code. If the Simulate Tab fails to find a Simulate
Entry asset in the
same directory, it will look in each parent directory. This makes it possible to
put a “catch-all”
Simulate Entry in the root directory of your project. You can also put entities
that need different
Simulate Entry code in separate directories, with a Simulate Entry asset next
to each, which can
reference different implementations of the the tm_simulate_entry_i
interface.

5.13 Collaboration

The editor has built-in support for real-time collaboration, allowing multiple people to work
together in the same project. All user actions — importing assets, creating and editing entities,
etc, are supported in the collaborative workflow.

In our collaboration model, one of the users always acts as a host. The host
invites others to join
her in editing her project. All the changes made by the
participants in the session end up in the
host’s project and it’s the host’s
responsibility to save the project, check in the changes into
version control, or
do whatever else is needed to make the changes permanent.

To host a collaboration setting, open the collaboration tab from Tab >
Collaboration and
choose one of the Host options.

Host LAN Server: Host a server on your LAN. The system will choose a free port on your
machine
for hosting. Other users on the same LAN can join your session by choosing Join
LAN Server and
selecting your machine.

Host Internet Server: Host a server that can be accessed over the internet on a
specified port.
If you check the “Use UPnP” checkbox the system will attempt to use UPnP
to open the port in your
router, so that external users can access your server. To connect,
an external user would choose
Join Internet Server and specify your external IP address.

Note that there is no guarantee that UPnP works with your particular router. If Internet
hosting
is not working for you, you may have to manually forward the hosting port in your
router.

Host Discord Server: Host a server through Discord. You must have the Discord app
running on
your machine to use this option. You can invite friends to your discord editing
session by selecting
them in your active friends list and sending them invites.

Collaboration tab when hosting.


If you just want to try out collaboration on your own, you can run the client and the host on the
same machine (just start two instances of the_machinery.exe) and connect using the LAN
option.

Collaboration session running on a single machine.

6 Extending The Machinery

6.1 Writing a plugin

The Machinery is built around a plugin model. All features, even the built-in ones, are provided
through plugins. You can extend The Machinery by writing your own plugins. When The
Machinery
launches, it loads all the plugins named tm_*.dll in its plugins/ folder. If you write
your own
plugins, name them so that they start with tm_ and put them in this folder, they will be
loaded
together with the built-in plugins.
The easiest way to build a plugin is to start with an existing example. There are three places
where
you can find plugin samples:

1. The samples folder in the SDK has a number of plugin samples.

2. The All Sample Projects package in the Download tab has a plugins folder with some
small
samples.

3. You can create a new plugin with the menu command File > New Plugin. This will
create a
new .c file for the plugin together with some helper files for compiling it.

The distribution already comes with pre-built .dlls for the sample plugins, such as
bin/plugins/tm_pong_tab.dll. You can see this plugin in action by selecting Tab > Pong in
the
editor to open up its tab:

Pong tab.

To build the sample plugins (and your own) you need three things:

1. You need to have Visual Studio 2019 installed including the MS C++ Build Tools on your
computer.
Note that the Community Edition works fine.
2. You need to set the TM_SDK_DIR environment variable to the path of the SDK package that
you
installed on your computer. When you compile a plugin, it looks for The Machinery
headers in the
%TM_SDK_DIR%/headers folder.

3. You need the tmbuild.exe from the SDK package. tmbuild.exe does all the steps needed
to
compile the plugin. Put it in your PATH or copy it to your plugin folder so that you can
run it
easily from the command line.

To compile a plugin, simply open a command prompt in the plugin folder and run the
tmbuild.exe
executable:

sample-projects/plugins/custom_tab> %TM_SDK_DIR%/bin/tmbuild.exe
Installing 7za.exe...

Installing premake-5.0.0-alpha14-windows...

Building configurations...

Running action 'vs2019'...

Generated custom_tab.sln...

Generated build/custom_tab/custom_tab.vcxproj...

Done (133ms).

Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Framework

Copyright (C) Microsoft Corporation. All rights reserved.

custom_tab.c

custom_tab.vcxproj -> C:\work\themachinery\build\bin\plugins\tm_custom_tab.dll

-----------------------------
tmbuild completed in: 23.471 s

tmbuild.exe will perform the following steps to build your executable:

1. Create a libs folder and download premake5 into it. (You can set the TM_LIB_DIR
environment
variable to use a shared libs dir for all your projects.)

2. Run premake5 to create a Visual Studio project from the premake5.lua script.

3. Build the Visual Studio project to build the plugin.

In order to write a plugin, it is useful to understand a little bit about how the plugin system in
The
Machinery works.

The Machinery uses C99 as its interface language. I.e., all the header files that you use to
communicate with The Machinery are C99 header files, and when you write a plugin you should
expose
C99 headers for your APIs. The implementation of a plugin can be written in whichever
language you
like, as long as it exposes and communicates through a C99 header. In particular,
you can write the
implementation in C++ if you want to. (At Our Machinery, we write the
implementations in C99.)

The Machinery is organized into individual APIs that can be called to perform specific tasks. A
plugin is a DLL that exposes one or several of these APIs. In order to implement its
functionality,
the plugin may in turn rely on APIs exposed by other plugins.

A central object called the API registry is used to keep track of all the APIs. When you want to
use an API from another plugin, you ask the API registry for it. Similarly, you expose your APIs
to
the world by registering them with the API registry.

This may seem a bit abstract at this point, so let’s look at a concrete example, unicode.h which
exposes an API for encoding and decoding Unicode strings:

// This header has been abridged and commented from the original to make things

// clearer.

// Include standard header.

#include "api_types.h"

// Forward declarations.

struct tm_temp_allocator_i;

// Name of this API in the registry.

#define TM_UNICODE_API_NAME "tm_unicode_api"

// Unicode helper functions.

struct tm_unicode_api

// Encodes the `codepoint` as UTF-8 into `utf8` and returns a pointer to the

// position where to insert the next codepoint. `utf8` should have room for at
// least four bytes (the maximum size of a UTF-8 encoded codepoint).

char *(*utf8_encode)(char *utf8, uint32_t codepoint);

// Decodes and returns the first codepoint in the UTF-8 string `utf8`. The string

// pointer is advanced to point to the next codepoint in the string. Will generate

// an error message if the string is not a UTF-8 string.

uint32_t (*utf8_decode)(const char **utf8);

// ...

};

Let’s go through this.

First, the code includes <api_types.h>. This is a shared header with common type declarations,
it
includes things like <stdbool.h> and <stdint.h> and also defines a few The Machinery
specific
types, such as tm_vec3_t.

In The Machinery we have a rule that header files can't include other header files (except
for
<api_types.h>). This helps keep compile times down, but it also simplifies the structure of the
code. When you read a header file you don’t have to follow a long chain of other header files to
understand
what is happening.

Next follows a block of forward struct declarations (in this case only one).

Next, we have the name of this API defined as a constant TM_UNICODE_API_NAME, followed by the
struct tm_unicode_api that defines the functions in the API.

To use this API, you would first use the API registry to query for the API pointer, then using that
pointer, call the functions of the API:

struct tm_unicode_api *tm_unicode_api =

(struct tm_unicode_api *)tm_global_api_registry->get(TM_UNICODE_API_NAME);

tm_unicode_api->utf8_encode(utf8, codepoint);

The different APIs that you can query for and use are documented in their respective header
files,
and in the apidoc.md.html documentation file (which is just extracted from the headers).
Consult
these files for information on how to use the various APIs that are available in The
Machinery.

In addition to APIs defined in header files, The Machinery also contains some header files with
inline functions that you can include directly into your implementation files. For example
<math.inl> provides common mathematical operations on vectors and matrices, while
<carray.inl>
provides a “stretchy-buffer” implementation (i.e. a C version of C++’s
std::vector).

To write a plugin you need to implement a tm_load_plugin() function that is called whenever
the
plugin DLL is loaded/unloaded. In this function, you can interact with various engine
interfaces. For
example, you can implement TM_UNIT_TEST_INTERFACE_NAME to implement unit
tests that get run
together with the engine unit tests, you can implement
TM_THE_TRUTH_CREATE_TYPES_INTERFACE_NAME to
extend our data model, The Truth, with your
own data types or implement
TM_ENTITY_CREATE_COMPONENT_INTERFACE_NAME to extend our
entity model with your own component
types.

You can also create your own APIs that other plugins can query for. If you create your own APIs,
you
want to define them in your header file, so that other plugins can #include it and know how
to
call your APIs. Note that if you are not defining your own APIs, but just implementing some
of the
engine's ones, your plugin typically doesn't need a header file:
my_plugin.h:

#include "foundation/api_types.h"

#define MY_API_NAME "my_api"

struct my_api

void (*foo)(void);

};

my_plugin.c:
static struct tm_api_registry_api *tm_global_api_registry;

static struct tm_error_api *tm_error_api;

static struct tm_logger_api *tm_logger_api;

#include "my_plugin.h"

#include "foundation/api_registry.h"

#include "foundation/error.h"

#include "foundation/log.h"

#include "foundation/unit_test.h"

static void foo(void)

// ...

static struct my_api *my_api = &(struct my_api) {


.foo = foo,

};

static void my_unit_test(tm_unit_test_runner_i *tr, struct tm_allocator_i *a)

// ...

static struct tm_unit_test_i *my_unit_test = &(struct tm_unit_test_i) {

.name = "my_api",

.test = my_unit_test,

};

TM_DLL_EXPORT void tm_load_plugin(struct tm_api_registry_api *reg, bool load)

tm_global_api_registry = reg;

tm_error_api = reg->get(TM_ERROR_API_NAME);

tm_logger_api = reg->get(TM_LOGGER_API_NAME);

tm_set_or_remove_api(reg, load, MY_API_NAME, my_api);

tm_add_or_remove_implementation(reg, load, TM_UNIT_TEST_INTERFACE_NAME,


my_unit_test);

When The Machinery loads a plugin DLL, it looks for the tm_load_plugin() function and calls
it.
If it can't find the function, it prints an error message.
We store the API registry pointer in a static variable so that we can use it everywhere in our
DLL.
We also get() some of the API pointers that we will use frequently and store them in static
variables so that we don’t have to use the registry to query for them every time we want to use
them. Finally, we add our own API to the registry, so others can query for and use it.

We also add an implementation of the unit test interface to the registry. The API registry has
support for both APIs and interfaces. The difference is that APIs only have a single
implementation,
whereas interfaces can have many implementations. For example, all code that
can be unit-tested
implements the unit test interface. Unit test programs can query the API
registry to find all these
implementations and run all the unit tests.

To extend the editor you add implementations to the interfaces used by the editor. For example,
you
can add implementations of the TM_THE_TRUTH_CREATE_TYPES_INTERFACE_NAME in order to
create new
data types in The Truth, and add implementations of the
TM_ENTITY_CREATE_COMPONENT_INTERFACE_NAME
in order to define new entity components. See
the sample plugin examples.

It does not matter in which order the plugins are loaded. If you query for a plugin that hasn’t yet
been registered, you get a pointer to a nulled struct back. When the plugin is loaded, that struct
is filled in with the actual function pointers. As long as you don’t call the functions before the
plugin that implements them has been loaded, you are good. (You can test this by checking for
NULL
pointers in the struct.)

6.1.1 Hot-reloading

We support hot-reloading of plugins while The Machinery is running. This allows you to work
on a
plugin and see the changes in real-time without having to shut down and restart the
application
between each change to your code.

Hot-reloading is enabled by default, but can be disabled with the --no-hot-reload parameter.

When a reload happens, the function pointers in the plugin's API struct are replaced with
function
pointers to the new code. Since clients hold pointers to this struct, they will use the new
function
pointers automatically — they don't have to re-query the system for the API.

Note that hot-reloading is not magical and can break in a lot of situations. For example, if you
remove functions in the API or change their parameters, any clients of your API will still try to
call them using the old parameter lists, and things will most likely crash. Similarly, if a client
has
stashed away a function pointer to one of your API functions somewhere, such as in a list of
callbacks, there is no way for us to patch that copy and it will continue to call the old code.
Also,
if you make changes to the layout of live data objects (such as adding or removing struct
fields)
things will break because we make no attempts to transfer the data to the new struct
format.
But adding or removing static functions, or changing the code inside functions should work
without
problems. We find hot-reloading to be a big time saver even if it doesn't work in all
circumstances.

If you want to use global variables in your DLL you should do so using the
tm_api_registry_api->static_variable() function in your tm_load_plugin() code. If you just
declare a global variable in your .c file, that variable will be allocated in the DLLs memory space
and when the DLL is reloaded you will lose all changes to the variable. When you use
static_variable(), the variable is allocated on the heap, and its content is preserved when the
DLL is reloaded.

If you are using hot-reloading together with a debugger on Windows, be aware that the
debugger will
lock .pdb files which will prevent you from rebuilding your code. The suggested
workflow is
something like this:

Detach the debugger if it's currently attached.


Rebuild your DLL and fix any compiler bugs.
When the DLL is built successfully, The Machinery will automatically reload it.
If you need to continue debugging, re-attach the debugger.

6.1.2 Plugin assets

When you put a plugin in the plugin folder, it will be loaded every time you start The Machinery
and used by all projects. This is convenient, but sometimes you want plugins that are project
specific, e.g., the gameplay code for a particular game.

There are two ways of doing this.

First, you could create a separate The Machinery executable folder for that specific project. Just
make a copy of the The Machinery folder and add any plugins you need. Whenever you want to
work on
that project, make sure to start that executable instead of the standard one.

In addition to adding project specific plugins, this method also lets you do additional things,
such as using different versions of The Machinery for different projects and remove any of the
standard plugins that you don't need in your project.

The second method is to store plugins as assets in the project itself. To do this, create a New
Plugin in the Asset Browser and set the DLL path of the plugin to your DLL. We call this a
Plugin Asset.

The Plugin Assets will be loaded whenever you open the project and unloaded whenever you
close
the project. Since the plugin is distributed with the project, if you send the project to
someone,
they will automatically get the plugin too — they don't have to manually install into
their
plugin folder. This can be a convenient way of distributing plugins.

⚠ Security Warning

Since plugin assets can contain arbitrary code and there is no sandboxing, when you
run a
plugin asset, it will have full access to your machine. Therefore, you should only
run plugin
assets from trusted sources. When you open a project that contains plugin
assets, you will be asked if you want to allow the code to run on your machine or not.
You should only click
[Allow] if you trust the author of the project.

Version Issues

Since The Machinery is still in early adopters mode and doesn't have a stable API,
plugins will only work
with the specific version they are developed for. If you send a
plugin to someone else
(for example as a plugin asset in a project), you must make
sure that they use the exact same
version of The Machinery. Otherwise, the plugin will
most likely crash.

You hot-reload plugin assets by checking the Import When Changed checkbox in the plugin
properties. If checked, the editor will monitor the plugin's import path for changes and if it
detects a file change, it will reimport the plugin.

6.1.3 Extending the visual scripting language

You can extend the visual scripting language with your own nodes.

To do this, you first write the code that implements the function that the node performs,
together
with some macros that specify how to create a visual scripting node from the code.
Then you run
generate-graph-nodes.exe to generate an *.inl file with glue code.

For example, here's some code for computing the square of a floating-point number:
GGN_BEGIN("Sample/Math/Float");

GGN_NODE_QUERY();

static inline void sample_float_square(float a, float *res)

*res = a * a;

GGN_GEN_REGISTER_FUNCTION();

GGN_END();

#include "my_graph_nodes.inl"

There are some things to note here:

Node functions always return their results in pointer variables (the reason is that they
can
have more than one result).

All the code for the node(s) is surrounded by two special macros:
GGN_BEGIN() and
GGN_END().

The GGN_NODE_QUERY() macro marks this node as a Query node. Query nodes are triggered
automatically when their output is requested. Nodes that aren't query nodes need to be
triggered
by an explicit event.

The GGN_GEN_REGISTER_FUNCTION() macro automatically creates a register function for


registering
the node with the visual scripting system.

generate-graph-nodes.exe will only check files with graph_nodes in their name by


default.

For more samples on how to write nodes, see code/graph_nodes in the distribution package. See
plugins/graph_interpreter/graph_node_macros.h for a description of the macros you can use.

The GGN_* macros are processed by the helper program generate-graph-nodes.exe. This
program
generates glue code that ties your function into the graph system — creating
connectors that
correspond to your function parameters, etc.

The glue code is stored in an .inl file with the same name as the .c file that contains the
graph
nodes. To use the glue code, you need to include it in your .c file as shown above.

The final thing you need to do is to register your graph nodes with the graph interpreter system.
See the samples/plugins/graph_nodes sample for an example of how to do that.
6.2 Writing an executable

Writing a stand-alone executable is similar to writing a plugin except that you need to write
initialization code for booting up all the systems that you want to use as well as the main loop
code that runs the executable.

bin/simple-draw.exe is a sample executable that uses the UI / Draw2D interfaces of The


Machinery
to implement a simple drawing program:

Simple Draw executable.

The source code of this sample program is available in the samples directory. By playing with
and modifying this, you can see how to build your own applications on top of The Machinery.

Note that just as when writing plugins, you need a Visual Studio installation (2019) to build an
executable. You need to set TM_SDK_DIR to the location of The Machinery SDK you are using, and
you
use tmbuild.exe to build the executable.

bin/simple-3d.exe is a sample executable that uses the full 3D API.


Simple 3D executable.

You will find the source code for this too in the samples directory.

Thank you again!


formatted by Markdeep 1.13  

You might also like