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,361 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bevy
4
+ class TypeRegistry
5
+ attr_reader :registrations
6
+
7
+ def initialize
8
+ @registrations = {}
9
+ end
10
+
11
+ def register(type)
12
+ type_name = extract_type_name(type)
13
+ @registrations[type_name] = TypeRegistration.new(type)
14
+ self
15
+ end
16
+
17
+ def get(type_name)
18
+ @registrations[type_name]
19
+ end
20
+
21
+ def registered?(type_name)
22
+ @registrations.key?(type_name)
23
+ end
24
+
25
+ def type_names
26
+ @registrations.keys
27
+ end
28
+
29
+ def type_name
30
+ 'TypeRegistry'
31
+ end
32
+
33
+ private
34
+
35
+ def extract_type_name(type)
36
+ if type.is_a?(Class)
37
+ instance = type.allocate rescue nil
38
+ if instance && instance.respond_to?(:type_name)
39
+ instance.type_name
40
+ else
41
+ type.name.split('::').last
42
+ end
43
+ else
44
+ type.respond_to?(:type_name) ? type.type_name : type.to_s
45
+ end
46
+ end
47
+ end
48
+
49
+ class TypeRegistration
50
+ attr_reader :type, :type_info, :data
51
+
52
+ def initialize(type)
53
+ @type = type
54
+ @type_info = build_type_info(type)
55
+ @data = {}
56
+ end
57
+
58
+ def type_name
59
+ 'TypeRegistration'
60
+ end
61
+
62
+ def insert_data(key, value)
63
+ @data[key] = value
64
+ self
65
+ end
66
+
67
+ def get_data(key)
68
+ @data[key]
69
+ end
70
+
71
+ def type_name
72
+ 'TypeRegistration'
73
+ end
74
+
75
+ private
76
+
77
+ def build_type_info(type)
78
+ if type.is_a?(Class)
79
+ StructInfo.new(type)
80
+ else
81
+ ValueInfo.new(type)
82
+ end
83
+ end
84
+ end
85
+
86
+ class TypeInfo
87
+ attr_reader :name
88
+
89
+ def initialize(name)
90
+ @name = name
91
+ end
92
+
93
+ def type_name
94
+ 'TypeInfo'
95
+ end
96
+ end
97
+
98
+ class StructInfo < TypeInfo
99
+ attr_reader :fields
100
+
101
+ def initialize(type)
102
+ name = if type.is_a?(Class)
103
+ instance = type.allocate rescue nil
104
+ if instance && instance.respond_to?(:type_name)
105
+ instance.type_name
106
+ else
107
+ type.name.split('::').last
108
+ end
109
+ else
110
+ type.respond_to?(:type_name) ? type.type_name : type.to_s
111
+ end
112
+ super(name)
113
+ @fields = extract_fields(type)
114
+ end
115
+
116
+ def field(name)
117
+ @fields.find { |f| f.name == name }
118
+ end
119
+
120
+ def field_count
121
+ @fields.size
122
+ end
123
+
124
+ def type_name
125
+ 'StructInfo'
126
+ end
127
+
128
+ private
129
+
130
+ def extract_fields(type)
131
+ fields = []
132
+ if type.respond_to?(:attributes)
133
+ type.attributes.each do |name, config|
134
+ fields << FieldInfo.new(name: name, type: config[:type])
135
+ end
136
+ elsif type.is_a?(Class)
137
+ type.instance_methods(false).each do |method|
138
+ next if method.to_s.end_with?('=')
139
+ next if %i[initialize type_name to_h to_native].include?(method)
140
+
141
+ fields << FieldInfo.new(name: method, type: :unknown)
142
+ end
143
+ end
144
+ fields
145
+ end
146
+ end
147
+
148
+ class ValueInfo < TypeInfo
149
+ def type_name
150
+ 'ValueInfo'
151
+ end
152
+ end
153
+
154
+ class FieldInfo
155
+ attr_reader :name, :type, :default
156
+
157
+ def initialize(name:, type:, default: nil)
158
+ @name = name.to_sym
159
+ @type = type
160
+ @default = default
161
+ end
162
+
163
+ def type_name
164
+ 'FieldInfo'
165
+ end
166
+ end
167
+
168
+ module Reflect
169
+ def get_field(name)
170
+ if respond_to?(name)
171
+ send(name)
172
+ elsif instance_variable_defined?(:"@#{name}")
173
+ instance_variable_get(:"@#{name}")
174
+ end
175
+ end
176
+
177
+ def set_field(name, value)
178
+ setter = :"#{name}="
179
+ if respond_to?(setter)
180
+ send(setter, value)
181
+ elsif instance_variable_defined?(:"@#{name}")
182
+ instance_variable_set(:"@#{name}", value)
183
+ end
184
+ end
185
+
186
+ def field_names
187
+ instance_variables.map { |v| v.to_s.delete('@').to_sym }
188
+ end
189
+
190
+ def apply(other)
191
+ other.field_names.each do |name|
192
+ set_field(name, other.get_field(name))
193
+ end
194
+ self
195
+ end
196
+
197
+ def clone_value
198
+ clone
199
+ end
200
+ end
201
+
202
+ class ReflectComponent
203
+ attr_reader :component_type
204
+
205
+ def initialize(component_type)
206
+ @component_type = component_type
207
+ end
208
+
209
+ def insert(entity, component, world)
210
+ world.insert_component(entity, component)
211
+ end
212
+
213
+ def remove(entity, world)
214
+ world.remove_component(entity, @component_type)
215
+ end
216
+
217
+ def reflect(entity, world)
218
+ world.get_component(entity, @component_type)
219
+ end
220
+
221
+ def type_name
222
+ 'ReflectComponent'
223
+ end
224
+ end
225
+
226
+ class ReflectResource
227
+ attr_reader :resource_type
228
+
229
+ def initialize(resource_type)
230
+ @resource_type = resource_type
231
+ end
232
+
233
+ def insert(resource, world)
234
+ world.insert_resource(resource)
235
+ end
236
+
237
+ def remove(world)
238
+ world.remove_resource(@resource_type)
239
+ end
240
+
241
+ def reflect(world)
242
+ world.get_resource(@resource_type)
243
+ end
244
+
245
+ def type_name
246
+ 'ReflectResource'
247
+ end
248
+ end
249
+
250
+ class DynamicStruct
251
+ include Reflect
252
+
253
+ def initialize(type_name:, fields: {})
254
+ @_type_name = type_name
255
+ fields.each do |name, value|
256
+ instance_variable_set(:"@#{name}", value)
257
+ define_singleton_method(name) { instance_variable_get(:"@#{name}") }
258
+ define_singleton_method(:"#{name}=") { |v| instance_variable_set(:"@#{name}", v) }
259
+ end
260
+ end
261
+
262
+ def type_name
263
+ @_type_name
264
+ end
265
+
266
+ def to_h
267
+ field_names.reject { |n| n == :_type_name }.to_h { |n| [n, get_field(n)] }
268
+ end
269
+ end
270
+
271
+ class FromReflect
272
+ def self.from_reflect(reflected)
273
+ return nil unless reflected
274
+
275
+ case reflected
276
+ when Hash
277
+ DynamicStruct.new(type_name: 'Anonymous', fields: reflected)
278
+ when DynamicStruct
279
+ reflected.clone_value
280
+ else
281
+ reflected.respond_to?(:clone_value) ? reflected.clone_value : reflected.dup
282
+ end
283
+ end
284
+ end
285
+
286
+ class ReflectSerializer
287
+ def self.serialize(value)
288
+ case value
289
+ when nil, true, false, Integer, Float, String, Symbol
290
+ value
291
+ when Array
292
+ value.map { |v| serialize(v) }
293
+ when Hash
294
+ value.transform_values { |v| serialize(v) }
295
+ when Reflect
296
+ { _type: value.type_name }.merge(
297
+ value.field_names.to_h { |n| [n, serialize(value.get_field(n))] }
298
+ )
299
+ else
300
+ value.respond_to?(:to_h) ? serialize(value.to_h) : value.to_s
301
+ end
302
+ end
303
+ end
304
+
305
+ class ReflectDeserializer
306
+ def initialize(registry)
307
+ @registry = registry
308
+ end
309
+
310
+ def deserialize(data)
311
+ case data
312
+ when Hash
313
+ if data[:_type]
314
+ type_name = data[:_type]
315
+ registration = @registry.get(type_name)
316
+ if registration
317
+ fields = data.reject { |k, _| k == :_type }
318
+ DynamicStruct.new(type_name: type_name, fields: fields)
319
+ else
320
+ DynamicStruct.new(type_name: type_name, fields: data.reject { |k, _| k == :_type })
321
+ end
322
+ else
323
+ data.transform_values { |v| deserialize(v) }
324
+ end
325
+ when Array
326
+ data.map { |v| deserialize(v) }
327
+ else
328
+ data
329
+ end
330
+ end
331
+
332
+ def type_name
333
+ 'ReflectDeserializer'
334
+ end
335
+ end
336
+
337
+ class TypePath
338
+ attr_reader :path
339
+
340
+ def initialize(path)
341
+ @path = path
342
+ end
343
+
344
+ def module_name
345
+ parts = @path.split('::')
346
+ parts.size > 1 ? parts[0..-2].join('::') : nil
347
+ end
348
+
349
+ def type_ident
350
+ @path.split('::').last
351
+ end
352
+
353
+ def full_path
354
+ @path
355
+ end
356
+
357
+ def type_name
358
+ 'TypePath'
359
+ end
360
+ end
361
+ end
@@ -0,0 +1,210 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bevy
4
+ class RenderGraph
5
+ attr_reader :nodes, :edges
6
+
7
+ def initialize
8
+ @nodes = {}
9
+ @edges = []
10
+ @input_node = nil
11
+ @output_node = nil
12
+ end
13
+
14
+ def add_node(name, node)
15
+ @nodes[name] = node
16
+ self
17
+ end
18
+
19
+ def remove_node(name)
20
+ @nodes.delete(name)
21
+ @edges.reject! { |e| e[:from] == name || e[:to] == name }
22
+ end
23
+
24
+ def get_node(name)
25
+ @nodes[name]
26
+ end
27
+
28
+ def add_edge(from, to)
29
+ @edges << { from: from, to: to }
30
+ self
31
+ end
32
+
33
+ def set_input(name)
34
+ @input_node = name
35
+ end
36
+
37
+ def set_output(name)
38
+ @output_node = name
39
+ end
40
+
41
+ def node_count
42
+ @nodes.size
43
+ end
44
+
45
+ def edge_count
46
+ @edges.size
47
+ end
48
+
49
+ def topological_order
50
+ visited = {}
51
+ order = []
52
+
53
+ @nodes.keys.each do |name|
54
+ visit(name, visited, order) unless visited[name]
55
+ end
56
+
57
+ order.reverse
58
+ end
59
+
60
+ def type_name
61
+ 'RenderGraph'
62
+ end
63
+
64
+ private
65
+
66
+ def visit(name, visited, order)
67
+ visited[name] = true
68
+ @edges.each do |edge|
69
+ next unless edge[:from] == name
70
+ next if visited[edge[:to]]
71
+
72
+ visit(edge[:to], visited, order)
73
+ end
74
+ order << name
75
+ end
76
+ end
77
+
78
+ class RenderGraphNode
79
+ attr_reader :name, :inputs, :outputs
80
+
81
+ def initialize(name)
82
+ @name = name
83
+ @inputs = []
84
+ @outputs = []
85
+ end
86
+
87
+ def add_input(name, type = :texture)
88
+ @inputs << { name: name, type: type }
89
+ self
90
+ end
91
+
92
+ def add_output(name, type = :texture)
93
+ @outputs << { name: name, type: type }
94
+ self
95
+ end
96
+
97
+ def run(_world, _resources)
98
+ raise NotImplementedError
99
+ end
100
+
101
+ def type_name
102
+ 'RenderGraphNode'
103
+ end
104
+ end
105
+
106
+ class ViewNode < RenderGraphNode
107
+ attr_accessor :view_query
108
+
109
+ def initialize(name)
110
+ super(name)
111
+ @view_query = nil
112
+ end
113
+
114
+ def type_name
115
+ 'ViewNode'
116
+ end
117
+ end
118
+
119
+ class RenderPass
120
+ attr_accessor :label, :color_attachments, :depth_stencil_attachment
121
+
122
+ def initialize(label: nil)
123
+ @label = label
124
+ @color_attachments = []
125
+ @depth_stencil_attachment = nil
126
+ end
127
+
128
+ def add_color_attachment(attachment)
129
+ @color_attachments << attachment
130
+ self
131
+ end
132
+
133
+ def type_name
134
+ 'RenderPass'
135
+ end
136
+ end
137
+
138
+ class ColorAttachment
139
+ attr_accessor :view, :resolve_target, :load_op, :store_op, :clear_color
140
+
141
+ LOAD_CLEAR = :clear
142
+ LOAD_LOAD = :load
143
+ STORE_STORE = :store
144
+ STORE_DISCARD = :discard
145
+
146
+ def initialize(
147
+ view: nil,
148
+ load_op: LOAD_CLEAR,
149
+ store_op: STORE_STORE,
150
+ clear_color: nil
151
+ )
152
+ @view = view
153
+ @resolve_target = nil
154
+ @load_op = load_op
155
+ @store_op = store_op
156
+ @clear_color = clear_color || Color.black
157
+ end
158
+
159
+ def type_name
160
+ 'ColorAttachment'
161
+ end
162
+ end
163
+
164
+ class DepthStencilAttachment
165
+ attr_accessor :view, :depth_load_op, :depth_store_op, :clear_depth
166
+
167
+ def initialize(
168
+ view: nil,
169
+ depth_load_op: :clear,
170
+ depth_store_op: :store,
171
+ clear_depth: 1.0
172
+ )
173
+ @view = view
174
+ @depth_load_op = depth_load_op
175
+ @depth_store_op = depth_store_op
176
+ @clear_depth = clear_depth.to_f
177
+ end
178
+
179
+ def type_name
180
+ 'DepthStencilAttachment'
181
+ end
182
+ end
183
+
184
+ class RenderTarget
185
+ attr_accessor :size, :format, :samples
186
+
187
+ def initialize(size:, format: :bgra8_unorm, samples: 1)
188
+ @size = size
189
+ @format = format
190
+ @samples = samples
191
+ end
192
+
193
+ def type_name
194
+ 'RenderTarget'
195
+ end
196
+ end
197
+
198
+ class CameraRenderGraph
199
+ attr_accessor :camera, :graph_name
200
+
201
+ def initialize(camera:, graph_name: 'main')
202
+ @camera = camera
203
+ @graph_name = graph_name
204
+ end
205
+
206
+ def type_name
207
+ 'CameraRenderGraph'
208
+ end
209
+ end
210
+ end