copy lua book chapters as starting point for ruby book
Some checks failed
Rust / build (pull_request) Has been cancelled
Some checks failed
Rust / build (pull_request) Has been cancelled
This commit is contained in:
parent
679cfd8140
commit
35dc89322e
9 changed files with 484 additions and 0 deletions
87
book/src/ruby/builtin_types.md
Normal file
87
book/src/ruby/builtin_types.md
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
# Builtin types
|
||||||
|
|
||||||
|
bevy_scriptum provides following types that can be used in Lua:
|
||||||
|
|
||||||
|
- ```Vec3```
|
||||||
|
- ```BevyEntity```
|
||||||
|
|
||||||
|
## Vec3
|
||||||
|
|
||||||
|
### Constructor
|
||||||
|
|
||||||
|
`Vec3(x: number, y: number, z: number)`
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
|
||||||
|
- `x: number`
|
||||||
|
- `y: number`
|
||||||
|
- `z: number`
|
||||||
|
|
||||||
|
|
||||||
|
### Example Lua usage
|
||||||
|
|
||||||
|
```
|
||||||
|
my_vec = Vec3(1, 2, 3)
|
||||||
|
set_translation(entity, my_vec)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Rust usage
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_scripting::<LuaRuntime>(|runtime| {
|
||||||
|
runtime.add_function(String::from("set_translation"), set_translation);
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_translation(
|
||||||
|
In((entity, translation)): In<(BevyEntity, BevyVec3)>,
|
||||||
|
mut entities: Query<&mut Transform>,
|
||||||
|
) {
|
||||||
|
let mut transform = entities.get_mut(entity.0).unwrap();
|
||||||
|
transform.translation = translation.0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## BevyEntity
|
||||||
|
|
||||||
|
### Constructor
|
||||||
|
|
||||||
|
None - instances can only be acquired by using built-in `entity` global variable.
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
|
||||||
|
- `index: integer`
|
||||||
|
|
||||||
|
### Example Lua usage
|
||||||
|
|
||||||
|
```lua
|
||||||
|
print(entity.index)
|
||||||
|
pass_to_rust(entity)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Rust usage
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_scripting::<LuaRuntime>(|runtime| {
|
||||||
|
runtime.add_function(String::from("pass_to_rust"), |In((entity,)): In<(BevyEntity,)>| {
|
||||||
|
println!("pass_to_rust called with entity: {:?}", entity);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
```
|
||||||
13
book/src/ruby/builtin_variables.md
Normal file
13
book/src/ruby/builtin_variables.md
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Builtin variables
|
||||||
|
|
||||||
|
## entity
|
||||||
|
|
||||||
|
A variable called `entity` is automatically available to all scripts - it represents bevy entity that the `Script` component is attached to.
|
||||||
|
It exposes `index` property that returns bevy entity index.
|
||||||
|
It is useful for accessing entity's components from scripts.
|
||||||
|
It can be used in the following way:
|
||||||
|
```lua
|
||||||
|
print("Current entity index: " .. entity.index)
|
||||||
|
```
|
||||||
|
|
||||||
|
`entity` variable is currently not available within promise callbacks.
|
||||||
121
book/src/ruby/calling_rust_from_script.md
Normal file
121
book/src/ruby/calling_rust_from_script.md
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
# Calling Rust from Lua
|
||||||
|
|
||||||
|
To call a rust function from Lua first you need to register a function
|
||||||
|
within Rust using builder pattern.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_scripting::<LuaRuntime>(|runtime| {
|
||||||
|
// `runtime` is a builder that you can use to register functions
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For example to register a function called `my_rust_func` you can do the following:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_scripting::<LuaRuntime>(|runtime| {
|
||||||
|
runtime.add_function(String::from("my_rust_func"), || {
|
||||||
|
println!("my_rust_func has been called");
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After you do that the function will be available to Lua code in your spawned scripts.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
my_rust_func()
|
||||||
|
```
|
||||||
|
|
||||||
|
Registered functions can also take parameters. A parameter can be any type
|
||||||
|
that implements `FromLua`.
|
||||||
|
|
||||||
|
Since a registered callback function is a Bevy system, the parameters are passed
|
||||||
|
to it as `In` struct with tuple, which has to be the first parameter of the closure.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_scripting::<LuaRuntime>(|runtime| {
|
||||||
|
runtime.add_function(String::from("func_with_params"), |args: In<(String, i64)>| {
|
||||||
|
println!("my_rust_func has been called with string {} and i64 {}", args.0.0, args.0.1);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To make it look nicer you can destructure the `In` struct.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_scripting::<LuaRuntime>(|runtime| {
|
||||||
|
runtime.add_function(String::from("func_with_params"), |In((a, b)): In<(String, i64)>| {
|
||||||
|
println!("my_rust_func has been called with string {} and i64 {}", a, b);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The above function can be called from Lua
|
||||||
|
|
||||||
|
```lua
|
||||||
|
func_with_params("abc", 123)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Return value via promise
|
||||||
|
|
||||||
|
Any registered rust function that returns a value will retrurn a promise when
|
||||||
|
called within a script. By calling `:and_then` on the promise you can register
|
||||||
|
a callback that will receive the value returned from Rust function.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_scripting::<LuaRuntime>(|runtime| {
|
||||||
|
runtime.add_function(String::from("returns_value"), || {
|
||||||
|
123
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```lua
|
||||||
|
returns_value():and_then(function (value)
|
||||||
|
print(value) -- 123
|
||||||
|
end)
|
||||||
|
```
|
||||||
67
book/src/ruby/calling_script_from_rust.md
Normal file
67
book/src/ruby/calling_script_from_rust.md
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
# Calling Lua from Rust
|
||||||
|
|
||||||
|
To call a function defined in Lua
|
||||||
|
|
||||||
|
```lua
|
||||||
|
function on_update()
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
We need to acquire `LuaRuntime` resource within a bevy system.
|
||||||
|
Then we will be able to call `call_fn` on it, providing the name
|
||||||
|
of the function to call, `LuaScriptData` that has been automatically
|
||||||
|
attached to entity after an entity with script attached has been spawned
|
||||||
|
and its script evaluated, the entity and optionally some arguments.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn call_lua_on_update_from_rust(
|
||||||
|
mut scripted_entities: Query<(Entity, &mut LuaScriptData)>,
|
||||||
|
scripting_runtime: ResMut<LuaRuntime>,
|
||||||
|
) {
|
||||||
|
for (entity, mut script_data) in &mut scripted_entities {
|
||||||
|
// calling function named `on_update` defined in lua script
|
||||||
|
scripting_runtime
|
||||||
|
.call_fn("on_update", &mut script_data, entity, ())
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
```
|
||||||
|
|
||||||
|
We can also pass some arguments by providing a tuple or `Vec` as the last
|
||||||
|
`call_fn` argument.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn call_lua_on_update_from_rust(
|
||||||
|
mut scripted_entities: Query<(Entity, &mut LuaScriptData)>,
|
||||||
|
scripting_runtime: ResMut<LuaRuntime>,
|
||||||
|
) {
|
||||||
|
for (entity, mut script_data) in &mut scripted_entities {
|
||||||
|
scripting_runtime
|
||||||
|
.call_fn("on_update", &mut script_data, entity, (123, String::from("hello")))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
```
|
||||||
|
|
||||||
|
They will be passed to `on_update` Lua function
|
||||||
|
```lua
|
||||||
|
function on_update(a, b)
|
||||||
|
print(a) -- 123
|
||||||
|
print(b) -- hello
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Any type that implements `IntoLua` can be passed as an argument withing the
|
||||||
|
tuple in `call_fn`.
|
||||||
66
book/src/ruby/hello_world.md
Normal file
66
book/src/ruby/hello_world.md
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
# Hello World
|
||||||
|
|
||||||
|
After you are done installing the required crates, you can start developing
|
||||||
|
your first game or application using bevy_scriptum.
|
||||||
|
|
||||||
|
To start using the library you need to first import some structs and traits
|
||||||
|
with Rust `use` statements.
|
||||||
|
|
||||||
|
For convenience there is a main "prelude" module provided called
|
||||||
|
`bevy_scriptum::prelude` and a prelude for each runtime you have enabled as
|
||||||
|
a create feature.
|
||||||
|
|
||||||
|
You can now start exposing functions to the scripting language. For example, you can expose a function that prints a message to the console:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_scripting::<LuaRuntime>(|runtime| {
|
||||||
|
runtime.add_function(
|
||||||
|
String::from("my_print"),
|
||||||
|
|In((x,)): In<(String,)>| {
|
||||||
|
println!("my_print: '{}'", x);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you can create a script file in `assets` directory called `script.lua` that calls this function:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
my_print("Hello world!")
|
||||||
|
```
|
||||||
|
|
||||||
|
And spawn an entity with attached `Script` component with a handle to a script source file:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_scripting::<LuaRuntime>(|runtime| {
|
||||||
|
runtime.add_function(
|
||||||
|
String::from("my_print"),
|
||||||
|
|In((x,)): In<(String,)>| {
|
||||||
|
println!("my_print: '{}'", x);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.add_systems(Startup,|mut commands: Commands, asset_server: Res<AssetServer>| {
|
||||||
|
commands.spawn(Script::<LuaScript>::new(asset_server.load("script.lua")));
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You should then see `my_print: 'Hello world!'` printed in your console.
|
||||||
12
book/src/ruby/installation.md
Normal file
12
book/src/ruby/installation.md
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
Add the following to your `Cargo.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[dependencies]
|
||||||
|
bevy = "0.16"
|
||||||
|
bevy_scriptum = { version = "0.8", features = ["lua"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need a different version of bevy you need to use a matching bevy_scriptum
|
||||||
|
version according to the [bevy support matrix](../bevy_support_matrix.md)
|
||||||
75
book/src/ruby/interacting_with_bevy.md
Normal file
75
book/src/ruby/interacting_with_bevy.md
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Interacting with bevy in callbacks
|
||||||
|
|
||||||
|
Every registered function is also just a regular Bevy system.
|
||||||
|
|
||||||
|
That allows you to do anything you would do in a Bevy system.
|
||||||
|
|
||||||
|
You could for example create a callback system function that prints names
|
||||||
|
of all entities with `Player` component.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct Player;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_scripting::<LuaRuntime>(|runtime| {
|
||||||
|
runtime.add_function(
|
||||||
|
String::from("print_player_names"),
|
||||||
|
|players: Query<&Name, With<Player>>| {
|
||||||
|
for player in &players {
|
||||||
|
println!("player name: {}", player);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In script:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
print_player_names()
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use functions that interact with Bevy entities and resources and
|
||||||
|
take arguments at the same time. It could be used for example to mutate a
|
||||||
|
component.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct Player {
|
||||||
|
health: i32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_scripting::<LuaRuntime>(|runtime| {
|
||||||
|
runtime.add_function(
|
||||||
|
String::from("hurt_player"),
|
||||||
|
|In((hit_value,)): In<(i32,)>, mut players: Query<&mut Player>| {
|
||||||
|
let mut player = players.single_mut();
|
||||||
|
player.health -= hit_value;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And it could be called in script like:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
hurt_player(5)
|
||||||
|
```
|
||||||
3
book/src/ruby/lua.md
Normal file
3
book/src/ruby/lua.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Lua
|
||||||
|
|
||||||
|
This chapter demonstrates how to work with bevy_scriptum when using Lua language runtime.
|
||||||
40
book/src/ruby/spawning_scripts.md
Normal file
40
book/src/ruby/spawning_scripts.md
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
# Spawning scripts
|
||||||
|
|
||||||
|
To spawn a Lua script you will need to get a handle to a script asset using
|
||||||
|
bevy's `AssetServer`.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn my_spawner(mut commands: Commands, assets_server: Res<AssetServer>) {
|
||||||
|
commands.spawn(Script::<LuaScript>::new(
|
||||||
|
assets_server.load("my_script.lua"),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
```
|
||||||
|
|
||||||
|
After they scripts have been evaled by bevy_scriptum, the entities that they've
|
||||||
|
been attached to will get the `Script::<LuaScript>` component stripped and instead
|
||||||
|
```LuaScriptData``` component will be attached.
|
||||||
|
|
||||||
|
So to query scipted entities you could do something like:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_scriptum::prelude::*;
|
||||||
|
use bevy_scriptum::runtimes::lua::prelude::*;
|
||||||
|
|
||||||
|
fn my_system(
|
||||||
|
mut scripted_entities: Query<(Entity, &mut LuaScriptData)>,
|
||||||
|
) {
|
||||||
|
for (entity, mut script_data) in &mut scripted_entities {
|
||||||
|
// do something with scripted entities
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
```
|
||||||
Loading…
Reference in a new issue