bevy/crates/bevy_internal/Cargo.toml
Gino Valente df61117850
bevy_reflect: Function registry (#14098)
# Objective

#13152 added support for reflecting functions. Now, we need a way to
register those functions such that they may be accessed anywhere within
the ECS.

## Solution

Added a `FunctionRegistry` type similar to `TypeRegistry`.

This allows a function to be registered and retrieved by name.

```rust
fn foo() -> i32 {
    123
}

let mut registry = FunctionRegistry::default();
registry.register("my_function", foo);

let function = registry.get_mut("my_function").unwrap();
let value = function.call(ArgList::new()).unwrap().unwrap_owned();
assert_eq!(value.downcast_ref::<i32>(), Some(&123));
```

Additionally, I added an `AppFunctionRegistry` resource which wraps a
`FunctionRegistryArc`. Functions can be registered into this resource
using `App::register_function` or by getting a mutable reference to the
resource itself.

### Limitations

#### `Send + Sync`

In order to get this registry to work across threads, it needs to be
`Send + Sync`. This means that `DynamicFunction` needs to be `Send +
Sync`, which means that its internal function also needs to be `Send +
Sync`.

In most cases, this won't be an issue because standard Rust functions
(the type most likely to be registered) are always `Send + Sync`.
Additionally, closures tend to be `Send + Sync` as well, granted they
don't capture any `!Send` or `!Sync` variables.

This PR adds this `Send + Sync` requirement, but as mentioned above, it
hopefully shouldn't be too big of an issue.

#### Closures

Unfortunately, closures can't be registered yet. This will likely be
explored and added in a followup PR.

### Future Work

Besides addressing the limitations listed above, another thing we could
look into is improving the lookup of registered functions. One aspect is
in the performance of hashing strings. The other is in the developer
experience of having to call `std::any::type_name_of_val` to get the
name of their function (assuming they didn't give it a custom name).

## Testing

You can run the tests locally with:

```
cargo test --package bevy_reflect
```

---

## Changelog

- Added `FunctionRegistry`
- Added `AppFunctionRegistry` (a `Resource` available from `bevy_ecs`)
- Added `FunctionRegistryArc`
- Added `FunctionRegistrationError`
- Added `reflect_functions` feature to `bevy_ecs` and `bevy_app`
- `FunctionInfo` is no longer `Default`
- `DynamicFunction` now requires its wrapped function be `Send + Sync`

## Internal Migration Guide

> [!important]
> Function reflection was introduced as part of the 0.15 dev cycle. This
migration guide was written for developers relying on `main` during this
cycle, and is not a breaking change coming from 0.14.

`DynamicFunction` (both those created manually and those created with
`IntoFunction`), now require `Send + Sync`. All standard Rust functions
should meet that requirement. Closures, on the other hand, may not if
they capture any `!Send` or `!Sync` variables from its environment.
2024-08-06 01:09:48 +00:00

254 lines
8.9 KiB
TOML

[package]
name = "bevy_internal"
version = "0.15.0-dev"
edition = "2021"
description = "An internal Bevy crate used to facilitate optional dynamic linking via the 'dynamic_linking' feature"
homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy"
license = "MIT OR Apache-2.0"
keywords = ["game", "engine", "gamedev", "graphics", "bevy"]
categories = ["game-engines", "graphics", "gui", "rendering"]
[features]
trace = [
"bevy_app/trace",
"bevy_asset?/trace",
"bevy_core_pipeline?/trace",
"bevy_ecs/trace",
"bevy_log/trace",
"bevy_pbr?/trace",
"bevy_render?/trace",
"bevy_hierarchy/trace",
"bevy_winit?/trace",
]
trace_chrome = ["bevy_log/tracing-chrome"]
trace_tracy = ["bevy_render?/tracing-tracy", "bevy_log/tracing-tracy"]
trace_tracy_memory = ["bevy_log/trace_tracy_memory"]
wgpu_trace = ["bevy_render/wgpu_trace"]
detailed_trace = ["bevy_utils/detailed_trace"]
sysinfo_plugin = ["bevy_diagnostic/sysinfo_plugin"]
# Image format support for texture loading (PNG and HDR are enabled by default)
exr = ["bevy_render/exr"]
hdr = ["bevy_render/hdr"]
png = ["bevy_render/png"]
tga = ["bevy_render/tga"]
jpeg = ["bevy_render/jpeg"]
bmp = ["bevy_render/bmp"]
webp = ["bevy_render/webp"]
basis-universal = ["bevy_render/basis-universal"]
dds = ["bevy_render/dds", "bevy_core_pipeline/dds", "bevy_gltf/dds"]
pnm = ["bevy_render/pnm"]
ktx2 = ["bevy_render/ktx2"]
# For ktx2 supercompression
zlib = ["bevy_render/zlib"]
zstd = ["bevy_render/zstd"]
# Include tonemapping LUT KTX2 files.
tonemapping_luts = ["bevy_core_pipeline/tonemapping_luts"]
# Include SMAA LUT KTX2 Files
smaa_luts = ["bevy_core_pipeline/smaa_luts"]
# Audio format support (vorbis is enabled by default)
flac = ["bevy_audio/flac"]
mp3 = ["bevy_audio/mp3"]
vorbis = ["bevy_audio/vorbis"]
wav = ["bevy_audio/wav"]
minimp3 = ["bevy_audio/minimp3"]
symphonia-aac = ["bevy_audio/symphonia-aac"]
symphonia-all = ["bevy_audio/symphonia-all"]
symphonia-flac = ["bevy_audio/symphonia-flac"]
symphonia-isomp4 = ["bevy_audio/symphonia-isomp4"]
symphonia-vorbis = ["bevy_audio/symphonia-vorbis"]
symphonia-wav = ["bevy_audio/symphonia-wav"]
# Shader formats
shader_format_glsl = [
"bevy_render/shader_format_glsl",
"bevy_pbr?/shader_format_glsl",
]
shader_format_spirv = ["bevy_render/shader_format_spirv"]
serialize = [
"bevy_core/serialize",
"bevy_input/serialize",
"bevy_ecs/serialize",
"bevy_time/serialize",
"bevy_window/serialize",
"bevy_winit?/serialize",
"bevy_transform/serialize",
"bevy_math/serialize",
"bevy_scene?/serialize",
"bevy_ui?/serialize",
"bevy_color?/serialize",
]
multi_threaded = [
"bevy_asset?/multi_threaded",
"bevy_ecs/multi_threaded",
"bevy_render?/multi_threaded",
"bevy_tasks/multi_threaded",
]
async-io = ["bevy_tasks/async-io"]
# Display server protocol support (X11 is enabled by default)
wayland = ["bevy_winit/wayland"]
x11 = ["bevy_winit/x11"]
# Transmission textures in `StandardMaterial`:
pbr_transmission_textures = [
"bevy_pbr?/pbr_transmission_textures",
"bevy_gltf?/pbr_transmission_textures",
]
# Multi-layer material textures in `StandardMaterial`:
pbr_multi_layer_material_textures = [
"bevy_pbr?/pbr_multi_layer_material_textures",
"bevy_gltf?/pbr_multi_layer_material_textures",
]
# Anisotropy texture in `StandardMaterial`:
pbr_anisotropy_texture = [
"bevy_pbr?/pbr_anisotropy_texture",
"bevy_gltf?/pbr_anisotropy_texture",
]
# Optimise for WebGL2
webgl = [
"bevy_core_pipeline?/webgl",
"bevy_pbr?/webgl",
"bevy_render?/webgl",
"bevy_gizmos?/webgl",
"bevy_sprite?/webgl",
]
webgpu = [
"bevy_core_pipeline?/webgpu",
"bevy_pbr?/webgpu",
"bevy_render?/webgpu",
"bevy_gizmos?/webgpu",
"bevy_sprite?/webgpu",
]
# enable systems that allow for automated testing on CI
bevy_ci_testing = ["bevy_dev_tools/bevy_ci_testing", "bevy_render?/ci_limits"]
# Enable animation support, and glTF animation loading
animation = ["bevy_animation", "bevy_gltf?/bevy_animation"]
bevy_sprite = ["dep:bevy_sprite", "bevy_gizmos?/bevy_sprite"]
bevy_pbr = ["dep:bevy_pbr", "bevy_gizmos?/bevy_pbr"]
# Used to disable code that is unsupported when Bevy is dynamically linked
dynamic_linking = ["bevy_diagnostic/dynamic_linking"]
# Enable using a shared stdlib for cxx on Android.
android_shared_stdcxx = ["bevy_audio/android_shared_stdcxx"]
# Enable AccessKit on Unix backends (currently only works with experimental
# screen readers and forks.)
accesskit_unix = ["bevy_winit/accesskit_unix"]
bevy_text = ["dep:bevy_text", "bevy_ui?/bevy_text"]
bevy_render = ["dep:bevy_render", "bevy_scene?/bevy_render"]
# Enable assertions to check the validity of parameters passed to glam
glam_assert = ["bevy_math/glam_assert"]
# Enable assertions in debug builds to check the validity of parameters passed to glam
debug_glam_assert = ["bevy_math/debug_glam_assert"]
default_font = ["bevy_text?/default_font"]
# Enables the built-in asset processor for processed assets.
asset_processor = ["bevy_asset?/asset_processor"]
# Enables watching the filesystem for Bevy Asset hot-reloading
file_watcher = ["bevy_asset?/file_watcher"]
# Enables watching embedded files for Bevy Asset hot-reloading
embedded_watcher = ["bevy_asset?/embedded_watcher"]
# Enable system stepping support
bevy_debug_stepping = [
"bevy_ecs/bevy_debug_stepping",
"bevy_app/bevy_debug_stepping",
]
# Enables the meshlet renderer for dense high-poly scenes (experimental)
meshlet = ["bevy_pbr?/meshlet"]
# Enables processing meshes into meshlet meshes for bevy_pbr
meshlet_processor = ["bevy_pbr?/meshlet_processor"]
# Provides a collection of developer tools
bevy_dev_tools = ["dep:bevy_dev_tools"]
# Provides a picking functionality
bevy_picking = ["dep:bevy_picking"]
# Enable support for the ios_simulator by downgrading some rendering capabilities
ios_simulator = ["bevy_pbr?/ios_simulator", "bevy_render?/ios_simulator"]
# Enable built in global state machines
bevy_state = ["dep:bevy_state"]
# Enables source location tracking for change detection, which can assist with debugging
track_change_detection = ["bevy_ecs/track_change_detection"]
# Enable function reflection
reflect_functions = [
"bevy_reflect/functions",
"bevy_app/reflect_functions",
"bevy_ecs/reflect_functions",
]
[dependencies]
# bevy
bevy_a11y = { path = "../bevy_a11y", version = "0.15.0-dev" }
bevy_app = { path = "../bevy_app", version = "0.15.0-dev" }
bevy_core = { path = "../bevy_core", version = "0.15.0-dev" }
bevy_derive = { path = "../bevy_derive", version = "0.15.0-dev" }
bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.15.0-dev" }
bevy_ecs = { path = "../bevy_ecs", version = "0.15.0-dev" }
bevy_state = { path = "../bevy_state", optional = true, version = "0.15.0-dev" }
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.15.0-dev" }
bevy_input = { path = "../bevy_input", version = "0.15.0-dev" }
bevy_log = { path = "../bevy_log", version = "0.15.0-dev" }
bevy_math = { path = "../bevy_math", version = "0.15.0-dev" }
bevy_ptr = { path = "../bevy_ptr", version = "0.15.0-dev" }
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", features = [
"bevy",
] }
bevy_time = { path = "../bevy_time", version = "0.15.0-dev" }
bevy_transform = { path = "../bevy_transform", version = "0.15.0-dev" }
bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" }
bevy_window = { path = "../bevy_window", version = "0.15.0-dev" }
bevy_tasks = { path = "../bevy_tasks", version = "0.15.0-dev" }
# bevy (optional)
bevy_animation = { path = "../bevy_animation", optional = true, version = "0.15.0-dev" }
bevy_asset = { path = "../bevy_asset", optional = true, version = "0.15.0-dev" }
bevy_audio = { path = "../bevy_audio", optional = true, version = "0.15.0-dev" }
bevy_color = { path = "../bevy_color", optional = true, version = "0.15.0-dev" }
bevy_core_pipeline = { path = "../bevy_core_pipeline", optional = true, version = "0.15.0-dev" }
bevy_dev_tools = { path = "../bevy_dev_tools", optional = true, version = "0.15.0-dev" }
bevy_gilrs = { path = "../bevy_gilrs", optional = true, version = "0.15.0-dev" }
bevy_gizmos = { path = "../bevy_gizmos", optional = true, version = "0.15.0-dev", default-features = false }
bevy_gltf = { path = "../bevy_gltf", optional = true, version = "0.15.0-dev" }
bevy_pbr = { path = "../bevy_pbr", optional = true, version = "0.15.0-dev" }
bevy_picking = { path = "../bevy_picking", optional = true, version = "0.15.0-dev" }
bevy_render = { path = "../bevy_render", optional = true, version = "0.15.0-dev" }
bevy_scene = { path = "../bevy_scene", optional = true, version = "0.15.0-dev" }
bevy_sprite = { path = "../bevy_sprite", optional = true, version = "0.15.0-dev" }
bevy_text = { path = "../bevy_text", optional = true, version = "0.15.0-dev" }
bevy_ui = { path = "../bevy_ui", optional = true, version = "0.15.0-dev" }
bevy_winit = { path = "../bevy_winit", optional = true, version = "0.15.0-dev" }
[lints]
workspace = true
[package.metadata.docs.rs]
rustdoc-args = ["-Zunstable-options", "--generate-link-to-definition"]
all-features = true