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.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/Cargo.lock +4279 -0
  3. data/Cargo.toml +36 -0
  4. data/README.md +226 -0
  5. data/crates/bevy/Cargo.toml +52 -0
  6. data/crates/bevy/src/app.rs +43 -0
  7. data/crates/bevy/src/component.rs +111 -0
  8. data/crates/bevy/src/entity.rs +30 -0
  9. data/crates/bevy/src/error.rs +32 -0
  10. data/crates/bevy/src/event.rs +190 -0
  11. data/crates/bevy/src/input_bridge.rs +300 -0
  12. data/crates/bevy/src/lib.rs +42 -0
  13. data/crates/bevy/src/mesh_renderer.rs +328 -0
  14. data/crates/bevy/src/query.rs +53 -0
  15. data/crates/bevy/src/render_app.rs +689 -0
  16. data/crates/bevy/src/resource.rs +28 -0
  17. data/crates/bevy/src/schedule.rs +186 -0
  18. data/crates/bevy/src/sprite_renderer.rs +355 -0
  19. data/crates/bevy/src/system.rs +44 -0
  20. data/crates/bevy/src/text_renderer.rs +258 -0
  21. data/crates/bevy/src/types/color.rs +114 -0
  22. data/crates/bevy/src/types/dynamic.rs +131 -0
  23. data/crates/bevy/src/types/math.rs +260 -0
  24. data/crates/bevy/src/types/mod.rs +9 -0
  25. data/crates/bevy/src/types/transform.rs +166 -0
  26. data/crates/bevy/src/world.rs +163 -0
  27. data/crates/bevy_ruby_render/Cargo.toml +22 -0
  28. data/crates/bevy_ruby_render/src/asset.rs +360 -0
  29. data/crates/bevy_ruby_render/src/audio.rs +511 -0
  30. data/crates/bevy_ruby_render/src/camera.rs +365 -0
  31. data/crates/bevy_ruby_render/src/gamepad.rs +398 -0
  32. data/crates/bevy_ruby_render/src/lib.rs +26 -0
  33. data/crates/bevy_ruby_render/src/material.rs +310 -0
  34. data/crates/bevy_ruby_render/src/mesh.rs +491 -0
  35. data/crates/bevy_ruby_render/src/sprite.rs +289 -0
  36. data/ext/bevy/Cargo.toml +20 -0
  37. data/ext/bevy/extconf.rb +6 -0
  38. data/ext/bevy/src/conversions.rs +137 -0
  39. data/ext/bevy/src/lib.rs +29 -0
  40. data/ext/bevy/src/ruby_app.rs +65 -0
  41. data/ext/bevy/src/ruby_color.rs +149 -0
  42. data/ext/bevy/src/ruby_component.rs +189 -0
  43. data/ext/bevy/src/ruby_entity.rs +33 -0
  44. data/ext/bevy/src/ruby_math.rs +384 -0
  45. data/ext/bevy/src/ruby_query.rs +64 -0
  46. data/ext/bevy/src/ruby_render_app.rs +779 -0
  47. data/ext/bevy/src/ruby_system.rs +122 -0
  48. data/ext/bevy/src/ruby_world.rs +107 -0
  49. data/lib/bevy/animation.rb +597 -0
  50. data/lib/bevy/app.rb +675 -0
  51. data/lib/bevy/asset.rb +613 -0
  52. data/lib/bevy/audio.rb +545 -0
  53. data/lib/bevy/audio_effects.rb +224 -0
  54. data/lib/bevy/camera.rb +412 -0
  55. data/lib/bevy/component.rb +91 -0
  56. data/lib/bevy/diagnostics.rb +227 -0
  57. data/lib/bevy/ecs_advanced.rb +296 -0
  58. data/lib/bevy/event.rb +199 -0
  59. data/lib/bevy/gizmos.rb +158 -0
  60. data/lib/bevy/gltf.rb +227 -0
  61. data/lib/bevy/hierarchy.rb +444 -0
  62. data/lib/bevy/input.rb +514 -0
  63. data/lib/bevy/lighting.rb +369 -0
  64. data/lib/bevy/material.rb +248 -0
  65. data/lib/bevy/mesh.rb +257 -0
  66. data/lib/bevy/navigation.rb +344 -0
  67. data/lib/bevy/networking.rb +335 -0
  68. data/lib/bevy/particle.rb +337 -0
  69. data/lib/bevy/physics.rb +396 -0
  70. data/lib/bevy/plugins/default_plugins.rb +34 -0
  71. data/lib/bevy/plugins/input_plugin.rb +49 -0
  72. data/lib/bevy/reflect.rb +361 -0
  73. data/lib/bevy/render_graph.rb +210 -0
  74. data/lib/bevy/resource.rb +185 -0
  75. data/lib/bevy/scene.rb +254 -0
  76. data/lib/bevy/shader.rb +319 -0
  77. data/lib/bevy/shape.rb +195 -0
  78. data/lib/bevy/skeletal.rb +248 -0
  79. data/lib/bevy/sprite.rb +152 -0
  80. data/lib/bevy/sprite_sheet.rb +444 -0
  81. data/lib/bevy/state.rb +277 -0
  82. data/lib/bevy/system.rb +206 -0
  83. data/lib/bevy/text.rb +99 -0
  84. data/lib/bevy/text_advanced.rb +455 -0
  85. data/lib/bevy/timer.rb +147 -0
  86. data/lib/bevy/transform.rb +158 -0
  87. data/lib/bevy/ui.rb +454 -0
  88. data/lib/bevy/ui_advanced.rb +568 -0
  89. data/lib/bevy/version.rb +5 -0
  90. data/lib/bevy/visibility.rb +250 -0
  91. data/lib/bevy/window.rb +302 -0
  92. data/lib/bevy.rb +390 -0
  93. metadata +150 -0
