Skip to content

Commit

Permalink
Merge pull request #166 from yarn-slinger/book
Browse files Browse the repository at this point in the history
Write more docs
  • Loading branch information
janhohenheim authored Jan 23, 2024
2 parents 10765d2 + 6add217 commit 6d25427
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 10 deletions.
2 changes: 1 addition & 1 deletion crates/bevy_plugin/src/commands/command_wrapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) fn command_wrapping_plugin(_app: &mut App) {}
/// The signature of the method must adhere to the following rules:
/// - The first parameter must be of the type `In<T>`, where `T` can be converted into a [`YarnFnParam`]. This stands for the parameters passed to the command from Yarn.
/// Multiple parameters are supported as values wrapped in a tuple.
/// For example, to register a command that is called from yarn like `<<add_player "John" 42>>`, the first parameter must be of the type `In<(String, i32)>` and a call to `register_command` might look like this:
/// For example, to register a command that is called from Yarn like `<<add_player "John" 42>>`, the first parameter must be of the type `In<(String, i32)>` and a call to `register_command` might look like this:
/// ```rust
/// # use bevy_yarn_slinger::prelude::*;
/// # use bevy::prelude::*;
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_plugin/src/project/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ fn recompile_loaded_yarn_files(
}
}
events.clear();
info!("Successfully recompiled yarn project because of changes in Yarn files.");
info!("Successfully recompiled Yarn project because of changes in Yarn files.");
Ok(())
}

Expand Down Expand Up @@ -235,7 +235,7 @@ fn compile_loaded_yarn_files(
});

let file_plural = if file_count == 1 { "file" } else { "files" };
info!("Successfully compiled {file_count} yarn {file_plural}");
info!("Successfully compiled {file_count} Yarn {file_plural}");

*dirty = false;
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/types/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::any::TypeId;
use std::fmt::{Debug, Display};
use thiserror::Error;

/// All types in the virtual machine, both built-in, i.e. usable in yarn scripts, and internal.
/// All types in the virtual machine, both built-in, i.e. usable in Yarn scripts, and internal.
///
/// Whenever this appears in an `Option` with the `None` type,
/// treat it as an undefined type.
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/yarn_fn/function_wrapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use yarn_slinger_macros::all_tuples;
/// - It is allowed to have zero or more parameters
/// - Each parameter must be a [`YarnFnParam`], which means of the following types or a reference to them:
/// - [`bool`]
/// - A numeric types, i.e. one of [`f32`], [`f64`], [`i8`], [`i16`], [`i32`], [`i64`], [`i128`], [`u8`], [`u16`], [`u32`], [`u64`], [`u128`], [`usize`], [`isize`]
/// - A numeric type, i.e. one of [`f32`], [`f64`], [`i8`], [`i16`], [`i32`], [`i64`], [`i128`], [`u8`], [`u16`], [`u32`], [`u64`], [`u128`], [`usize`], [`isize`]
/// - [`String`] (for a reference, [`&str`] may be used instead of `&String`)
/// - [`YarnValue`], which means that a parameter may be any of the above types
/// - Tuples of the above types.
Expand Down
22 changes: 20 additions & 2 deletions docs/src/bevy_plugin/assets.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ title: Start
---
Granny: It's hard to believe that it's over, isn't it? #smiling
Granny: Funny how we get attached to the struggle. #laughing
Granny: Promise me tat you'll take care of yourself, okay? #smiling
Granny: Promise me that you'll take care of yourself, okay? #smiling
===
```

Expand All @@ -22,5 +22,23 @@ These annotations will also be written into the "comment" field of strings files

## Asset Providers

TODO (Feel free to [contribute](https://github.com/yarn-slinger/yarn-slinger/edit/main/docs/src/bevy_plugin/assets.md)!)
Assets are fetched from the filesystem by structs implementing `AssetProvider`. They need to be registered when creating a `DialogRunner`.
For example, if you use the `audio_assets` feature, you can register an asset provider for audio files by modifying the code found in the [setup](./setup.md) like this:

```rust
fn spawn_dialogue_runner(mut commands: Commands, project: Res<YarnProject>) {
let mut dialogue_runner = project
.build_dialogue_runner()
.add_asset_provider(AudioAssetProvider::new())
.build();
dialogue_runner.start_node("Start");
commands.spawn(dialogue_runner);
}

```

TODO: Code does not work
TODO: Mention default dialog view does not support this
TODO: Where stuff is searched
TODO: FileExtensionAssetProvider
TODO: Own AssetProvider?
63 changes: 62 additions & 1 deletion docs/src/bevy_plugin/custom_commands.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,64 @@
# Custom Commands

TODO (Feel free to [contribute](https://github.com/yarn-slinger/yarn-slinger/edit/main/docs/src/bevy_plugin/custom_commands.md)!)
[Commands](../yarn_files/commands.md) work very similar to Yarn [functions](../yarn_files/functions.md), but
use a different syntax and are able to modify the game world. As a consequence of their similarity,
registering custom commands is very similar to registering [custom functions](./custom_functions.md).

## Command Registration

Just as with Yarn functions, registration happens when creating a `DialogRunner`.
Let's again modify the example from the [setup](./setup.md):

```rust
fn spawn_dialogue_runner(mut commands: Commands, project: Res<YarnProject>) {
let mut dialogue_runner = project.create_dialogue_runner();
// Add our custom command to the dialogue runner
dialogue_runner
.commands_mut()
.add_command("print_addition", print_addition);
dialogue_runner.start_node("Start");
commands.spawn(dialogue_runner);
}

