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,250 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bevy
4
+ class Aabb
5
+ attr_accessor :center, :half_extents
6
+
7
+ def initialize(center:, half_extents:)
8
+ @center = center
9
+ @half_extents = half_extents
10
+ end
11
+
12
+ def self.from_min_max(min, max)
13
+ center = Vec3.new(
14
+ (min.x + max.x) / 2.0,
15
+ (min.y + max.y) / 2.0,
16
+ (min.z + max.z) / 2.0
17
+ )
18
+ half_extents = Vec3.new(
19
+ (max.x - min.x) / 2.0,
20
+ (max.y - min.y) / 2.0,
21
+ (max.z - min.z) / 2.0
22
+ )
23
+ new(center: center, half_extents: half_extents)
24
+ end
25
+
26
+ def min
27
+ Vec3.new(
28
+ @center.x - @half_extents.x,
29
+ @center.y - @half_extents.y,
30
+ @center.z - @half_extents.z
31
+ )
32
+ end
33
+
34
+ def max
35
+ Vec3.new(
36
+ @center.x + @half_extents.x,
37
+ @center.y + @half_extents.y,
38
+ @center.z + @half_extents.z
39
+ )
40
+ end
41
+
42
+ def contains_point?(point)
43
+ m = min
44
+ mx = max
45
+ point.x >= m.x && point.x <= mx.x &&
46
+ point.y >= m.y && point.y <= mx.y &&
47
+ point.z >= m.z && point.z <= mx.z
48
+ end
49
+
50
+ def intersects?(other)
51
+ min1 = min
52
+ max1 = max
53
+ min2 = other.min
54
+ max2 = other.max
55
+
56
+ min1.x <= max2.x && max1.x >= min2.x &&
57
+ min1.y <= max2.y && max1.y >= min2.y &&
58
+ min1.z <= max2.z && max1.z >= min2.z
59
+ end
60
+
61
+ def merge(other)
62
+ new_min = Vec3.new(
63
+ [min.x, other.min.x].min,
64
+ [min.y, other.min.y].min,
65
+ [min.z, other.min.z].min
66
+ )
67
+ new_max = Vec3.new(
68
+ [max.x, other.max.x].max,
69
+ [max.y, other.max.y].max,
70
+ [max.z, other.max.z].max
71
+ )
72
+ Aabb.from_min_max(new_min, new_max)
73
+ end
74
+
75
+ def type_name
76
+ 'Aabb'
77
+ end
78
+ end
79
+
80
+ class Frustum
81
+ attr_reader :planes
82
+
83
+ def initialize(planes)
84
+ @planes = planes
85
+ end
86
+
87
+ def self.from_view_projection(view_projection)
88
+ new([])
89
+ end
90
+
91
+ def contains_point?(point)
92
+ @planes.all? { |plane| plane.signed_distance(point) >= 0 }
93
+ end
94
+
95
+ def intersects_aabb?(aabb)
96
+ @planes.all? do |plane|
97
+ p_vertex = Vec3.new(
98
+ plane.normal.x >= 0 ? aabb.max.x : aabb.min.x,
99
+ plane.normal.y >= 0 ? aabb.max.y : aabb.min.y,
100
+ plane.normal.z >= 0 ? aabb.max.z : aabb.min.z
101
+ )
102
+ plane.signed_distance(p_vertex) >= 0
103
+ end
104
+ end
105
+
106
+ def type_name
107
+ 'Frustum'
108
+ end
109
+ end
110
+
111
+ class FrustumPlane
112
+ attr_reader :normal, :distance
113
+
114
+ def initialize(normal:, distance:)
115
+ @normal = normal
116
+ @distance = distance.to_f
117
+ end
118
+
119
+ def signed_distance(point)
120
+ @normal.x * point.x + @normal.y * point.y + @normal.z * point.z + @distance
121
+ end
122
+
123
+ def type_name
124
+ 'FrustumPlane'
125
+ end
126
+ end
127
+
128
+ class VisibleEntities
129
+ attr_reader :entities
130
+
131
+ def initialize
132
+ @entities = []
133
+ end
134
+
135
+ def add(entity)
136
+ @entities << entity
137
+ self
138
+ end
139
+
140
+ def clear
141
+ @entities = []
142
+ end
143
+
144
+ def count
145
+ @entities.size
146
+ end
147
+
148
+ def include?(entity)
149
+ @entities.include?(entity)
150
+ end
151
+
152
+ def type_name
153
+ 'VisibleEntities'
154
+ end
155
+ end
156
+
157
+ class RenderLayers
158
+ attr_reader :layers
159
+
160
+ DEFAULT_LAYER = 0
161
+
162
+ def initialize(layers = [DEFAULT_LAYER])
163
+ @layers = layers.to_a
164
+ end
165
+
166
+ def self.layer(layer)
167
+ new([layer])
168
+ end
169
+
170
+ def self.all
171
+ new((0..31).to_a)
172
+ end
173
+
174
+ def self.none
175
+ new([])
176
+ end
177
+
178
+ def with(layer)
179
+ self.class.new(@layers + [layer])
180
+ end
181
+
182
+ def without(layer)
183
+ self.class.new(@layers - [layer])
184
+ end
185
+
186
+ def intersects?(other)
187
+ (@layers & other.layers).any?
188
+ end
189
+
190
+ def type_name
191
+ 'RenderLayers'
192
+ end
193
+ end
194
+
195
+ class OcclusionCulling
196
+ attr_accessor :enabled
197
+
198
+ def initialize(enabled: true)
199
+ @enabled = enabled
200
+ @occluders = []
201
+ end
202
+
203
+ def add_occluder(aabb)
204
+ @occluders << aabb
205
+ end
206
+
207
+ def clear_occluders
208
+ @occluders = []
209
+ end
210
+
211
+ def is_occluded?(aabb, from_point)
212
+ return false unless @enabled
213
+
214
+ @occluders.any? do |occluder|
215
+ occluder != aabb && occludes?(occluder, aabb, from_point)
216
+ end
217
+ end
218
+
219
+ def type_name
220
+ 'OcclusionCulling'
221
+ end
222
+
223
+ private
224
+
225
+ def occludes?(occluder, target, _from_point)
226
+ occluder.contains_point?(target.center)
227
+ end
228
+ end
229
+
230
+ class Lod
231
+ attr_reader :distances, :current_level
232
+
233
+ def initialize(distances:)
234
+ @distances = distances.sort
235
+ @current_level = 0
236
+ end
237
+
238
+ def update(distance)
239
+ @current_level = @distances.index { |d| distance <= d } || @distances.size
240
+ end
241
+
242
+ def level_count
243
+ @distances.size + 1
244
+ end
245
+
246
+ def type_name
247
+ 'Lod'
248
+ end
249
+ end
250
+ end
@@ -0,0 +1,302 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bevy
4
+ module WindowMode
5
+ WINDOWED = :windowed
6
+ BORDERLESS_FULLSCREEN = :borderless_fullscreen
7
+ SIZED_FULLSCREEN = :sized_fullscreen
8
+ FULLSCREEN = :fullscreen
9
+ end
10
+
11
+ module CursorGrabMode
12
+ NONE = :none
13
+ CONFINED = :confined
14
+ LOCKED = :locked
15
+ end
16
+
17
+ module PresentMode
18
+ AUTO_VSYNC = :auto_vsync
19
+ AUTO_NO_VSYNC = :auto_no_vsync
20
+ FIFO = :fifo
21
+ FIFO_RELAXED = :fifo_relaxed
22
+ IMMEDIATE = :immediate
23
+ MAILBOX = :mailbox
24
+ end
25
+
26
+ class Window
27
+ attr_accessor :title, :width, :height, :position_x, :position_y
28
+ attr_accessor :mode, :present_mode, :resizable, :decorations
29
+ attr_accessor :cursor_visible, :cursor_grab_mode
30
+ attr_accessor :focused, :visible, :always_on_top
31
+ attr_accessor :resolution_scale_factor
32
+
33
+ def initialize(
34
+ title: 'Bevy App',
35
+ width: 1280.0,
36
+ height: 720.0,
37
+ mode: WindowMode::WINDOWED,
38
+ resizable: true,
39
+ decorations: true
40
+ )
41
+ @title = title
42
+ @width = width.to_f
43
+ @height = height.to_f
44
+ @position_x = nil
45
+ @position_y = nil
46
+ @mode = mode
47
+ @present_mode = PresentMode::AUTO_VSYNC
48
+ @resizable = resizable
49
+ @decorations = decorations
50
+ @cursor_visible = true
51
+ @cursor_grab_mode = CursorGrabMode::NONE
52
+ @focused = true
53
+ @visible = true
54
+ @always_on_top = false
55
+ @resolution_scale_factor = 1.0
56
+ end
57
+
58
+ def set_title(title)
59
+ @title = title
60
+ self
61
+ end
62
+
63
+ def resize(width, height)
64
+ @width = width.to_f
65
+ @height = height.to_f
66
+ self
67
+ end
68
+
69
+ def set_position(x, y)
70
+ @position_x = x.to_f
71
+ @position_y = y.to_f
72
+ self
73
+ end
74
+
75
+ def center
76
+ @position_x = nil
77
+ @position_y = nil
78
+ self
79
+ end
80
+
81
+ def set_mode(mode)
82
+ @mode = mode
83
+ self
84
+ end
85
+
86
+ def fullscreen
87
+ @mode = WindowMode::FULLSCREEN
88
+ self
89
+ end
90
+
91
+ def borderless_fullscreen
92
+ @mode = WindowMode::BORDERLESS_FULLSCREEN
93
+ self
94
+ end
95
+
96
+ def windowed
97
+ @mode = WindowMode::WINDOWED
98
+ self
99
+ end
100
+
101
+ def toggle_fullscreen
102
+ @mode = if @mode == WindowMode::WINDOWED
103
+ WindowMode::BORDERLESS_FULLSCREEN
104
+ else
105
+ WindowMode::WINDOWED
106
+ end
107
+ self
108
+ end
109
+
110
+ def hide_cursor
111
+ @cursor_visible = false
112
+ self
113
+ end
114
+
115
+ def show_cursor
116
+ @cursor_visible = true
117
+ self
118
+ end
119
+
120
+ def lock_cursor
121
+ @cursor_grab_mode = CursorGrabMode::LOCKED
122
+ self
123
+ end
124
+
125
+ def confine_cursor
126
+ @cursor_grab_mode = CursorGrabMode::CONFINED
127
+ self
128
+ end
129
+
130
+ def release_cursor
131
+ @cursor_grab_mode = CursorGrabMode::NONE
132
+ self
133
+ end
134
+
135
+ def aspect_ratio
136
+ return 0.0 if @height.zero?
137
+
138
+ @width / @height
139
+ end
140
+
141
+ def resolution
142
+ Vec2.new(@width, @height)
143
+ end
144
+
145
+ def fullscreen?
146
+ @mode != WindowMode::WINDOWED
147
+ end
148
+
149
+ def type_name
150
+ 'Window'
151
+ end
152
+
153
+ def to_h
154
+ {
155
+ title: @title,
156
+ width: @width,
157
+ height: @height,
158
+ mode: @mode,
159
+ resizable: @resizable,
160
+ decorations: @decorations,
161
+ cursor_visible: @cursor_visible,
162
+ cursor_grab_mode: @cursor_grab_mode
163
+ }
164
+ end
165
+ end
166
+
167
+ class PrimaryWindow
168
+ attr_reader :window
169
+
170
+ def initialize(window = nil)
171
+ @window = window || Window.new
172
+ end
173
+
174
+ delegate_missing_to :@window if defined?(delegate_missing_to)
175
+
176
+ def method_missing(method, *args, &block)
177
+ if @window.respond_to?(method)
178
+ @window.send(method, *args, &block)
179
+ else
180
+ super
181
+ end
182
+ end
183
+
184
+ def respond_to_missing?(method, include_private = false)
185
+ @window.respond_to?(method) || super
186
+ end
187
+
188
+ def type_name
189
+ 'PrimaryWindow'
190
+ end
191
+ end
192
+
193
+ class WindowResized
194
+ attr_reader :window_id, :width, :height
195
+
196
+ def initialize(window_id:, width:, height:)
197
+ @window_id = window_id
198
+ @width = width.to_f
199
+ @height = height.to_f
200
+ end
201
+
202
+ def type_name
203
+ 'WindowResized'
204
+ end
205
+ end
206
+
207
+ class WindowMoved
208
+ attr_reader :window_id, :position_x, :position_y
209
+
210
+ def initialize(window_id:, position_x:, position_y:)
211
+ @window_id = window_id
212
+ @position_x = position_x.to_f
213
+ @position_y = position_y.to_f
214
+ end
215
+
216
+ def type_name
217
+ 'WindowMoved'
218
+ end
219
+ end
220
+
221
+ class WindowFocused
222
+ attr_reader :window_id, :focused
223
+
224
+ def initialize(window_id:, focused:)
225
+ @window_id = window_id
226
+ @focused = focused
227
+ end
228
+
229
+ def focused?
230
+ @focused
231
+ end
232
+
233
+ def type_name
234
+ 'WindowFocused'
235
+ end
236
+ end
237
+
238
+ class WindowCloseRequested
239
+ attr_reader :window_id
240
+
241
+ def initialize(window_id:)
242
+ @window_id = window_id
243
+ end
244
+
245
+ def type_name
246
+ 'WindowCloseRequested'
247
+ end
248
+ end
249
+
250
+ class WindowCreated
251
+ attr_reader :window_id
252
+
253
+ def initialize(window_id:)
254
+ @window_id = window_id
255
+ end
256
+
257
+ def type_name
258
+ 'WindowCreated'
259
+ end
260
+ end
261
+
262
+ class Monitor
263
+ attr_reader :name, :physical_width, :physical_height, :refresh_rate, :scale_factor
264
+
265
+ def initialize(name:, physical_width:, physical_height:, refresh_rate: 60.0, scale_factor: 1.0)
266
+ @name = name
267
+ @physical_width = physical_width
268
+ @physical_height = physical_height
269
+ @refresh_rate = refresh_rate.to_f
270
+ @scale_factor = scale_factor.to_f
271
+ end
272
+
273
+ def resolution
274
+ Vec2.new(@physical_width.to_f, @physical_height.to_f)
275
+ end
276
+
277
+ def type_name
278
+ 'Monitor'
279
+ end
280
+ end
281
+
282
+ class WindowPlugin
283
+ attr_accessor :primary_window, :exit_condition, :close_when_requested
284
+
285
+ def initialize(primary_window: nil, close_when_requested: true)
286
+ @primary_window = primary_window
287
+ @close_when_requested = close_when_requested
288
+ @exit_condition = :on_primary_closed
289
+ end
290
+
291
+ def build(app)
292
+ if @primary_window
293
+ app.insert_resource(PrimaryWindow.new(@primary_window))
294
+ end
295
+ app
296
+ end
297
+
298
+ def type_name
299
+ 'WindowPlugin'
300
+ end
301
+ end
302
+ end