@@ -0,0 +1,398 @@
1
+ use std::collections::HashMap;
2
+
3
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4
+ pub enum GamepadButton {
5
+ South,
6
+ East,
7
+ North,
8
+ West,
9
+ LeftTrigger,
10
+ LeftTrigger2,
11
+ RightTrigger,
12
+ RightTrigger2,
13
+ Select,
14
+ Start,
15
+ Mode,
16
+ LeftThumb,
17
+ RightThumb,
18
+ DPadUp,
19
+ DPadDown,
20
+ DPadLeft,
21
+ DPadRight,
22
+ }
23
+
24
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
25
+ pub enum GamepadAxisType {
26
+ LeftStickX,
27
+ LeftStickY,
28
+ RightStickX,
29
+ RightStickY,
30
+ LeftTrigger,
31
+ RightTrigger,
32
+ }
33
+
34
+ #[derive(Debug, Clone, Copy)]
35
+ pub struct DeadZone {
36
+ pub inner: f32,
37
+ pub outer: f32,
38
+ }
39
+
40
+ impl Default for DeadZone {
41
+ fn default() -> Self {
42
+ Self {
43
+ inner: 0.1,
44
+ outer: 0.95,
45
+ }
46
+ }
47
+ }
48
+
49
+ impl DeadZone {
50
+ pub fn new(inner: f32, outer: f32) -> Self {
51
+ Self {
52
+ inner: inner.clamp(0.0, 1.0),
53
+ outer: outer.clamp(0.0, 1.0),
54
+ }
55
+ }
56
+
57
+ pub fn apply(&self, value: f32) -> f32 {
58
+ let abs_value = value.abs();
59
+ if abs_value < self.inner {
60
+ 0.0
61
+ } else if abs_value > self.outer {
62
+ value.signum()
63
+ } else {
64
+ let normalized = (abs_value - self.inner) / (self.outer - self.inner);
65
+ normalized * value.signum()
66
+ }
67
+ }
68
+ }
69
+
70
+ #[derive(Debug, Clone, Copy)]
71
+ pub struct RumbleRequest {
72
+ pub strong_magnitude: f32,
73
+ pub weak_magnitude: f32,
74
+ pub duration_secs: f32,
75
+ }
76
+
77
+ impl RumbleRequest {
78
+ pub fn new(strong: f32, weak: f32, duration: f32) -> Self {
79
+ Self {
80
+ strong_magnitude: strong.clamp(0.0, 1.0),
81
+ weak_magnitude: weak.clamp(0.0, 1.0),
82
+ duration_secs: duration.max(0.0),
83
+ }
84
+ }
85
+
86
+ pub fn strong(magnitude: f32, duration: f32) -> Self {
87
+ Self::new(magnitude, 0.0, duration)
88
+ }
89
+
90
+ pub fn weak(magnitude: f32, duration: f32) -> Self {
91
+ Self::new(0.0, magnitude, duration)
92
+ }
93
+
94
+ pub fn both(magnitude: f32, duration: f32) -> Self {
95
+ Self::new(magnitude, magnitude, duration)
96
+ }
97
+ }
98
+
99
+ #[derive(Debug, Clone, Copy)]
100
+ pub struct Vec2 {
101
+ pub x: f32,
102
+ pub y: f32,
103
+ }
104
+
105
+ impl Vec2 {
106
+ pub fn new(x: f32, y: f32) -> Self {
107
+ Self { x, y }
108
+ }
109
+
110
+ pub fn zero() -> Self {
111
+ Self { x: 0.0, y: 0.0 }
112
+ }
113
+
114
+ pub fn length(&self) -> f32 {
115
+ (self.x * self.x + self.y * self.y).sqrt()
116
+ }
117
+
118
+ pub fn normalized(&self) -> Self {
119
+ let len = self.length();
120
+ if len > 0.0 {
121
+ Self {
122
+ x: self.x / len,
123
+ y: self.y / len,
124
+ }
125
+ } else {
126
+ Self::zero()
127
+ }
128
+ }
129
+
130
+ pub fn apply_deadzone(&self, deadzone: &DeadZone) -> Self {
131
+ let len = self.length();
132
+ if len < deadzone.inner {
133
+ Self::zero()
134
+ } else if len > deadzone.outer {
135
+ self.normalized()
136
+ } else {
137
+ let normalized_len = (len - deadzone.inner) / (deadzone.outer - deadzone.inner);
138
+ let normalized = self.normalized();
139
+ Self {
140
+ x: normalized.x * normalized_len,
141
+ y: normalized.y * normalized_len,
142
+ }
143
+ }
144
+ }
145
+ }
146
+
147
+ #[derive(Debug, Clone)]
148
+ pub struct GamepadState {
149
+ pub id: u32,
150
+ pub name: String,
151
+ pub connected: bool,
152
+ buttons: HashMap<GamepadButton, ButtonState>,
153
+ axes: HashMap<GamepadAxisType, f32>,
154
+ dead_zones: HashMap<GamepadAxisType, DeadZone>,
155
+ stick_dead_zone: DeadZone,
156
+ pub pending_rumble: Option<RumbleRequest>,
157
+ }
158
+
159
+ #[derive(Debug, Clone, Copy, Default)]
160
+ pub struct ButtonState {
161
+ pub pressed: bool,
162
+ pub just_pressed: bool,
163
+ pub just_released: bool,
164
+ pub value: f32,
165
+ }
166
+
167
+ impl GamepadState {
168
+ pub fn new(id: u32) -> Self {
169
+ Self {
170
+ id,
171
+ name: format!("Gamepad {}", id),
172
+ connected: true,
173
+ buttons: HashMap::new(),
174
+ axes: HashMap::new(),
175
+ dead_zones: HashMap::new(),
176
+ stick_dead_zone: DeadZone::default(),
177
+ pending_rumble: None,
178
+ }
179
+ }
180
+
181
+ pub fn with_name(mut self, name: String) -> Self {
182
+ self.name = name;
183
+ self
184
+ }
185
+
186
+ pub fn set_stick_dead_zone(&mut self, dead_zone: DeadZone) {
187
+ self.stick_dead_zone = dead_zone;
188
+ }
189
+
190
+ pub fn set_axis_dead_zone(&mut self, axis: GamepadAxisType, dead_zone: DeadZone) {
191
+ self.dead_zones.insert(axis, dead_zone);
192
+ }
193
+
194
+ pub fn press(&mut self, button: GamepadButton) {
195
+ let state = self.buttons.entry(button).or_default();
196
+ if !state.pressed {
197
+ state.just_pressed = true;
198
+ }
199
+ state.pressed = true;
200
+ state.value = 1.0;
201
+ }
202
+
203
+ pub fn release(&mut self, button: GamepadButton) {
204
+ if let Some(state) = self.buttons.get_mut(&button) {
205
+ if state.pressed {
206
+ state.just_released = true;
207
+ }
208
+ state.pressed = false;
209
+ state.value = 0.0;
210
+ }
211
+ }
212
+
213
+ pub fn set_button_value(&mut self, button: GamepadButton, value: f32) {
214
+ let state = self.buttons.entry(button).or_default();
215
+ let was_pressed = state.pressed;
216
+ state.value = value;
217
+ state.pressed = value > 0.5;
218
+ if !was_pressed && state.pressed {
219
+ state.just_pressed = true;
220
+ } else if was_pressed && !state.pressed {
221
+ state.just_released = true;
222
+ }
223
+ }
224
+
225
+ pub fn pressed(&self, button: GamepadButton) -> bool {
226
+ self.buttons
227
+ .get(&button)
228
+ .is_some_and(|state| state.pressed)
229
+ }
230
+
231
+ pub fn just_pressed(&self, button: GamepadButton) -> bool {
232
+ self.buttons
233
+ .get(&button)
234
+ .is_some_and(|state| state.just_pressed)
235
+ }
236
+
237
+ pub fn just_released(&self, button: GamepadButton) -> bool {
238
+ self.buttons
239
+ .get(&button)
240
+ .is_some_and(|state| state.just_released)
241
+ }
242
+
243
+ pub fn button_value(&self, button: GamepadButton) -> f32 {
244
+ self.buttons.get(&button).map_or(0.0, |state| state.value)
245
+ }
246
+
247
+ pub fn set_axis(&mut self, axis: GamepadAxisType, value: f32) {
248
+ self.axes.insert(axis, value.clamp(-1.0, 1.0));
249
+ }
250
+
251
+ pub fn axis_raw(&self, axis: GamepadAxisType) -> f32 {
252
+ self.axes.get(&axis).copied().unwrap_or(0.0)
253
+ }
254
+
255
+ pub fn axis(&self, axis: GamepadAxisType) -> f32 {
256
+ let raw = self.axis_raw(axis);
257
+ let default_dead_zone = DeadZone::default();
258
+ let dead_zone = self.dead_zones.get(&axis).unwrap_or(&default_dead_zone);
259
+ dead_zone.apply(raw)
260
+ }
261
+
262
+ pub fn left_stick_raw(&self) -> Vec2 {
263
+ Vec2::new(
264
+ self.axis_raw(GamepadAxisType::LeftStickX),
265
+ self.axis_raw(GamepadAxisType::LeftStickY),
266
+ )
267
+ }
268
+
269
+ pub fn left_stick(&self) -> Vec2 {
270
+ self.left_stick_raw().apply_deadzone(&self.stick_dead_zone)
271
+ }
272
+
273
+ pub fn right_stick_raw(&self) -> Vec2 {
274
+ Vec2::new(
275
+ self.axis_raw(GamepadAxisType::RightStickX),
276
+ self.axis_raw(GamepadAxisType::RightStickY),
277
+ )
278
+ }
279
+
280
+ pub fn right_stick(&self) -> Vec2 {
281
+ self.right_stick_raw().apply_deadzone(&self.stick_dead_zone)
282
+ }
283
+
284
+ pub fn left_trigger(&self) -> f32 {
285
+ self.axis(GamepadAxisType::LeftTrigger).max(0.0)
286
+ }
287
+
288
+ pub fn right_trigger(&self) -> f32 {
289
+ self.axis(GamepadAxisType::RightTrigger).max(0.0)
290
+ }
291
+
292
+ pub fn rumble(&mut self, request: RumbleRequest) {
293
+ self.pending_rumble = Some(request);
294
+ }
295
+
296
+ pub fn stop_rumble(&mut self) {
297
+ self.pending_rumble = Some(RumbleRequest::new(0.0, 0.0, 0.0));
298
+ }
299
+
300
+ pub fn clear_frame_state(&mut self) {
301
+ for state in self.buttons.values_mut() {
302
+ state.just_pressed = false;
303
+ state.just_released = false;
304
+ }
305
+ self.pending_rumble = None;
306
+ }
307
+
308
+ pub fn reset(&mut self) {
309
+ self.buttons.clear();
310
+ self.axes.clear();
311
+ self.pending_rumble = None;
312
+ }
313
+ }
314
+
315
+ #[derive(Debug, Clone, Default)]
316
+ pub struct GamepadManager {
317
+ gamepads: HashMap<u32, GamepadState>,
318
+ default_stick_dead_zone: DeadZone,
319
+ }
320
+
321
+ impl GamepadManager {
322
+ pub fn new() -> Self {
323
+ Self {
324
+ gamepads: HashMap::new(),
325
+ default_stick_dead_zone: DeadZone::default(),
326
+ }
327
+ }
328
+
329
+ pub fn set_default_dead_zone(&mut self, dead_zone: DeadZone) {
330
+ self.default_stick_dead_zone = dead_zone;
331
+ }
332
+
333
+ pub fn connect(&mut self, id: u32) -> &mut GamepadState {
334
+ let mut state = GamepadState::new(id);
335
+ state.set_stick_dead_zone(self.default_stick_dead_zone);
336
+ self.gamepads.entry(id).or_insert(state)
337
+ }
338
+
339
+ pub fn connect_with_name(&mut self, id: u32, name: String) -> &mut GamepadState {
340
+ let mut state = GamepadState::new(id).with_name(name);
341
+ state.set_stick_dead_zone(self.default_stick_dead_zone);
342
+ self.gamepads.entry(id).or_insert(state)
343
+ }
344
+
345
+ pub fn disconnect(&mut self, id: u32) -> Option<GamepadState> {
346
+ self.gamepads.remove(&id)
347
+ }
348
+
349
+ pub fn is_connected(&self, id: u32) -> bool {
350
+ self.gamepads.contains_key(&id)
351
+ }
352
+
353
+ pub fn get(&self, id: u32) -> Option<&GamepadState> {
354
+ self.gamepads.get(&id)
355
+ }
356
+
357
+ pub fn get_mut(&mut self, id: u32) -> Option<&mut GamepadState> {
358
+ self.gamepads.get_mut(&id)
359
+ }
360
+
361
+ pub fn connected_ids(&self) -> Vec<u32> {
362
+ self.gamepads.keys().copied().collect()
363
+ }
364
+
365
+ pub fn count(&self) -> usize {
366
+ self.gamepads.len()
367
+ }
368
+
369
+ pub fn iter(&self) -> impl Iterator<Item = &GamepadState> {
370
+ self.gamepads.values()
371
+ }
372
+
373
+ pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut GamepadState> {
374
+ self.gamepads.values_mut()
375
+ }
376
+
377
+ pub fn clear_frame_state(&mut self) {
378
+ for gamepad in self.gamepads.values_mut() {
379
+ gamepad.clear_frame_state();
380
+ }
381
+ }
382
+
383
+ pub fn any_pressed(&self, button: GamepadButton) -> bool {
384
+ self.gamepads.values().any(|gp| gp.pressed(button))
385
+ }
386
+
387
+ pub fn any_just_pressed(&self, button: GamepadButton) -> bool {
388
+ self.gamepads.values().any(|gp| gp.just_pressed(button))
389
+ }
390
+
391
+ pub fn first(&self) -> Option<&GamepadState> {
392
+ self.gamepads.values().next()
393
+ }
394
+
395
+ pub fn first_mut(&mut self) -> Option<&mut GamepadState> {
396
+ self.gamepads.values_mut().next()
397
+ }
398
+ }
@@ -0,0 +1,26 @@
1
+ pub mod asset;
2
+ pub mod audio;
3
+ pub mod camera;
4
+ pub mod gamepad;
5
+ pub mod material;
6
+ pub mod mesh;
7
+ pub mod sprite;
8
+
9
+ pub use asset::{
10
+ AssetChangeEvent, AssetChangeType, AssetId, AssetLoadQueue, AssetLoadRequest, AssetLoadState,
11
+ AssetMeta, AssetRegistry, FileWatcher,
12
+ };
13
+ pub use audio::{
14
+ AudioChannel, AudioMixer, AudioQueue, AudioSettings, AudioTrack, FadeSettings, PlaybackMode,
15
+ SpatialAudio,
16
+ };
17
+ pub use camera::{
18
+ Camera2dBundle, Camera3dBundle, CameraBounds, CameraConfig, CameraController, CameraShake,
19
+ CameraZoom, SmoothFollow, ViewportConfig,
20
+ };
21
+ pub use gamepad::{
22
+ DeadZone, GamepadAxisType, GamepadButton, GamepadManager, GamepadState, RumbleRequest,
23
+ };
24
+ pub use material::{BlendMode, ColorMaterial, MaterialBuilder, MaterialProperties, StandardMaterial};
25
+ pub use mesh::{MeshBuilder, MeshData, MeshSync, MeshTransformData, ShapeType};
26
+ pub use sprite::{SpriteData, SpriteSync, TransformData};