fn print_addition(In((a, b)): In<(f32, f32)>) {
print!("{a} + {b} = {c}", c = a + b)
}
```

We call the command like this:

```text
title: Start
---
Let's print the addition of 1 and 3 in the console:
<<print_addition(1, 3)>>
===
```

You will have seen one crucial difference to Yarn functions immediately.
The parameters are not passed in directly to the Rust function, but are wrapped in an `In` struct.
This is because Rust functions that are registered as commands are always valid Bevy systems.
The `In` parameter just tells the function which values come from the Yarn file, but we can additionally query the Bevy world as we want:

```rust
fn spawn_dialogue_runner(mut commands: Commands, project: Res<YarnProject>) {
let mut dialogue_runner = project.create_dialogue_runner();
// Add our custom command to the dialogue runner
dialogue_runner
.commands_mut()
.add_command("insert_resource", insert_resource);
dialogue_runner.start_node("Start");
commands.spawn(dialogue_runner);
}

TODO
fn insert_resource(In(name): In<&str>) {
print!("{a} + {b} = {c}", c = a + b)
}
```

TODO

TODO mention return types

TODO mention that no params still needs In param
Binary file added docs/src/bevy_plugin/custom_fn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
92 changes: 91 additions & 1 deletion docs/src/bevy_plugin/custom_functions.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,93 @@
# Custom Functions

TODO (Feel free to [contribute](https://github.com/yarn-slinger/yarn-slinger/edit/main/docs/src/bevy_plugin/custom_functions.md)!)
As mentioned in the chapter [Functions](../yarn_files/functions.md), Yarn can access user-defined functions.
A collection of functions is called a *library* and can be accessed through a `DialogRunner`.

## Function Registration

For an easy example, let's modify the code used in the [setup](./setup.md) to provide a simple `pow` function to Yarn:
```rust
fn spawn_dialogue_runner(mut commands: Commands, project: Res<YarnProject>) {
let mut dialogue_runner = project.create_dialogue_runner();
// Add our custom function to the dialogue runner
dialogue_runner.library_mut().add_function("pow", pow);
dialogue_runner.start_node("Start");
commands.spawn(dialogue_runner);
}

fn pow(base: f32, exponent: f32) -> f32 {
base.powf(exponent)
}
```

The following snippet is of special importance:
```rust
dialogue_runner.library_mut().add_function("pow", pow);
```
The first parameter of `add_function()` is the name of the function as seen by Yarn, `"pow"` in this case.
The second parameter is the Rust function that will be called in the background.
Here, we reference the function definition of `fn pow(...)`, but you could also register a lambda.


This `pow` function can now be called from the Yarn file like this:

```text
title: Start
---
Two to the power of three is {pow(2,3)}
===
```

Which will result in the following output:
![custom_fn.png](custom_fn.png)

## Allowed Signatures

Custom functions need to follow some rules. Don't worry, they're pretty lax.

- Their parameter and output types need to be primitive types or `String`
- Parameters are allowed to be references
- Parameters can have the special type `YarnValue`, which stands for any input type.
Additionally, functions are assumed to have no side effects. You can read the full list of requirements in the docs for `YarnFn`.

Here are some examples of valid functions:
```rust
fn add(a: f32, b: f32) -> f32 {
a + b
}

fn concat(a: &str, b: &str) -> String {
format!("{a}{b}")
}

fn greet(name: &str, age: usize) -> String {
format!("Hello {name}, you are {age} years old!")
}

fn format_anything(value: YarnValue) -> String {
format!("Got the following value: {value}")
}
```

If you need functions that have side effects, e.g. for manipulating the game world, use [custom commands](./custom_commands.md) instead.

## Size constraints

Registered Rust functions can have a maximum of 16 parameters.
If you need more, you can wrap parameters in tuples:

```rust
fn add((a, b): (f32, f32)) -> f32 {
a + b
}
```

Tuples are treated as separate parameters when calling the function from Yarn:
```text
title: Start
---
Two plus three is {add(2, 3)}
===
```

Since tuples can be nested, you can use have potentially infinite parameters.
2 changes: 1 addition & 1 deletion examples/bevy_yarn_slinger/src/bin/custom_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct SomethingAddedByYarnSlinger {
}

// Commands are valid Bevy systems with inputs (and optional outputs).
// The `In` param will determine the yarn signature. This function can thus be called like
// The `In` param will determine the Yarn signature. This function can thus be called like
// `<<insert_resource "Bob" 42>>` in Yarn.
fn insert_resource(In((name, age)): In<(&str, f32)>, mut commands: Commands) {
commands.insert_resource(SomethingAddedByYarnSlinger {
Expand Down

0 comments on commit 6d25427

Please sign in to comment.