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,369 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bevy
4
+ class PointLight
5
+ attr_accessor :color, :intensity, :range, :radius, :shadows_enabled
6
+
7
+ def initialize(color: nil, intensity: 800.0, range: 20.0, radius: 0.0, shadows_enabled: true)
8
+ @color = color || Color.white
9
+ @intensity = intensity.to_f
10
+ @range = range.to_f
11
+ @radius = radius.to_f
12
+ @shadows_enabled = shadows_enabled
13
+ end
14
+
15
+ def with_color(color)
16
+ self.class.new(
17
+ color: color,
18
+ intensity: @intensity,
19
+ range: @range,
20
+ radius: @radius,
21
+ shadows_enabled: @shadows_enabled
22
+ )
23
+ end
24
+
25
+ def with_intensity(intensity)
26
+ self.class.new(
27
+ color: @color,
28
+ intensity: intensity,
29
+ range: @range,
30
+ radius: @radius,
31
+ shadows_enabled: @shadows_enabled
32
+ )
33
+ end
34
+
35
+ def with_range(range)
36
+ self.class.new(
37
+ color: @color,
38
+ intensity: @intensity,
39
+ range: range,
40
+ radius: @radius,
41
+ shadows_enabled: @shadows_enabled
42
+ )
43
+ end
44
+
45
+ def type_name
46
+ 'PointLight'
47
+ end
48
+
49
+ def to_h
50
+ {
51
+ color: @color.to_a,
52
+ intensity: @intensity,
53
+ range: @range,
54
+ radius: @radius,
55
+ shadows_enabled: @shadows_enabled
56
+ }
57
+ end
58
+
59
+ def to_native
60
+ native = Component.new('PointLight')
61
+ native['color_r'] = @color.r
62
+ native['color_g'] = @color.g
63
+ native['color_b'] = @color.b
64
+ native['color_a'] = @color.a
65
+ native['intensity'] = @intensity
66
+ native['range'] = @range
67
+ native['radius'] = @radius
68
+ native['shadows_enabled'] = @shadows_enabled
69
+ native
70
+ end
71
+
72
+ def self.from_native(native)
73
+ color = Color.rgba(
74
+ native['color_r'] || 1.0,
75
+ native['color_g'] || 1.0,
76
+ native['color_b'] || 1.0,
77
+ native['color_a'] || 1.0
78
+ )
79
+ new(
80
+ color: color,
81
+ intensity: native['intensity'] || 800.0,
82
+ range: native['range'] || 20.0,
83
+ radius: native['radius'] || 0.0,
84
+ shadows_enabled: native['shadows_enabled'] != false
85
+ )
86
+ end
87
+ end
88
+
89
+ class DirectionalLight
90
+ attr_accessor :color, :illuminance, :shadows_enabled
91
+
92
+ def initialize(color: nil, illuminance: 100_000.0, shadows_enabled: true)
93
+ @color = color || Color.white
94
+ @illuminance = illuminance.to_f
95
+ @shadows_enabled = shadows_enabled
96
+ end
97
+
98
+ def with_color(color)
99
+ self.class.new(color: color, illuminance: @illuminance, shadows_enabled: @shadows_enabled)
100
+ end
101
+
102
+ def with_illuminance(illuminance)
103
+ self.class.new(color: @color, illuminance: illuminance, shadows_enabled: @shadows_enabled)
104
+ end
105
+
106
+ def type_name
107
+ 'DirectionalLight'
108
+ end
109
+
110
+ def to_h
111
+ {
112
+ color: @color.to_a,
113
+ illuminance: @illuminance,
114
+ shadows_enabled: @shadows_enabled
115
+ }
116
+ end
117
+
118
+ def to_native
119
+ native = Component.new('DirectionalLight')
120
+ native['color_r'] = @color.r
121
+ native['color_g'] = @color.g
122
+ native['color_b'] = @color.b
123
+ native['color_a'] = @color.a
124
+ native['illuminance'] = @illuminance
125
+ native['shadows_enabled'] = @shadows_enabled
126
+ native
127
+ end
128
+
129
+ def self.from_native(native)
130
+ color = Color.rgba(
131
+ native['color_r'] || 1.0,
132
+ native['color_g'] || 1.0,
133
+ native['color_b'] || 1.0,
134
+ native['color_a'] || 1.0
135
+ )
136
+ new(
137
+ color: color,
138
+ illuminance: native['illuminance'] || 100_000.0,
139
+ shadows_enabled: native['shadows_enabled'] != false
140
+ )
141
+ end
142
+ end
143
+
144
+ class SpotLight
145
+ attr_accessor :color, :intensity, :range, :radius, :inner_angle, :outer_angle, :shadows_enabled
146
+
147
+ def initialize(
148
+ color: nil,
149
+ intensity: 800.0,
150
+ range: 20.0,
151
+ radius: 0.0,
152
+ inner_angle: 0.0,
153
+ outer_angle: Math::PI / 4.0,
154
+ shadows_enabled: true
155
+ )
156
+ @color = color || Color.white
157
+ @intensity = intensity.to_f
158
+ @range = range.to_f
159
+ @radius = radius.to_f
160
+ @inner_angle = inner_angle.to_f
161
+ @outer_angle = outer_angle.to_f
162
+ @shadows_enabled = shadows_enabled
163
+ end
164
+
165
+ def with_color(color)
166
+ self.class.new(
167
+ color: color,
168
+ intensity: @intensity,
169
+ range: @range,
170
+ radius: @radius,
171
+ inner_angle: @inner_angle,
172
+ outer_angle: @outer_angle,
173
+ shadows_enabled: @shadows_enabled
174
+ )
175
+ end
176
+
177
+ def with_intensity(intensity)
178
+ self.class.new(
179
+ color: @color,
180
+ intensity: intensity,
181
+ range: @range,
182
+ radius: @radius,
183
+ inner_angle: @inner_angle,
184
+ outer_angle: @outer_angle,
185
+ shadows_enabled: @shadows_enabled
186
+ )
187
+ end
188
+
189
+ def with_angles(inner, outer)
190
+ self.class.new(
191
+ color: @color,
192
+ intensity: @intensity,
193
+ range: @range,
194
+ radius: @radius,
195
+ inner_angle: inner,
196
+ outer_angle: outer,
197
+ shadows_enabled: @shadows_enabled
198
+ )
199
+ end
200
+
201
+ def type_name
202
+ 'SpotLight'
203
+ end
204
+
205
+ def to_h
206
+ {
207
+ color: @color.to_a,
208
+ intensity: @intensity,
209
+ range: @range,
210
+ radius: @radius,
211
+ inner_angle: @inner_angle,
212
+ outer_angle: @outer_angle,
213
+ shadows_enabled: @shadows_enabled
214
+ }
215
+ end
216
+
217
+ def to_native
218
+ native = Component.new('SpotLight')
219
+ native['color_r'] = @color.r
220
+ native['color_g'] = @color.g
221
+ native['color_b'] = @color.b
222
+ native['color_a'] = @color.a
223
+ native['intensity'] = @intensity
224
+ native['range'] = @range
225
+ native['radius'] = @radius
226
+ native['inner_angle'] = @inner_angle
227
+ native['outer_angle'] = @outer_angle
228
+ native['shadows_enabled'] = @shadows_enabled
229
+ native
230
+ end
231
+
232
+ def self.from_native(native)
233
+ color = Color.rgba(
234
+ native['color_r'] || 1.0,
235
+ native['color_g'] || 1.0,
236
+ native['color_b'] || 1.0,
237
+ native['color_a'] || 1.0
238
+ )
239
+ new(
240
+ color: color,
241
+ intensity: native['intensity'] || 800.0,
242
+ range: native['range'] || 20.0,
243
+ radius: native['radius'] || 0.0,
244
+ inner_angle: native['inner_angle'] || 0.0,
245
+ outer_angle: native['outer_angle'] || Math::PI / 4.0,
246
+ shadows_enabled: native['shadows_enabled'] != false
247
+ )
248
+ end
249
+ end
250
+
251
+ class AmbientLight
252
+ attr_accessor :color, :brightness
253
+
254
+ def initialize(color: nil, brightness: 0.05)
255
+ @color = color || Color.white
256
+ @brightness = brightness.to_f
257
+ end
258
+
259
+ def with_color(color)
260
+ self.class.new(color: color, brightness: @brightness)
261
+ end
262
+
263
+ def with_brightness(brightness)
264
+ self.class.new(color: @color, brightness: brightness)
265
+ end
266
+
267
+ def type_name
268
+ 'AmbientLight'
269
+ end
270
+
271
+ def to_h
272
+ {
273
+ color: @color.to_a,
274
+ brightness: @brightness
275
+ }
276
+ end
277
+
278
+ def to_native
279
+ native = Component.new('AmbientLight')
280
+ native['color_r'] = @color.r
281
+ native['color_g'] = @color.g
282
+ native['color_b'] = @color.b
283
+ native['color_a'] = @color.a
284
+ native['brightness'] = @brightness
285
+ native
286
+ end
287
+
288
+ def self.from_native(native)
289
+ color = Color.rgba(
290
+ native['color_r'] || 1.0,
291
+ native['color_g'] || 1.0,
292
+ native['color_b'] || 1.0,
293
+ native['color_a'] || 1.0
294
+ )
295
+ new(
296
+ color: color,
297
+ brightness: native['brightness'] || 0.05
298
+ )
299
+ end
300
+ end
301
+
302
+ class EnvironmentMapLight
303
+ attr_accessor :diffuse_map, :specular_map, :intensity
304
+
305
+ def initialize(diffuse_map: nil, specular_map: nil, intensity: 1.0)
306
+ @diffuse_map = diffuse_map
307
+ @specular_map = specular_map
308
+ @intensity = intensity.to_f
309
+ end
310
+
311
+ def type_name
312
+ 'EnvironmentMapLight'
313
+ end
314
+
315
+ def to_h
316
+ {
317
+ diffuse_map: @diffuse_map,
318
+ specular_map: @specular_map,
319
+ intensity: @intensity
320
+ }
321
+ end
322
+ end
323
+
324
+ class CascadeShadowConfig
325
+ attr_accessor :num_cascades, :minimum_distance, :maximum_distance, :first_cascade_far_bound, :overlap_proportion
326
+
327
+ def initialize(
328
+ num_cascades: 4,
329
+ minimum_distance: 0.1,
330
+ maximum_distance: 1000.0,
331
+ first_cascade_far_bound: 5.0,
332
+ overlap_proportion: 0.2
333
+ )
334
+ @num_cascades = num_cascades
335
+ @minimum_distance = minimum_distance.to_f
336
+ @maximum_distance = maximum_distance.to_f
337
+ @first_cascade_far_bound = first_cascade_far_bound.to_f
338
+ @overlap_proportion = overlap_proportion.to_f
339
+ end
340
+
341
+ def type_name
342
+ 'CascadeShadowConfig'
343
+ end
344
+
345
+ def to_h
346
+ {
347
+ num_cascades: @num_cascades,
348
+ minimum_distance: @minimum_distance,
349
+ maximum_distance: @maximum_distance,
350
+ first_cascade_far_bound: @first_cascade_far_bound,
351
+ overlap_proportion: @overlap_proportion
352
+ }
353
+ end
354
+ end
355
+
356
+ class LightBundle
357
+ attr_reader :light, :transform, :visibility
358
+
359
+ def initialize(light:, transform: nil, visibility: true)
360
+ @light = light
361
+ @transform = transform || Transform.identity
362
+ @visibility = visibility
363
+ end
364
+
365
+ def type_name
366
+ "#{@light.class.name.split('::').last}Bundle"
367
+ end
368
+ end
369
+ end
@@ -0,0 +1,248 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bevy
4
+ module BlendMode
5
+ OPAQUE = :opaque
6
+ BLEND = :blend
7
+ ALPHA_BLEND = :alpha_blend
8
+ PREMULTIPLIED = :premultiplied
9
+ ADD = :add
10
+ MULTIPLY = :multiply
11
+ end
12
+
13
+ class ColorMaterial
14
+ attr_accessor :color, :alpha_mode
15
+
16
+ def initialize(color = nil, alpha_mode: nil)
17
+ @color = color || Color.white
18
+ @alpha_mode = alpha_mode || (@color.a < 1.0 ? BlendMode::BLEND : BlendMode::OPAQUE)
19
+ end
20
+
21
+ def type_name
22
+ 'ColorMaterial'
23
+ end
24
+
25
+ def self.from_rgb(r, g, b)
26
+ new(Color.new(r, g, b, 1.0))
27
+ end
28
+
29
+ def self.from_rgba(r, g, b, a)
30
+ new(Color.new(r, g, b, a))
31
+ end
32
+
33
+ def with_alpha_mode(mode)
34
+ self.class.new(@color, alpha_mode: mode)
35
+ end
36
+
37
+ def to_native
38
+ native = Component.new('ColorMaterial')
39
+ native['color_r'] = @color.r
40
+ native['color_g'] = @color.g
41
+ native['color_b'] = @color.b
42
+ native['color_a'] = @color.a
43
+ native['alpha_mode'] = @alpha_mode.to_s
44
+ native
45
+ end
46
+
47
+ def to_h
48
+ {
49
+ color: @color.to_a,
50
+ alpha_mode: @alpha_mode
51
+ }
52
+ end
53
+ end
54
+
55
+ class StandardMaterial
56
+ attr_accessor :base_color, :emissive, :metallic, :roughness, :reflectance
57
+ attr_accessor :alpha_mode, :unlit, :double_sided
58
+ attr_accessor :texture_path, :normal_map_path
59
+
60
+ def initialize(
61
+ base_color: nil,
62
+ emissive: nil,
63
+ metallic: 0.0,
64
+ roughness: 0.5,
65
+ reflectance: 0.5,
66
+ alpha_mode: nil,
67
+ unlit: false,
68
+ double_sided: false,
69
+ texture_path: nil,
70
+ normal_map_path: nil
71
+ )
72
+ @base_color = base_color || Color.white
73
+ @emissive = emissive || Color.black
74
+ @metallic = metallic
75
+ @roughness = roughness
76
+ @reflectance = reflectance
77
+ @alpha_mode = alpha_mode || BlendMode::OPAQUE
78
+ @unlit = unlit
79
+ @double_sided = double_sided
80
+ @texture_path = texture_path
81
+ @normal_map_path = normal_map_path
82
+ end
83
+
84
+ def type_name
85
+ 'StandardMaterial'
86
+ end
87
+
88
+ def self.from_color(color)
89
+ new(base_color: color, alpha_mode: color.a < 1.0 ? BlendMode::BLEND : BlendMode::OPAQUE)
90
+ end
91
+
92
+ def with_base_color(color)
93
+ dup.tap { |m| m.base_color = color }
94
+ end
95
+
96
+ def with_emissive(color)
97
+ dup.tap { |m| m.emissive = color }
98
+ end
99
+
100
+ def with_metallic(value)
101
+ dup.tap { |m| m.metallic = value.clamp(0.0, 1.0) }
102
+ end
103
+
104
+ def with_roughness(value)
105
+ dup.tap { |m| m.roughness = value.clamp(0.0, 1.0) }
106
+ end
107
+
108
+ def with_reflectance(value)
109
+ dup.tap { |m| m.reflectance = value.clamp(0.0, 1.0) }
110
+ end
111
+
112
+ def with_alpha_mode(mode)
113
+ dup.tap { |m| m.alpha_mode = mode }
114
+ end
115
+
116
+ def with_unlit(value = true)
117
+ dup.tap { |m| m.unlit = value }
118
+ end
119
+
120
+ def with_double_sided(value = true)
121
+ dup.tap { |m| m.double_sided = value }
122
+ end
123
+
124
+ def with_texture(path)
125
+ dup.tap { |m| m.texture_path = path }
126
+ end
127
+
128
+ def with_normal_map(path)
129
+ dup.tap { |m| m.normal_map_path = path }
130
+ end
131
+
132
+ def to_native
133
+ native = Component.new('StandardMaterial')
134
+ native['base_color_r'] = @base_color.r
135
+ native['base_color_g'] = @base_color.g
136
+ native['base_color_b'] = @base_color.b
137
+ native['base_color_a'] = @base_color.a
138
+ native['emissive_r'] = @emissive.r
139
+ native['emissive_g'] = @emissive.g
140
+ native['emissive_b'] = @emissive.b
141
+ native['metallic'] = @metallic
142
+ native['roughness'] = @roughness
143
+ native['reflectance'] = @reflectance
144
+ native['alpha_mode'] = @alpha_mode.to_s
145
+ native['unlit'] = @unlit
146
+ native['double_sided'] = @double_sided
147
+ native['texture_path'] = @texture_path if @texture_path
148
+ native['normal_map_path'] = @normal_map_path if @normal_map_path
149
+ native
150
+ end
151
+
152
+ def to_h
153
+ {
154
+ base_color: @base_color.to_a,
155
+ emissive: @emissive.to_a,
156
+ metallic: @metallic,
157
+ roughness: @roughness,
158
+ reflectance: @reflectance,
159
+ alpha_mode: @alpha_mode,
160
+ unlit: @unlit,
161
+ double_sided: @double_sided,
162
+ texture_path: @texture_path,
163
+ normal_map_path: @normal_map_path
164
+ }
165
+ end
166
+ end
167
+
168
+ class MaterialBuilder
169
+ def initialize
170
+ @base_color = Color.white
171
+ @emissive = Color.black
172
+ @metallic = 0.0
173
+ @roughness = 0.5
174
+ @reflectance = 0.5
175
+ @alpha_mode = BlendMode::OPAQUE
176
+ @unlit = false
177
+ @double_sided = false
178
+ @texture_path = nil
179
+ @normal_map_path = nil
180
+ end
181
+
182
+ def color(r, g, b, a = 1.0)
183
+ @base_color = Color.new(r, g, b, a)
184
+ @alpha_mode = BlendMode::BLEND if a < 1.0
185
+ self
186
+ end
187
+
188
+ def emissive(r, g, b)
189
+ @emissive = Color.new(r, g, b, 1.0)
190
+ self
191
+ end
192
+
193
+ def metallic(value)
194
+ @metallic = value.clamp(0.0, 1.0)
195
+ self
196
+ end
197
+
198
+ def roughness(value)
199
+ @roughness = value.clamp(0.0, 1.0)
200
+ self
201
+ end
202
+
203
+ def reflectance(value)
204
+ @reflectance = value.clamp(0.0, 1.0)
205
+ self
206
+ end
207
+
208
+ def unlit
209
+ @unlit = true
210
+ self
211
+ end
212
+
213
+ def double_sided
214
+ @double_sided = true
215
+ self
216
+ end
217
+
218
+ def texture(path)
219
+ @texture_path = path
220
+ self
221
+ end
222
+
223
+ def normal_map(path)
224
+ @normal_map_path = path
225
+ self
226
+ end
227
+
228
+ def blend_mode(mode)
229
+ @alpha_mode = mode
230
+ self
231
+ end
232
+
233
+ def build
234
+ StandardMaterial.new(
235
+ base_color: @base_color,
236
+ emissive: @emissive,
237
+ metallic: @metallic,
238
+ roughness: @roughness,
239
+ reflectance: @reflectance,
240
+ alpha_mode: @alpha_mode,
241
+ unlit: @unlit,
242
+ double_sided: @double_sided,
243
+ texture_path: @texture_path,
244
+ normal_map_path: @normal_map_path
245
+ )
246
+ end
247
+ end
248
+ end