bevy 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Cargo.lock +4279 -0
- data/Cargo.toml +36 -0
- data/README.md +226 -0
- data/crates/bevy/Cargo.toml +52 -0
- data/crates/bevy/src/app.rs +43 -0
- data/crates/bevy/src/component.rs +111 -0
- data/crates/bevy/src/entity.rs +30 -0
- data/crates/bevy/src/error.rs +32 -0
- data/crates/bevy/src/event.rs +190 -0
- data/crates/bevy/src/input_bridge.rs +300 -0
- data/crates/bevy/src/lib.rs +42 -0
- data/crates/bevy/src/mesh_renderer.rs +328 -0
- data/crates/bevy/src/query.rs +53 -0
- data/crates/bevy/src/render_app.rs +689 -0
- data/crates/bevy/src/resource.rs +28 -0
- data/crates/bevy/src/schedule.rs +186 -0
- data/crates/bevy/src/sprite_renderer.rs +355 -0
- data/crates/bevy/src/system.rs +44 -0
- data/crates/bevy/src/text_renderer.rs +258 -0
- data/crates/bevy/src/types/color.rs +114 -0
- data/crates/bevy/src/types/dynamic.rs +131 -0
- data/crates/bevy/src/types/math.rs +260 -0
- data/crates/bevy/src/types/mod.rs +9 -0
- data/crates/bevy/src/types/transform.rs +166 -0
- data/crates/bevy/src/world.rs +163 -0
- data/crates/bevy_ruby_render/Cargo.toml +22 -0
- data/crates/bevy_ruby_render/src/asset.rs +360 -0
- data/crates/bevy_ruby_render/src/audio.rs +511 -0
- data/crates/bevy_ruby_render/src/camera.rs +365 -0
- data/crates/bevy_ruby_render/src/gamepad.rs +398 -0
- data/crates/bevy_ruby_render/src/lib.rs +26 -0
- data/crates/bevy_ruby_render/src/material.rs +310 -0
- data/crates/bevy_ruby_render/src/mesh.rs +491 -0
- data/crates/bevy_ruby_render/src/sprite.rs +289 -0
- data/ext/bevy/Cargo.toml +20 -0
- data/ext/bevy/extconf.rb +6 -0
- data/ext/bevy/src/conversions.rs +137 -0
- data/ext/bevy/src/lib.rs +29 -0
- data/ext/bevy/src/ruby_app.rs +65 -0
- data/ext/bevy/src/ruby_color.rs +149 -0
- data/ext/bevy/src/ruby_component.rs +189 -0
- data/ext/bevy/src/ruby_entity.rs +33 -0
- data/ext/bevy/src/ruby_math.rs +384 -0
- data/ext/bevy/src/ruby_query.rs +64 -0
- data/ext/bevy/src/ruby_render_app.rs +779 -0
- data/ext/bevy/src/ruby_system.rs +122 -0
- data/ext/bevy/src/ruby_world.rs +107 -0
- data/lib/bevy/animation.rb +597 -0
- data/lib/bevy/app.rb +675 -0
- data/lib/bevy/asset.rb +613 -0
- data/lib/bevy/audio.rb +545 -0
- data/lib/bevy/audio_effects.rb +224 -0
- data/lib/bevy/camera.rb +412 -0
- data/lib/bevy/component.rb +91 -0
- data/lib/bevy/diagnostics.rb +227 -0
- data/lib/bevy/ecs_advanced.rb +296 -0
- data/lib/bevy/event.rb +199 -0
- data/lib/bevy/gizmos.rb +158 -0
- data/lib/bevy/gltf.rb +227 -0
- data/lib/bevy/hierarchy.rb +444 -0
- data/lib/bevy/input.rb +514 -0
- data/lib/bevy/lighting.rb +369 -0
- data/lib/bevy/material.rb +248 -0
- data/lib/bevy/mesh.rb +257 -0
- data/lib/bevy/navigation.rb +344 -0
- data/lib/bevy/networking.rb +335 -0
- data/lib/bevy/particle.rb +337 -0
- data/lib/bevy/physics.rb +396 -0
- data/lib/bevy/plugins/default_plugins.rb +34 -0
- data/lib/bevy/plugins/input_plugin.rb +49 -0
- data/lib/bevy/reflect.rb +361 -0
- data/lib/bevy/render_graph.rb +210 -0
- data/lib/bevy/resource.rb +185 -0
- data/lib/bevy/scene.rb +254 -0
- data/lib/bevy/shader.rb +319 -0
- data/lib/bevy/shape.rb +195 -0
- data/lib/bevy/skeletal.rb +248 -0
- data/lib/bevy/sprite.rb +152 -0
- data/lib/bevy/sprite_sheet.rb +444 -0
- data/lib/bevy/state.rb +277 -0
- data/lib/bevy/system.rb +206 -0
- data/lib/bevy/text.rb +99 -0
- data/lib/bevy/text_advanced.rb +455 -0
- data/lib/bevy/timer.rb +147 -0
- data/lib/bevy/transform.rb +158 -0
- data/lib/bevy/ui.rb +454 -0
- data/lib/bevy/ui_advanced.rb +568 -0
- data/lib/bevy/version.rb +5 -0
- data/lib/bevy/visibility.rb +250 -0
- data/lib/bevy/window.rb +302 -0
- data/lib/bevy.rb +390 -0
- metadata +150 -0
data/Cargo.toml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[workspace]
|
|
2
|
+
members = ["crates/*", "ext/bevy"]
|
|
3
|
+
resolver = "2"
|
|
4
|
+
|
|
5
|
+
[workspace.package]
|
|
6
|
+
version = "0.1.0"
|
|
7
|
+
edition = "2024"
|
|
8
|
+
license = "MIT OR Apache-2.0"
|
|
9
|
+
repository = "https://github.com/ydah/bevy-ruby"
|
|
10
|
+
|
|
11
|
+
[workspace.dependencies]
|
|
12
|
+
bevy_ecs = "0.15"
|
|
13
|
+
bevy_app = "0.15"
|
|
14
|
+
bevy_math = "0.15"
|
|
15
|
+
bevy_transform = "0.15"
|
|
16
|
+
bevy_color = "0.15"
|
|
17
|
+
bevy_render = { version = "0.15", default-features = false }
|
|
18
|
+
bevy_sprite = { version = "0.15", default-features = false }
|
|
19
|
+
bevy_window = "0.15"
|
|
20
|
+
bevy_winit = "0.15"
|
|
21
|
+
bevy_asset = "0.15"
|
|
22
|
+
bevy_time = "0.15"
|
|
23
|
+
bevy_input = "0.15"
|
|
24
|
+
bevy_core_pipeline = { version = "0.15", default-features = false }
|
|
25
|
+
bevy_hierarchy = "0.15"
|
|
26
|
+
bevy_log = "0.15"
|
|
27
|
+
bevy_core = "0.15"
|
|
28
|
+
bevy_a11y = "0.15"
|
|
29
|
+
bevy_image = "0.15"
|
|
30
|
+
bevy_text = { version = "0.15", features = ["default_font"] }
|
|
31
|
+
bevy_picking = "0.15"
|
|
32
|
+
bevy_prototype_lyon = "0.13"
|
|
33
|
+
magnus = "0.8"
|
|
34
|
+
rb-sys = "0.9"
|
|
35
|
+
parking_lot = "0.12"
|
|
36
|
+
thiserror = "2"
|
data/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Bevy Ruby
|
|
2
|
+
|
|
3
|
+
Bevy bindings for Ruby, providing ECS-driven game/app architecture, 2D rendering sync, input bridging, and runtime interaction events.
|
|
4
|
+
|
|
5
|
+
<img width="400" alt="Image" src="https://github.com/user-attachments/assets/440971a6-bf10-4cc2-abe6-e5cf28949b95" />
|
|
6
|
+
|
|
7
|
+
## Status
|
|
8
|
+
|
|
9
|
+
This project provides a practical, Bevy-compatible API surface in Ruby, with a mix of:
|
|
10
|
+
|
|
11
|
+
- native-backed features through Rust + Bevy integration
|
|
12
|
+
- Ruby convenience/DSL layers for ergonomic usage
|
|
13
|
+
|
|
14
|
+
### Native-backed (current)
|
|
15
|
+
|
|
16
|
+
- App/game loop integration (`App`, schedules, startup/update flow)
|
|
17
|
+
- ECS bridge (`World`, `Entity`, dynamic component/resource/event plumbing)
|
|
18
|
+
- Render bridge (window + camera + sync to Bevy scene)
|
|
19
|
+
- `Sprite`
|
|
20
|
+
- `Text2d`
|
|
21
|
+
- `Mesh` 2D primitives (rectangle/circle/regular polygon/line/ellipse)
|
|
22
|
+
- Input bridge
|
|
23
|
+
- keyboard and mouse state
|
|
24
|
+
- gamepad state
|
|
25
|
+
- gamepad rumble forwarding (`RumbleRequest`)
|
|
26
|
+
- Picking event bridge (`bevy_picking`)
|
|
27
|
+
- `over`, `out`, `down`, `up`, `click`
|
|
28
|
+
|
|
29
|
+
### Ruby layer (current)
|
|
30
|
+
|
|
31
|
+
- DSL and registries
|
|
32
|
+
- `ComponentDSL`
|
|
33
|
+
- `ResourceDSL`
|
|
34
|
+
- `EventDSL`
|
|
35
|
+
- `EventRegistry`, readers/writers
|
|
36
|
+
- Runtime helpers
|
|
37
|
+
- `SystemContext` query/spawn/resource/event APIs
|
|
38
|
+
- input helper methods for keyboard/mouse/gamepad
|
|
39
|
+
- picking helper methods (`picking_events`, `picked?`)
|
|
40
|
+
- Value and utility types
|
|
41
|
+
- `Vec2`, `Vec3`, `Quat`, `Transform`, `Color`
|
|
42
|
+
- `KeyboardInput`, `MouseInput`, `GamepadInput`, `Gamepads`, `DeadZone`
|
|
43
|
+
|
|
44
|
+
### Native build note
|
|
45
|
+
|
|
46
|
+
- The Rust backend currently targets Bevy `0.15`.
|
|
47
|
+
- A number of high-level Ruby modules exist in `lib/bevy/*`, but not all are fully wired end-to-end in native Bevy systems yet (for example, parts of audio/scene/gltf/ui/shader/material-related areas).
|
|
48
|
+
|
|
49
|
+
## Requirements
|
|
50
|
+
|
|
51
|
+
- Ruby 3.2+
|
|
52
|
+
- Rust toolchain (`rustc`, `cargo`) for native extension build
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
Add this line to your application's Gemfile:
|
|
57
|
+
|
|
58
|
+
```ruby
|
|
59
|
+
gem 'bevy'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Then run:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
bundle install
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Installing Native Library
|
|
69
|
+
|
|
70
|
+
This gem does not require installing a separate external runtime shared library.
|
|
71
|
+
|
|
72
|
+
The native extension is built from this repository's Rust crates.
|
|
73
|
+
|
|
74
|
+
### macOS
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
xcode-select --install
|
|
78
|
+
bundle install
|
|
79
|
+
bundle exec rake compile
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Linux
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
bundle install
|
|
86
|
+
bundle exec rake compile
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Windows
|
|
90
|
+
|
|
91
|
+
```powershell
|
|
92
|
+
bundle install
|
|
93
|
+
bundle exec rake compile
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Quick Start
|
|
97
|
+
|
|
98
|
+
```ruby
|
|
99
|
+
require 'bevy'
|
|
100
|
+
|
|
101
|
+
class Velocity < Bevy::ComponentDSL
|
|
102
|
+
attribute :x, Float, default: 120.0
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
app = Bevy::App.new(
|
|
106
|
+
render: true,
|
|
107
|
+
window: { title: 'Bevy Ruby', width: 800.0, height: 600.0 }
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
app.add_startup_system do |ctx|
|
|
111
|
+
ctx.spawn(
|
|
112
|
+
Velocity.new,
|
|
113
|
+
Bevy::Transform.from_xyz(0.0, 0.0, 0.0),
|
|
114
|
+
Bevy::Sprite.new(
|
|
115
|
+
color: Bevy::Color.from_hex('#4ECDC4'),
|
|
116
|
+
custom_size: Bevy::Vec2.new(80.0, 80.0)
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
app.add_update_system do |ctx|
|
|
122
|
+
ctx.query(Velocity, Bevy::Transform) do |entity, vel, transform|
|
|
123
|
+
next_x = transform.translation.x + vel.x * ctx.delta
|
|
124
|
+
vel.x *= -1.0 if next_x > 360.0 || next_x < -360.0
|
|
125
|
+
|
|
126
|
+
ctx.world.insert_component(
|
|
127
|
+
entity,
|
|
128
|
+
transform.with_translation(Bevy::Vec3.new(transform.translation.x + vel.x * ctx.delta, 0.0, 0.0))
|
|
129
|
+
)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
ctx.app.stop if ctx.key_pressed?('ESCAPE')
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
app.run
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Gamepad Rumble Example
|
|
139
|
+
|
|
140
|
+
```ruby
|
|
141
|
+
require 'bevy'
|
|
142
|
+
|
|
143
|
+
app = Bevy::App.new(render: true)
|
|
144
|
+
|
|
145
|
+
app.add_update_system do |ctx|
|
|
146
|
+
next unless ctx.any_gamepad_connected?
|
|
147
|
+
|
|
148
|
+
if ctx.gamepad_just_pressed?(Bevy::GamepadButton::SOUTH)
|
|
149
|
+
ctx.gamepad&.rumble(
|
|
150
|
+
Bevy::RumbleRequest.new(strong: 0.8, weak: 0.3, duration: 0.4)
|
|
151
|
+
)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
app.run
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Picking Event Example
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
require 'bevy'
|
|
162
|
+
|
|
163
|
+
app = Bevy::App.new(render: true)
|
|
164
|
+
|
|
165
|
+
app.add_update_system do |ctx|
|
|
166
|
+
ctx.picking_events(:click).each do |event|
|
|
167
|
+
puts "clicked target=#{event.target_id} button=#{event.button}"
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
app.run
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## API Coverage (Bevy docs parity)
|
|
175
|
+
|
|
176
|
+
| Area | Status | Notes |
|
|
177
|
+
| --- | --- | --- |
|
|
178
|
+
| ECS basics (`App`/`World`/entities/components/resources/events) | Implemented | Core loop and dynamic ECS bindings are available |
|
|
179
|
+
| 2D render sync (`Sprite`/`Text2d`/`Mesh` shapes) | Implemented | Ruby-side component data is synchronized to Bevy |
|
|
180
|
+
| Keyboard and mouse input | Implemented | Render loop input state is exposed through `SystemContext` |
|
|
181
|
+
| Gamepad input + rumble | Implemented | State bridge plus `RumbleRequest` forwarding |
|
|
182
|
+
| Picking events (`over`/`out`/`down`/`up`/`click`) | Implemented | Exposed as `Bevy::PickingEvent` |
|
|
183
|
+
| Camera transform controls (2D) | Implemented | Position/scale helpers are available |
|
|
184
|
+
| 3D/PBR-native workflows | Partial | Current bridge is primarily focused on 2D sync |
|
|
185
|
+
| Asset/scene/gltf/audio/ui/full parity with upstream Bevy | Partial | Some APIs exist in Ruby, but native end-to-end wiring is incomplete in several domains |
|
|
186
|
+
| Upstream Bevy version parity (`0.18+`/`main`) | Not implemented | Current backend target is Bevy `0.15` |
|
|
187
|
+
|
|
188
|
+
## Development
|
|
189
|
+
|
|
190
|
+
After checking out the repo, install dependencies:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
bundle install
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Build native extension:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
bundle exec rake compile
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Run tests:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
bundle exec rake spec
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Run examples:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
bundle exec ruby examples/hello_world.rb
|
|
212
|
+
bundle exec ruby examples/input_handling.rb
|
|
213
|
+
bundle exec ruby examples/gamepad.rb
|
|
214
|
+
bundle exec ruby examples/shapes_2d.rb
|
|
215
|
+
bundle exec ruby examples/space_shooter.rb
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
|
|
220
|
+
This project is available under the [MIT License](LICENSE).
|
|
221
|
+
|
|
222
|
+
## Contributing
|
|
223
|
+
|
|
224
|
+
Bug reports and pull requests are welcome at:
|
|
225
|
+
|
|
226
|
+
- https://github.com/ydah/bevy-ruby
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "bevy-ruby"
|
|
3
|
+
version.workspace = true
|
|
4
|
+
edition.workspace = true
|
|
5
|
+
license.workspace = true
|
|
6
|
+
repository.workspace = true
|
|
7
|
+
|
|
8
|
+
[features]
|
|
9
|
+
default = ["rendering"]
|
|
10
|
+
rendering = [
|
|
11
|
+
"bevy_window",
|
|
12
|
+
"bevy_winit",
|
|
13
|
+
"bevy_render",
|
|
14
|
+
"bevy_sprite",
|
|
15
|
+
"bevy_core_pipeline",
|
|
16
|
+
"bevy_asset",
|
|
17
|
+
"bevy_hierarchy",
|
|
18
|
+
"bevy_log",
|
|
19
|
+
"bevy_core",
|
|
20
|
+
"bevy_a11y",
|
|
21
|
+
"bevy_image",
|
|
22
|
+
"bevy_text",
|
|
23
|
+
"bevy_picking",
|
|
24
|
+
"bevy_prototype_lyon",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[dependencies]
|
|
28
|
+
bevy_ecs.workspace = true
|
|
29
|
+
bevy_app.workspace = true
|
|
30
|
+
bevy_math.workspace = true
|
|
31
|
+
bevy_transform.workspace = true
|
|
32
|
+
bevy_color.workspace = true
|
|
33
|
+
bevy_time.workspace = true
|
|
34
|
+
bevy_input.workspace = true
|
|
35
|
+
parking_lot.workspace = true
|
|
36
|
+
thiserror.workspace = true
|
|
37
|
+
|
|
38
|
+
# Optional rendering dependencies
|
|
39
|
+
bevy_window = { workspace = true, optional = true }
|
|
40
|
+
bevy_winit = { workspace = true, optional = true, features = ["x11", "wayland"] }
|
|
41
|
+
bevy_render = { workspace = true, optional = true }
|
|
42
|
+
bevy_sprite = { workspace = true, optional = true }
|
|
43
|
+
bevy_core_pipeline = { workspace = true, optional = true }
|
|
44
|
+
bevy_asset = { workspace = true, optional = true }
|
|
45
|
+
bevy_hierarchy = { workspace = true, optional = true }
|
|
46
|
+
bevy_log = { workspace = true, optional = true }
|
|
47
|
+
bevy_core = { workspace = true, optional = true }
|
|
48
|
+
bevy_a11y = { workspace = true, optional = true }
|
|
49
|
+
bevy_image = { workspace = true, optional = true }
|
|
50
|
+
bevy_text = { workspace = true, optional = true, features = ["default_font"] }
|
|
51
|
+
bevy_picking = { workspace = true, optional = true }
|
|
52
|
+
bevy_prototype_lyon = { workspace = true, optional = true }
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
use crate::component::ComponentRegistry;
|
|
2
|
+
use crate::system::{ScheduleLabel, SystemDescriptor};
|
|
3
|
+
use crate::world::WorldWrapper;
|
|
4
|
+
use std::sync::Arc;
|
|
5
|
+
|
|
6
|
+
pub struct AppBuilder {
|
|
7
|
+
registry: Arc<ComponentRegistry>,
|
|
8
|
+
systems: Vec<SystemDescriptor>,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
impl AppBuilder {
|
|
12
|
+
pub fn new() -> Self {
|
|
13
|
+
Self {
|
|
14
|
+
registry: ComponentRegistry::new(),
|
|
15
|
+
systems: Vec::new(),
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
pub fn registry(&self) -> &Arc<ComponentRegistry> {
|
|
20
|
+
&self.registry
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
pub fn add_system(&mut self, descriptor: SystemDescriptor) {
|
|
24
|
+
self.systems.push(descriptor);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
pub fn systems_for_schedule(&self, schedule: ScheduleLabel) -> Vec<&SystemDescriptor> {
|
|
28
|
+
self.systems
|
|
29
|
+
.iter()
|
|
30
|
+
.filter(|s| s.schedule == schedule)
|
|
31
|
+
.collect()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
pub fn create_world(&self) -> WorldWrapper {
|
|
35
|
+
WorldWrapper::with_registry(Arc::clone(&self.registry))
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
impl Default for AppBuilder {
|
|
40
|
+
fn default() -> Self {
|
|
41
|
+
Self::new()
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
use bevy_ecs::component::ComponentId;
|
|
2
|
+
use parking_lot::RwLock;
|
|
3
|
+
use std::any::TypeId;
|
|
4
|
+
use std::collections::HashMap;
|
|
5
|
+
use std::sync::Arc;
|
|
6
|
+
|
|
7
|
+
#[derive(Debug, Clone)]
|
|
8
|
+
pub struct AttributeDescriptor {
|
|
9
|
+
pub name: String,
|
|
10
|
+
pub attr_type: AttributeType,
|
|
11
|
+
pub default_value: Option<Vec<u8>>,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
15
|
+
pub enum AttributeType {
|
|
16
|
+
Integer,
|
|
17
|
+
Float,
|
|
18
|
+
Boolean,
|
|
19
|
+
String,
|
|
20
|
+
Vec2,
|
|
21
|
+
Vec3,
|
|
22
|
+
Quat,
|
|
23
|
+
Entity,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
#[derive(Debug, Clone)]
|
|
27
|
+
pub struct ComponentMetadata {
|
|
28
|
+
pub name: String,
|
|
29
|
+
pub attributes: Vec<AttributeDescriptor>,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
#[derive(Debug, Clone)]
|
|
33
|
+
pub struct ComponentData {
|
|
34
|
+
pub metadata: ComponentMetadata,
|
|
35
|
+
pub data: HashMap<String, Vec<u8>>,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
impl ComponentData {
|
|
39
|
+
pub fn new(name: &str) -> Self {
|
|
40
|
+
Self {
|
|
41
|
+
metadata: ComponentMetadata {
|
|
42
|
+
name: name.to_string(),
|
|
43
|
+
attributes: Vec::new(),
|
|
44
|
+
},
|
|
45
|
+
data: HashMap::new(),
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pub fn with_attribute(mut self, name: &str, attr_type: AttributeType) -> Self {
|
|
50
|
+
self.metadata.attributes.push(AttributeDescriptor {
|
|
51
|
+
name: name.to_string(),
|
|
52
|
+
attr_type,
|
|
53
|
+
default_value: None,
|
|
54
|
+
});
|
|
55
|
+
self
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
pub fn set_data(&mut self, name: &str, data: Vec<u8>) {
|
|
59
|
+
self.data.insert(name.to_string(), data);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
pub fn get_data(&self, name: &str) -> Option<&Vec<u8>> {
|
|
63
|
+
self.data.get(name)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
pub struct ComponentRegistry {
|
|
68
|
+
name_to_id: RwLock<HashMap<String, ComponentId>>,
|
|
69
|
+
id_to_metadata: RwLock<HashMap<ComponentId, ComponentMetadata>>,
|
|
70
|
+
#[allow(dead_code)]
|
|
71
|
+
type_to_id: RwLock<HashMap<TypeId, ComponentId>>,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
impl ComponentRegistry {
|
|
75
|
+
pub fn new() -> Arc<Self> {
|
|
76
|
+
Arc::new(Self {
|
|
77
|
+
name_to_id: RwLock::new(HashMap::new()),
|
|
78
|
+
id_to_metadata: RwLock::new(HashMap::new()),
|
|
79
|
+
type_to_id: RwLock::new(HashMap::new()),
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
pub fn register(&self, name: &str, component_id: ComponentId, metadata: ComponentMetadata) {
|
|
84
|
+
self.name_to_id
|
|
85
|
+
.write()
|
|
86
|
+
.insert(name.to_string(), component_id);
|
|
87
|
+
self.id_to_metadata.write().insert(component_id, metadata);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
pub fn get_id(&self, name: &str) -> Option<ComponentId> {
|
|
91
|
+
self.name_to_id.read().get(name).copied()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
pub fn get_metadata(&self, id: ComponentId) -> Option<ComponentMetadata> {
|
|
95
|
+
self.id_to_metadata.read().get(&id).cloned()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
pub fn is_registered(&self, name: &str) -> bool {
|
|
99
|
+
self.name_to_id.read().contains_key(name)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
impl Default for ComponentRegistry {
|
|
104
|
+
fn default() -> Self {
|
|
105
|
+
Self {
|
|
106
|
+
name_to_id: RwLock::new(HashMap::new()),
|
|
107
|
+
id_to_metadata: RwLock::new(HashMap::new()),
|
|
108
|
+
type_to_id: RwLock::new(HashMap::new()),
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
use bevy_ecs::entity::Entity;
|
|
2
|
+
|
|
3
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
4
|
+
pub struct EntityWrapper(pub Entity);
|
|
5
|
+
|
|
6
|
+
impl EntityWrapper {
|
|
7
|
+
pub fn new(entity: Entity) -> Self {
|
|
8
|
+
Self(entity)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
pub fn id(&self) -> u64 {
|
|
12
|
+
self.0.to_bits()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
pub fn inner(&self) -> Entity {
|
|
16
|
+
self.0
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
impl From<Entity> for EntityWrapper {
|
|
21
|
+
fn from(entity: Entity) -> Self {
|
|
22
|
+
Self(entity)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
impl From<EntityWrapper> for Entity {
|
|
27
|
+
fn from(wrapper: EntityWrapper) -> Self {
|
|
28
|
+
wrapper.0
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
use bevy_ecs::entity::Entity;
|
|
2
|
+
use thiserror::Error;
|
|
3
|
+
|
|
4
|
+
#[derive(Error, Debug)]
|
|
5
|
+
pub enum BevyRubyError {
|
|
6
|
+
#[error("Entity {0:?} not found")]
|
|
7
|
+
EntityNotFound(Entity),
|
|
8
|
+
|
|
9
|
+
#[error("Component '{component}' not found on entity {entity:?}")]
|
|
10
|
+
ComponentNotFound { entity: Entity, component: String },
|
|
11
|
+
|
|
12
|
+
#[error("Component '{0}' already exists")]
|
|
13
|
+
ComponentAlreadyExists(String),
|
|
14
|
+
|
|
15
|
+
#[error("Resource '{0}' not found")]
|
|
16
|
+
ResourceNotFound(String),
|
|
17
|
+
|
|
18
|
+
#[error("Resource '{0}' already exists")]
|
|
19
|
+
ResourceAlreadyExists(String),
|
|
20
|
+
|
|
21
|
+
#[error("Component '{0}' is not registered")]
|
|
22
|
+
ComponentNotRegistered(String),
|
|
23
|
+
|
|
24
|
+
#[error("Invalid type conversion: expected {expected}, got {actual}")]
|
|
25
|
+
InvalidType { expected: String, actual: String },
|
|
26
|
+
|
|
27
|
+
#[error("System error: {0}")]
|
|
28
|
+
SystemError(String),
|
|
29
|
+
|
|
30
|
+
#[error("World is not available")]
|
|
31
|
+
WorldNotAvailable,
|
|
32
|
+
}
|