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,248 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bevy
4
+ class Skeleton
5
+ attr_reader :bones, :root_bones
6
+
7
+ def initialize
8
+ @bones = []
9
+ @root_bones = []
10
+ end
11
+
12
+ def add_bone(bone)
13
+ @bones << bone
14
+ @root_bones << bone if bone.parent_index.nil?
15
+ self
16
+ end
17
+
18
+ def get_bone(index)
19
+ @bones[index]
20
+ end
21
+
22
+ def bone_count
23
+ @bones.size
24
+ end
25
+
26
+ def find_bone_by_name(name)
27
+ @bones.find { |b| b.name == name }
28
+ end
29
+
30
+ def type_name
31
+ 'Skeleton'
32
+ end
33
+ end
34
+
35
+ class Bone
36
+ attr_accessor :name, :parent_index, :inverse_bind_pose, :local_transform
37
+
38
+ def initialize(name:, parent_index: nil)
39
+ @name = name
40
+ @parent_index = parent_index
41
+ @inverse_bind_pose = Transform.identity
42
+ @local_transform = Transform.identity
43
+ end
44
+
45
+ def type_name
46
+ 'Bone'
47
+ end
48
+ end
49
+
50
+ class SkinnedMesh
51
+ attr_reader :skeleton, :joint_indices, :joint_weights
52
+
53
+ def initialize(skeleton:)
54
+ @skeleton = skeleton
55
+ @joint_indices = []
56
+ @joint_weights = []
57
+ end
58
+
59
+ def add_vertex_weights(indices, weights)
60
+ @joint_indices << indices
61
+ @joint_weights << weights
62
+ end
63
+
64
+ def vertex_count
65
+ @joint_indices.size
66
+ end
67
+
68
+ def type_name
69
+ 'SkinnedMesh'
70
+ end
71
+ end
72
+
73
+ class SkeletalAnimation
74
+ attr_reader :name, :duration, :tracks
75
+
76
+ def initialize(name:, duration:)
77
+ @name = name
78
+ @duration = duration.to_f
79
+ @tracks = {}
80
+ end
81
+
82
+ def add_track(bone_name, track)
83
+ @tracks[bone_name] = track
84
+ self
85
+ end
86
+
87
+ def get_track(bone_name)
88
+ @tracks[bone_name]
89
+ end
90
+
91
+ def sample(time)
92
+ @tracks.transform_values { |track| track.sample(time) }
93
+ end
94
+
95
+ def type_name
96
+ 'SkeletalAnimation'
97
+ end
98
+ end
99
+
100
+ class BoneTrack
101
+ attr_reader :bone_name, :translation_keys, :rotation_keys, :scale_keys
102
+
103
+ def initialize(bone_name:)
104
+ @bone_name = bone_name
105
+ @translation_keys = []
106
+ @rotation_keys = []
107
+ @scale_keys = []
108
+ end
109
+
110
+ def add_translation_key(time, value)
111
+ @translation_keys << { time: time.to_f, value: value }
112
+ self
113
+ end
114
+
115
+ def add_rotation_key(time, value)
116
+ @rotation_keys << { time: time.to_f, value: value }
117
+ self
118
+ end
119
+
120
+ def add_scale_key(time, value)
121
+ @scale_keys << { time: time.to_f, value: value }
122
+ self
123
+ end
124
+
125
+ def sample(time)
126
+ {
127
+ translation: sample_keys(@translation_keys, time),
128
+ rotation: sample_keys(@rotation_keys, time),
129
+ scale: sample_keys(@scale_keys, time)
130
+ }
131
+ end
132
+
133
+ def type_name
134
+ 'BoneTrack'
135
+ end
136
+
137
+ private
138
+
139
+ def sample_keys(keys, time)
140
+ return nil if keys.empty?
141
+ return keys.first[:value] if keys.size == 1
142
+
143
+ prev_key = keys.last { |k| k[:time] <= time } || keys.first
144
+ next_key = keys.find { |k| k[:time] > time } || keys.last
145
+
146
+ return prev_key[:value] if prev_key == next_key
147
+
148
+ t = (time - prev_key[:time]) / (next_key[:time] - prev_key[:time])
149
+ lerp_value(prev_key[:value], next_key[:value], t)
150
+ end
151
+
152
+ def lerp_value(a, b, t)
153
+ return a unless a.respond_to?(:x) && b.respond_to?(:x)
154
+
155
+ Vec3.new(
156
+ a.x + (b.x - a.x) * t,
157
+ a.y + (b.y - a.y) * t,
158
+ a.z + (b.z - a.z) * t
159
+ )
160
+ end
161
+ end
162
+
163
+ class AnimationBlender
164
+ attr_reader :animations, :weights
165
+
166
+ def initialize
167
+ @animations = []
168
+ @weights = []
169
+ end
170
+
171
+ def add_animation(animation, weight: 1.0)
172
+ @animations << animation
173
+ @weights << weight.to_f
174
+ self
175
+ end
176
+
177
+ def set_weight(index, weight)
178
+ @weights[index] = weight.to_f if index < @weights.size
179
+ end
180
+
181
+ def blend(time)
182
+ return {} if @animations.empty?
183
+
184
+ total_weight = @weights.sum
185
+ return {} if total_weight == 0
186
+
187
+ result = {}
188
+ @animations.each_with_index do |anim, i|
189
+ weight = @weights[i] / total_weight
190
+ sample = anim.sample(time)
191
+ sample.each do |bone_name, transform|
192
+ result[bone_name] ||= { translation: Vec3.zero, rotation: Quat.identity, scale: Vec3.one }
193
+ blend_transform(result[bone_name], transform, weight)
194
+ end
195
+ end
196
+ result
197
+ end
198
+
199
+ def type_name
200
+ 'AnimationBlender'
201
+ end
202
+
203
+ private
204
+
205
+ def blend_transform(result, transform, weight)
206
+ if transform[:translation]
207
+ result[:translation] = Vec3.new(
208
+ result[:translation].x + transform[:translation].x * weight,
209
+ result[:translation].y + transform[:translation].y * weight,
210
+ result[:translation].z + transform[:translation].z * weight
211
+ )
212
+ end
213
+ end
214
+ end
215
+
216
+ class IkChain
217
+ attr_reader :target, :bones, :iterations
218
+
219
+ def initialize(bones:, iterations: 10)
220
+ @bones = bones
221
+ @iterations = iterations
222
+ @target = Vec3.zero
223
+ end
224
+
225
+ def set_target(position)
226
+ @target = position
227
+ end
228
+
229
+ def solve(skeleton)
230
+ @iterations.times do
231
+ backward_pass(skeleton)
232
+ forward_pass(skeleton)
233
+ end
234
+ end
235
+
236
+ def type_name
237
+ 'IkChain'
238
+ end
239
+
240
+ private
241
+
242
+ def backward_pass(_skeleton)
243
+ end
244
+
245
+ def forward_pass(_skeleton)
246
+ end
247
+ end
248
+ end
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bevy
4
+ class Sprite
5
+ attr_reader :color, :flip_x, :flip_y, :custom_size, :anchor
6
+
7
+ def initialize(color: nil, flip_x: false, flip_y: false, custom_size: nil, anchor: nil)
8
+ @color = color || Color.white
9
+ @flip_x = flip_x
10
+ @flip_y = flip_y
11
+ @custom_size = custom_size
12
+ @anchor = anchor || Vec2.new(0.5, 0.5)
13
+ end
14
+
15
+ def type_name
16
+ 'Sprite'
17
+ end
18
+
19
+ def with_color(color)
20
+ self.class.new(
21
+ color: color,
22
+ flip_x: @flip_x,
23
+ flip_y: @flip_y,
24
+ custom_size: @custom_size,
25
+ anchor: @anchor
26
+ )
27
+ end
28
+
29
+ def with_flip_x(flip_x)
30
+ self.class.new(
31
+ color: @color,
32
+ flip_x: flip_x,
33
+ flip_y: @flip_y,
34
+ custom_size: @custom_size,
35
+ anchor: @anchor
36
+ )
37
+ end
38
+
39
+ def with_flip_y(flip_y)
40
+ self.class.new(
41
+ color: @color,
42
+ flip_x: @flip_x,
43
+ flip_y: flip_y,
44
+ custom_size: @custom_size,
45
+ anchor: @anchor
46
+ )
47
+ end
48
+
49
+ def with_custom_size(size)
50
+ self.class.new(
51
+ color: @color,
52
+ flip_x: @flip_x,
53
+ flip_y: @flip_y,
54
+ custom_size: size,
55
+ anchor: @anchor
56
+ )
57
+ end
58
+
59
+ def with_anchor(anchor)
60
+ self.class.new(
61
+ color: @color,
62
+ flip_x: @flip_x,
63
+ flip_y: @flip_y,
64
+ custom_size: @custom_size,
65
+ anchor: anchor
66
+ )
67
+ end
68
+
69
+ def to_native
70
+ native = Component.new('Sprite')
71
+ native['color_r'] = @color.r
72
+ native['color_g'] = @color.g
73
+ native['color_b'] = @color.b
74
+ native['color_a'] = @color.a
75
+ native['flip_x'] = @flip_x
76
+ native['flip_y'] = @flip_y
77
+ native['anchor_x'] = @anchor.x
78
+ native['anchor_y'] = @anchor.y
79
+ if @custom_size
80
+ native['custom_size_x'] = @custom_size.x
81
+ native['custom_size_y'] = @custom_size.y
82
+ native['has_custom_size'] = true
83
+ else
84
+ native['has_custom_size'] = false
85
+ end
86
+ native
87
+ end
88
+
89
+ def self.from_native(native)
90
+ color = Color.new(
91
+ native['color_r'] || 1.0,
92
+ native['color_g'] || 1.0,
93
+ native['color_b'] || 1.0,
94
+ native['color_a'] || 1.0
95
+ )
96
+ anchor = Vec2.new(
97
+ native['anchor_x'] || 0.5,
98
+ native['anchor_y'] || 0.5
99
+ )
100
+ custom_size = (Vec2.new(native['custom_size_x'], native['custom_size_y']) if native['has_custom_size'])
101
+ new(
102
+ color: color,
103
+ flip_x: native['flip_x'] || false,
104
+ flip_y: native['flip_y'] || false,
105
+ custom_size: custom_size,
106
+ anchor: anchor
107
+ )
108
+ end
109
+
110
+ def to_h
111
+ h = {
112
+ color: @color.to_a,
113
+ flip_x: @flip_x,
114
+ flip_y: @flip_y,
115
+ anchor: @anchor.to_a
116
+ }
117
+ h[:custom_size] = @custom_size.to_a if @custom_size
118
+ h
119
+ end
120
+
121
+ def to_sync_hash
122
+ h = {
123
+ color_r: @color.r,
124
+ color_g: @color.g,
125
+ color_b: @color.b,
126
+ color_a: @color.a,
127
+ flip_x: @flip_x,
128
+ flip_y: @flip_y,
129
+ anchor_x: @anchor.x,
130
+ anchor_y: @anchor.y
131
+ }
132
+ if @custom_size
133
+ h[:custom_size_x] = @custom_size.x
134
+ h[:custom_size_y] = @custom_size.y
135
+ end
136
+ h
137
+ end
138
+ end
139
+
140
+ class SpriteBundle
141
+ attr_reader :sprite, :transform
142
+
143
+ def initialize(sprite: nil, transform: nil)
144
+ @sprite = sprite || Sprite.new
145
+ @transform = transform || Transform.identity
146
+ end
147
+
148
+ def components
149
+ [@sprite, @transform]
150
+ end
151
+ end
152
+ end