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,360 @@
1
+ use std::collections::{HashMap, HashSet};
2
+ use std::path::{Path, PathBuf};
3
+ use std::time::SystemTime;
4
+
5
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6
+ pub enum AssetLoadState {
7
+ NotLoaded,
8
+ Loading,
9
+ Loaded,
10
+ Failed,
11
+ }
12
+
13
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14
+ pub struct AssetId(pub u64);
15
+
16
+ impl AssetId {
17
+ pub fn new(id: u64) -> Self {
18
+ Self(id)
19
+ }
20
+ }
21
+
22
+ #[derive(Debug, Clone)]
23
+ pub struct AssetMeta {
24
+ pub id: AssetId,
25
+ pub path: PathBuf,
26
+ pub asset_type: String,
27
+ pub state: AssetLoadState,
28
+ pub last_modified: Option<SystemTime>,
29
+ pub dependencies: Vec<AssetId>,
30
+ pub dependents: Vec<AssetId>,
31
+ }
32
+
33
+ impl AssetMeta {
34
+ pub fn new(id: AssetId, path: PathBuf, asset_type: String) -> Self {
35
+ Self {
36
+ id,
37
+ path,
38
+ asset_type,
39
+ state: AssetLoadState::NotLoaded,
40
+ last_modified: None,
41
+ dependencies: Vec::new(),
42
+ dependents: Vec::new(),
43
+ }
44
+ }
45
+ }
46
+
47
+ #[derive(Debug, Clone)]
48
+ pub struct AssetChangeEvent {
49
+ pub id: AssetId,
50
+ pub path: PathBuf,
51
+ pub change_type: AssetChangeType,
52
+ }
53
+
54
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
55
+ pub enum AssetChangeType {
56
+ Created,
57
+ Modified,
58
+ Deleted,
59
+ }
60
+
61
+ pub struct FileWatcher {
62
+ watched_paths: HashMap<PathBuf, SystemTime>,
63
+ base_paths: Vec<PathBuf>,
64
+ extensions: HashSet<String>,
65
+ }
66
+
67
+ impl FileWatcher {
68
+ pub fn new() -> Self {
69
+ Self {
70
+ watched_paths: HashMap::new(),
71
+ base_paths: Vec::new(),
72
+ extensions: HashSet::new(),
73
+ }
74
+ }
75
+
76
+ pub fn add_base_path(&mut self, path: PathBuf) {
77
+ self.base_paths.push(path);
78
+ }
79
+
80
+ pub fn add_extension(&mut self, ext: String) {
81
+ self.extensions.insert(ext.to_lowercase());
82
+ }
83
+
84
+ pub fn watch(&mut self, path: &Path) -> bool {
85
+ if let Ok(metadata) = std::fs::metadata(path) {
86
+ if let Ok(modified) = metadata.modified() {
87
+ self.watched_paths.insert(path.to_path_buf(), modified);
88
+ return true;
89
+ }
90
+ }
91
+ false
92
+ }
93
+
94
+ pub fn unwatch(&mut self, path: &Path) {
95
+ self.watched_paths.remove(path);
96
+ }
97
+
98
+ pub fn check_changes(&mut self) -> Vec<(PathBuf, AssetChangeType)> {
99
+ let mut changes = Vec::new();
100
+ let mut to_remove = Vec::new();
101
+
102
+ for (path, last_modified) in &self.watched_paths {
103
+ match std::fs::metadata(path) {
104
+ Ok(metadata) => {
105
+ if let Ok(modified) = metadata.modified() {
106
+ if modified > *last_modified {
107
+ changes.push((path.clone(), AssetChangeType::Modified));
108
+ }
109
+ }
110
+ }
111
+ Err(_) => {
112
+ changes.push((path.clone(), AssetChangeType::Deleted));
113
+ to_remove.push(path.clone());
114
+ }
115
+ }
116
+ }
117
+
118
+ for path in to_remove {
119
+ self.watched_paths.remove(&path);
120
+ }
121
+
122
+ for (path, change_type) in &changes {
123
+ if *change_type == AssetChangeType::Modified {
124
+ if let Ok(metadata) = std::fs::metadata(path) {
125
+ if let Ok(modified) = metadata.modified() {
126
+ self.watched_paths.insert(path.clone(), modified);
127
+ }
128
+ }
129
+ }
130
+ }
131
+
132
+ changes
133
+ }
134
+
135
+ pub fn watched_count(&self) -> usize {
136
+ self.watched_paths.len()
137
+ }
138
+ }
139
+
140
+ impl Default for FileWatcher {
141
+ fn default() -> Self {
142
+ Self::new()
143
+ }
144
+ }
145
+
146
+ pub struct AssetRegistry {
147
+ assets: HashMap<AssetId, AssetMeta>,
148
+ path_to_id: HashMap<PathBuf, AssetId>,
149
+ next_id: u64,
150
+ file_watcher: FileWatcher,
151
+ hot_reload_enabled: bool,
152
+ }
153
+
154
+ impl AssetRegistry {
155
+ pub fn new() -> Self {
156
+ Self {
157
+ assets: HashMap::new(),
158
+ path_to_id: HashMap::new(),
159
+ next_id: 0,
160
+ file_watcher: FileWatcher::new(),
161
+ hot_reload_enabled: false,
162
+ }
163
+ }
164
+
165
+ pub fn enable_hot_reload(&mut self) {
166
+ self.hot_reload_enabled = true;
167
+ }
168
+
169
+ pub fn disable_hot_reload(&mut self) {
170
+ self.hot_reload_enabled = false;
171
+ }
172
+
173
+ pub fn is_hot_reload_enabled(&self) -> bool {
174
+ self.hot_reload_enabled
175
+ }
176
+
177
+ pub fn register(&mut self, path: PathBuf, asset_type: String) -> AssetId {
178
+ if let Some(&id) = self.path_to_id.get(&path) {
179
+ return id;
180
+ }
181
+
182
+ let id = AssetId::new(self.next_id);
183
+ self.next_id += 1;
184
+
185
+ let meta = AssetMeta::new(id, path.clone(), asset_type);
186
+ self.assets.insert(id, meta);
187
+ self.path_to_id.insert(path.clone(), id);
188
+
189
+ if self.hot_reload_enabled {
190
+ self.file_watcher.watch(&path);
191
+ }
192
+
193
+ id
194
+ }
195
+
196
+ pub fn unregister(&mut self, id: AssetId) {
197
+ if let Some(meta) = self.assets.remove(&id) {
198
+ self.path_to_id.remove(&meta.path);
199
+ if self.hot_reload_enabled {
200
+ self.file_watcher.unwatch(&meta.path);
201
+ }
202
+ }
203
+ }
204
+
205
+ pub fn get(&self, id: AssetId) -> Option<&AssetMeta> {
206
+ self.assets.get(&id)
207
+ }
208
+
209
+ pub fn get_mut(&mut self, id: AssetId) -> Option<&mut AssetMeta> {
210
+ self.assets.get_mut(&id)
211
+ }
212
+
213
+ pub fn get_by_path(&self, path: &Path) -> Option<&AssetMeta> {
214
+ self.path_to_id
215
+ .get(path)
216
+ .and_then(|id| self.assets.get(id))
217
+ }
218
+
219
+ pub fn set_state(&mut self, id: AssetId, state: AssetLoadState) {
220
+ if let Some(meta) = self.assets.get_mut(&id) {
221
+ meta.state = state;
222
+ if state == AssetLoadState::Loaded {
223
+ if let Ok(file_meta) = std::fs::metadata(&meta.path) {
224
+ meta.last_modified = file_meta.modified().ok();
225
+ }
226
+ }
227
+ }
228
+ }
229
+
230
+ pub fn add_dependency(&mut self, asset_id: AssetId, dependency_id: AssetId) {
231
+ if let Some(meta) = self.assets.get_mut(&asset_id) {
232
+ if !meta.dependencies.contains(&dependency_id) {
233
+ meta.dependencies.push(dependency_id);
234
+ }
235
+ }
236
+ if let Some(dep_meta) = self.assets.get_mut(&dependency_id) {
237
+ if !dep_meta.dependents.contains(&asset_id) {
238
+ dep_meta.dependents.push(asset_id);
239
+ }
240
+ }
241
+ }
242
+
243
+ pub fn check_for_changes(&mut self) -> Vec<AssetChangeEvent> {
244
+ if !self.hot_reload_enabled {
245
+ return Vec::new();
246
+ }
247
+
248
+ let changes = self.file_watcher.check_changes();
249
+ changes
250
+ .into_iter()
251
+ .filter_map(|(path, change_type)| {
252
+ self.path_to_id.get(&path).map(|&id| AssetChangeEvent {
253
+ id,
254
+ path,
255
+ change_type,
256
+ })
257
+ })
258
+ .collect()
259
+ }
260
+
261
+ pub fn get_dependents(&self, id: AssetId) -> Vec<AssetId> {
262
+ self.assets
263
+ .get(&id)
264
+ .map_or_else(Vec::new, |meta| meta.dependents.clone())
265
+ }
266
+
267
+ pub fn get_reload_list(&self, changed_id: AssetId) -> Vec<AssetId> {
268
+ let mut to_reload = vec![changed_id];
269
+ let mut visited = HashSet::new();
270
+ let mut queue = vec![changed_id];
271
+
272
+ while let Some(id) = queue.pop() {
273
+ if visited.contains(&id) {
274
+ continue;
275
+ }
276
+ visited.insert(id);
277
+
278
+ for dep_id in self.get_dependents(id) {
279
+ if !visited.contains(&dep_id) {
280
+ to_reload.push(dep_id);
281
+ queue.push(dep_id);
282
+ }
283
+ }
284
+ }
285
+
286
+ to_reload
287
+ }
288
+
289
+ pub fn all_ids(&self) -> Vec<AssetId> {
290
+ self.assets.keys().copied().collect()
291
+ }
292
+
293
+ pub fn count(&self) -> usize {
294
+ self.assets.len()
295
+ }
296
+ }
297
+
298
+ impl Default for AssetRegistry {
299
+ fn default() -> Self {
300
+ Self::new()
301
+ }
302
+ }
303
+
304
+ pub struct AssetLoadRequest {
305
+ pub id: AssetId,
306
+ pub path: PathBuf,
307
+ pub asset_type: String,
308
+ pub priority: i32,
309
+ }
310
+
311
+ pub struct AssetLoadQueue {
312
+ requests: Vec<AssetLoadRequest>,
313
+ }
314
+
315
+ impl AssetLoadQueue {
316
+ pub fn new() -> Self {
317
+ Self {
318
+ requests: Vec::new(),
319
+ }
320
+ }
321
+
322
+ pub fn enqueue(&mut self, request: AssetLoadRequest) {
323
+ let insert_pos = self
324
+ .requests
325
+ .iter()
326
+ .position(|r| r.priority < request.priority)
327
+ .unwrap_or(self.requests.len());
328
+ self.requests.insert(insert_pos, request);
329
+ }
330
+
331
+ pub fn dequeue(&mut self) -> Option<AssetLoadRequest> {
332
+ if self.requests.is_empty() {
333
+ None
334
+ } else {
335
+ Some(self.requests.remove(0))
336
+ }
337
+ }
338
+
339
+ pub fn peek(&self) -> Option<&AssetLoadRequest> {
340
+ self.requests.first()
341
+ }
342
+
343
+ pub fn is_empty(&self) -> bool {
344
+ self.requests.is_empty()
345
+ }
346
+
347
+ pub fn len(&self) -> usize {
348
+ self.requests.len()
349
+ }
350
+
351
+ pub fn clear(&mut self) {
352
+ self.requests.clear();
353
+ }
354
+ }
355
+
356
+ impl Default for AssetLoadQueue {
357
+ fn default() -> Self {
358
+ Self::new()
359
+ }
360
+ }