Skip to content

Commit

Permalink
README is quite outdated (#55)
Browse files Browse the repository at this point in the history
Closes #49
  • Loading branch information
TitanNano authored Aug 23, 2024
1 parent 45ab022 commit c7ced77
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 57 deletions.
109 changes: 54 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,105 +1,96 @@
# Godot Rust Script
An implementation of the rust programing language as a scripting language for the godot engine based on [godot-rust/gdext](https://github.com/godot-rust/gdext).
An implementation of the rust programing language as a scripting language for the godot 4.x engine based on [godot-rust/gdext](https://github.com/godot-rust/gdext).

# Important Notice

**godot-rust-script is still very experimental and unstable.**
**godot-rust-script is still experimental and undergoes breaking changes from time to time.**

This project also currently depends on a slightly modfied fork of [godot-rust/gdext](https://github.com/godot-rust/gdext) and should not be used in combination with any other version.
# Why?

# Featues
- use rust as scripts similar to GDScript or CSharp
- hot reload your rust scripts in development mode
- use familiar godot annotations similar to GDScripts annotations for editor integration
The question of why this project exists might arise, and it's a good question. The [godot-rust/gdext](https://github.com/godot-rust/gdext)
project already implements excellent bindings with the engine and provides a good developer experience. If you are just looking to write code
for your Godot project in rust, you most likely are already well served with gdext and definitely do not **need** this library.

# Setup
## When would you want to use `godot-rust-script`?

godot-rust-script comes with two compontents. A script runtime and a library for writing godot script compatible rust structs. Both these components have to be set up.
GDExtension works by allowing dynamic libraries to define their own Godot classes, which inherit directly from an existing class. These
classes inherit all the functionality of their base classes. Nothing more, nothing less. Scripts, on the other hand, offer a bit more
flexibility. While they also define a base class, this is more like a minimally required interface. Scripts are attached to an instance of
an existing class. As long as the instance inherits the required base class, the script is compatible with it. This makes the scripts somewhat
more flexible and provides more compossibility than using plain class-based inheritance. It is up to you to decide if you need this
additional flexibility.

Two sepearte crates are required to make rust scripts work.
# Setup

## Runtime library
To use `godot-rust-script` first follow the basic setup instructions for `gdext`.

rs-runtime/Cargo.toml
## Add Dependency

```toml
[package]
name = "rs-runtime"
version = "0.1.0"
edition = "2021"
The project has to be added as a cargo dependency. At the moment, it is not available on crates.io since it is still under heavy development.
This library currently re-exports the `godot` crate, but adding the `godot` dependency as well is recommended, as this most likely will change in the future.

```toml
[lib]
crate-type = ["cdylib"]

[dependencies]
godot-rust-script = { git = "https://github.com/TitanNano/godot-rust-script.git", branch = "master", features = ["runtime"] }
scripts = { path = "./scripts" }
godot-rust-script = { git = "https://github.com/TitanNano/godot-rust-script.git", branch = "master" }
```

rs-runtime/src/main.rs

```rs
use std::cell::RefCell;
## Bootstrap Script Runtime

use godot::prelude::{gdextension, ExtensionLibrary, InitLevel};
use godot_rust_script::{self, RustScriptExtensionLayer};
The script runtime has to be registered with the engine, as Godot does not know how scripts written in rust should be executed or even that
it's available as a scripting language.

godot_rust_script::setup!(scripts);
For this, a manual implementation of the `godot::init::ExtensionLibrary` trait is required. Initializing and deinitalizing the runtime can then
be achieved via two macro calls. The `init!(...)` macro requires the name / path to a module in your library, which represents the root module
of all available scripts.

struct NativeLib;

thread_local! {
static RUST_SCRIPT_LAYER: RefCell<RustScriptExtensionLayer> = RefCell::new(godot_rust_script::init!());
}
```rs
struct Lib;

#[gdextension]
unsafe impl ExtensionLibrary for NativeLib {
unsafe impl ExtensionLibrary for Lib {
fn on_level_init(level: InitLevel) {
match level {
InitLevel::Core => (),
InitLevel::Servers => (),
InitLevel::Scene => RUST_SCRIPT_LAYER.with_borrow_mut(|layer| layer.initialize()),
InitLevel::Scene => godot_rust_script::init!(scripts),
InitLevel::Editor => (),
}
}

fn on_level_deinit(level: InitLevel) {
match level {
InitLevel::Editor => (),
InitLevel::Scene => RUST_SCRIPT_LAYER.with_borrow_mut(|layer| layer.deinitialize()),
InitLevel::Servers => {}
InitLevel::Scene => godot_rust_script::deinit!(),
InitLevel::Servers => (),
InitLevel::Core => (),
}
}
}
```

## Scripts Library

scripts-lib/Cargo.toml
## Define Scripts Root

```toml
[package]
name = "scripts"
version = "0.1.0"
edition = "2021"
Rust scripts require a root module. All rust modules under this module will be considered as potential scripts.

[lib]
crate-type = ["dylib", "rlib"]
```rs
mod example_script;

[dependencies]
godot-rust-script = { git = "https://github.com/TitanNano/godot-rust-script.git", branch = "master", features = ["scripts"] }
godot_rust_script::define_script_root!();
```

scripts-lib/src/lib.rs
## Write the first Script

```rs
mod example_script;
Godots script system is file-based, which means each of your rust scripts has to go into its own module file. Rust script then uses the name
of your module file (e.g., `player_controller.rs`) to identify the script class / struct inside of it (e.g., `PlayerController`).

godot_rust_script::setup_library!();
```
Currently, all scripts are defined as global classes in the engine. This means each script must have a unique name.

scripts-lib/src/example_script.rs
Scripts are then composed of a `struct` definition and an `impl` block. Public functions inside the impl block will be made available to
other scripting languages and the engine, so they must use Godot compatible types. The same applies to struct fields.
Struct fields can additionally be exported via the `#[export]` attribute, so they show up in the editor inspector.

```rs
use godot_rust_script::{
Expand All @@ -109,9 +100,8 @@ use godot_rust_script::{

#[derive(Debug, GodotScript)]
struct ExampleScript {
#[export(exp_easing = ["positive_only"])]
#[export]
pub flag: bool,
//#[export(dir_path, color_no_alpha, global_dir, global_file, multiline)]
pub path: GodotString,
property: Option<Gd<Object>>,
base: Gd<Node3D>,
Expand All @@ -132,3 +122,12 @@ impl ExampleScript {
}
}
```

# FAQ

## Can I write / edit scripts in the godot editor?
No, it's currently neither supported nor planned. There are numerous good Rust editors and IDEs, so supporting the language inside
the Godot code editor is not a goal of this project.

## Can I compile my scripts from inside the godot editor?
This is currently not supported.
10 changes: 9 additions & 1 deletion rust-script/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ impl<T: GodotScript, B: Inherits<T::Base> + Inherits<Object>> CastToScript<T> fo
}

#[macro_export]
macro_rules! setup_library {
macro_rules! define_script_root {
() => {
#[no_mangle]
pub fn __godot_rust_script_init(
Expand Down Expand Up @@ -202,6 +202,14 @@ macro_rules! setup_library {
};
}

#[deprecated = "Has been renamed to define_script_root!()"]
#[macro_export]
macro_rules! setup_library {
() => {
::godot_rust_script::define_script_root!();
};
}

pub trait GodotScriptEnum: GodotConvert + FromGodot + ToGodot {}

#[macro_export]
Expand Down
2 changes: 1 addition & 1 deletion tests-scripts-lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

godot_rust_script::setup_library!();
godot_rust_script::define_script_root!();

0 comments on commit c7ced77

Please sign in to comment.