C++ Scripting
In this chapter you'll learn how to get started with C++ Scripting using Jenova Framework in Godot.
Script Anatomy
A Jenova C++ Script consists of several parts. This is the most basic C++ Script in Jenova Framework:
/* ------ Script Imports ------ */
// Godot SDK
#include <Godot/godot.hpp>
// Jenova SDK
#include <JenovaSDK.h>
// Namespaces
using namespace godot;
using namespace jenova::sdk;
/* ------ Script Features ------ */
// Set Class Name
JENOVA_CLASS_NAME("Jenova C++ Script")
/* ------- Script Block ------- */
// Script Block Begin
JENOVA_SCRIPT_BEGIN
/* Write C++ Script Here */
// Script Block End
JENOVA_SCRIPT_END
Script Imports
To start working with the engine, you need to import the required types from GodotSDK and JenovaSDK. While JenovaSDK is optional, it is recommended because of its helpful types and functions. After importing, include the relevant namespaces to simplify coding and avoid namespace prefixes for each type or function.
Script Features
Jenova provides features you can use in your script :
JENOVA_CLASS_NAME(<string>)
: Assigns a unique name to your C++ Script, displayed in the Inspector.JENOVA_TOOL_SCRIPT
: Executes the C++ Script within the editor. See Tool Scripts for more details.JENOVA_PROPERTY(<type>, <name>, <value>, ...)
: Exposes properties from your script to the Inspector. This is particularly useful when working with scene data, allowing you to customize values without modifying the script. See Properties for more information.JENOVA_GODOT_SDK
: Includes the entire GodotSDK headers in your script. This option is not recommended as it significantly slows down script compilation.
Script Block
Jenova C++ Scripts require that you write code within a Script Block, defined using these macros :
- Script Block Begin Macro (
JENOVA_SCRIPT_BEGIN
) - Script Block End Macro (
JENOVA_SCRIPT_END
)
Functions and properties within the Script Block are parsed and serialized into Metadata by the Jenova Symbol Parser making them accessible to the game engine.
You can place any function and value outside of the Script Block. The only difference is that they won't be serialized but can still be used anywhere in the code, Including inside the Script Block. It's recommended to place utility and helper functions outside of the Script Block.
Functions inside a Script Block are called "Script Callbacks", They are equivalent to GDScript Signals. Depending on the type of Node the script is assigned to, You can define signals that will be called by the Interpreter. Some common callbacks available for all Nodes include :
- OnReady : Translates to
_ready
- OnAwake : Translates to
_enter_tree
- OnDestroy : Translates to
_exit_tree
- OnProcess : Translates to
_process
- OnPhysicsProcess : Translates to
_physics_process
- OnInput : Translates to
_input
Additionally, you can use any other function exposed by a Node based on its type.
Control
or CanvasItem
you can define:void _gui_input(const InputEvent* p_event)
{
/* Handle Input Events */
}
Keep in mind that you are not forced to use the simplified function names and You're allowed to use the original name.
_ready
instead of OnReady
or use _enter_tree
instead of OnAwake
It's up to you!- All functions defined within the Script Block must use parameter types compatible with
godot::Variant
- On Linux do not use typedefs as function return types. Use Godot-compatible types directly.
Tool Scripts
C++ Scripts can execute within the Godot Editor by including JENOVA_TOOL_SCRIPT
in the script code. This is similar to @tool
in GDScript.
Tool Scripts are useful for implementing tools and utilities in the Godot Editor.
// Godot SDK
#include <Godot/godot.hpp>
// Jenova SDK
#include <JenovaSDK.h>
// Namespaces
using namespace godot;
using namespace jenova::sdk;
// Enable Execution in Editor
JENOVA_TOOL_SCRIPT
// Script Block Begin
JENOVA_SCRIPT_BEGIN
// Callbacks
void OnProcess(double delta)
{
Output("Editor Tool Script Executed with Delta: %lf", delta);
}
// Script Block End
JENOVA_SCRIPT_END
After compiling the above script, you will see messages printed in the Output window.
Due to the mechanism of Godot's scripting backend, You must close and reopen your scene to see the effects of Tool Scripts.
Macros
The Jenova Compiler Interface defines some macros for every C++ Script source that can be useful :
-
JENOVA_VERSION
: Represents the version of the Jenova Runtime as aX.X.X.X
string for feature control.#define JENOVA_VERSION "0.3.6.5"
-
JENOVA_COMPILER
: Indicates the compiler name used to compile scripts as a string.#define JENOVA_COMPILER "Microsoft Visual C++ Compiler"
-
XXXX_COMPILER
: Unique to each compiler, This macro allows cross-compiler code control to define features specific to each compiler.#define MSVC_COMPILER
#define MINGW_COMPILER
#define GCC_COMPILER
#define CLANG_COMPILER -
TOOL_SCRIPT
: When usingJENOVA_TOOL_SCRIPT
option inside your script, You can determine and define which part of code must be run inside editor as tool.Jenova C++ Scriptvoid OnReady()
{
#ifdef TOOL_SCRIPT
jenova::sdk::Output("Hello from C++ Tool Script!");
#else
jenova::sdk::Output("Hello from C++ Script!");
#endif // TOOL_SCRIPT
}
-
JENOVA_CALLBACK
: Enables inline handling of signals, making tasks like updating UI elements after animations more efficient. [ Advanced ] -
JENOVA_EXPORT
: Allows exporting a function from the Jenova Module for use in third-party modules and libraries. [ Advanced ]
You can also define custom definitions at Editor Settings > Jenova > Preprocessor Definitions
;
)Example : WIN64_JENOVA;Author "Hamid.Memar";FUNC_ADD(x,y) x+y
📖 Learn more about Jenova Editor Settings
NitroJIT vs Meteora
When using different Interpreter Backends it's crucial to understand their differences to prevent conflicts and crashes.
- NitroJIT
- Meteora
Below is a minimal example to demonstrate the differences between these two backends.
void _process(Caller* instance, Variant& delta)
{
Output("Delta : %lf", double(delta));
}
Variant _get_configuration_warnings()
{
PackedStringArray warnings;
warnings.push_back("Some Configuration Warning");
return warnings;
}
void _process(Caller* instance, double delta)
{
Output("Delta : %lf", delta);
}
PackedStringArray _get_configuration_warnings()
{
PackedStringArray warnings;
warnings.push_back("Some Configuration Warning");
return warnings;
}