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,335 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bevy
4
+ class NetworkResource
5
+ attr_accessor :connected, :client_id
6
+
7
+ def initialize
8
+ @connected = false
9
+ @client_id = nil
10
+ @message_queue = []
11
+ end
12
+
13
+ def connect(address)
14
+ @connected = true
15
+ @client_id = generate_client_id
16
+ end
17
+
18
+ def disconnect
19
+ @connected = false
20
+ @client_id = nil
21
+ end
22
+
23
+ def send_message(message)
24
+ return false unless @connected
25
+
26
+ @message_queue << { type: :outgoing, message: message, timestamp: ::Time.now }
27
+ true
28
+ end
29
+
30
+ def receive_messages
31
+ @message_queue.select { |m| m[:type] == :incoming }.map { |m| m[:message] }
32
+ end
33
+
34
+ def clear_messages
35
+ @message_queue = []
36
+ end
37
+
38
+ def type_name
39
+ 'NetworkResource'
40
+ end
41
+
42
+ private
43
+
44
+ def generate_client_id
45
+ rand(1_000_000..9_999_999)
46
+ end
47
+ end
48
+
49
+ class NetworkMessage
50
+ attr_reader :id, :sender, :payload, :timestamp
51
+ attr_accessor :reliable, :channel
52
+
53
+ def initialize(payload:, sender: nil, reliable: true, channel: 0)
54
+ @id = generate_id
55
+ @sender = sender
56
+ @payload = payload
57
+ @reliable = reliable
58
+ @channel = channel
59
+ @timestamp = ::Time.now
60
+ end
61
+
62
+ def type_name
63
+ 'NetworkMessage'
64
+ end
65
+
66
+ private
67
+
68
+ def generate_id
69
+ rand(1_000_000_000)
70
+ end
71
+ end
72
+
73
+ class NetworkServer
74
+ attr_reader :clients, :port
75
+ attr_accessor :running
76
+
77
+ def initialize(port: 7777)
78
+ @port = port
79
+ @running = false
80
+ @clients = {}
81
+ @message_handlers = {}
82
+ end
83
+
84
+ def start
85
+ @running = true
86
+ end
87
+
88
+ def stop
89
+ @running = false
90
+ @clients = {}
91
+ end
92
+
93
+ def broadcast(message)
94
+ return unless @running
95
+
96
+ @clients.each_value do |client|
97
+ client.send(message)
98
+ end
99
+ end
100
+
101
+ def send_to(client_id, message)
102
+ return unless @running
103
+
104
+ client = @clients[client_id]
105
+ client&.send(message)
106
+ end
107
+
108
+ def on_message(message_type, &handler)
109
+ @message_handlers[message_type] = handler
110
+ end
111
+
112
+ def client_count
113
+ @clients.size
114
+ end
115
+
116
+ def type_name
117
+ 'NetworkServer'
118
+ end
119
+ end
120
+
121
+ class NetworkClient
122
+ attr_reader :server_address, :client_id
123
+ attr_accessor :connected
124
+
125
+ def initialize
126
+ @connected = false
127
+ @server_address = nil
128
+ @client_id = nil
129
+ @message_queue = []
130
+ end
131
+
132
+ def connect(address)
133
+ @server_address = address
134
+ @connected = true
135
+ @client_id = rand(1_000_000)
136
+ end
137
+
138
+ def disconnect
139
+ @connected = false
140
+ @server_address = nil
141
+ end
142
+
143
+ def send_message(message)
144
+ return false unless @connected
145
+
146
+ @message_queue << { direction: :out, message: message }
147
+ true
148
+ end
149
+
150
+ def poll_messages
151
+ incoming = @message_queue.select { |m| m[:direction] == :in }
152
+ incoming.map { |m| m[:message] }
153
+ end
154
+
155
+ def type_name
156
+ 'NetworkClient'
157
+ end
158
+ end
159
+
160
+ class Replication
161
+ attr_reader :replicated_components
162
+
163
+ def initialize
164
+ @replicated_components = {}
165
+ end
166
+
167
+ def register(component_type, options = {})
168
+ @replicated_components[component_type] = {
169
+ priority: options[:priority] || 0,
170
+ interpolate: options[:interpolate] || false,
171
+ owner_only: options[:owner_only] || false
172
+ }
173
+ self
174
+ end
175
+
176
+ def is_replicated?(component_type)
177
+ @replicated_components.key?(component_type)
178
+ end
179
+
180
+ def type_name
181
+ 'Replication'
182
+ end
183
+ end
184
+
185
+ class NetworkedEntity
186
+ attr_accessor :network_id, :owner_id, :authority
187
+
188
+ AUTHORITY_SERVER = :server
189
+ AUTHORITY_CLIENT = :client
190
+
191
+ def initialize(network_id: nil, owner_id: nil, authority: AUTHORITY_SERVER)
192
+ @network_id = network_id || rand(1_000_000_000)
193
+ @owner_id = owner_id
194
+ @authority = authority
195
+ end
196
+
197
+ def server_authority?
198
+ @authority == AUTHORITY_SERVER
199
+ end
200
+
201
+ def client_authority?
202
+ @authority == AUTHORITY_CLIENT
203
+ end
204
+
205
+ def owned_by?(client_id)
206
+ @owner_id == client_id
207
+ end
208
+
209
+ def type_name
210
+ 'NetworkedEntity'
211
+ end
212
+ end
213
+
214
+ class NetworkTransform
215
+ attr_accessor :position, :rotation, :velocity
216
+ attr_accessor :interpolation_speed, :sync_rate
217
+
218
+ def initialize(sync_rate: 20.0, interpolation_speed: 10.0)
219
+ @position = Vec3.zero
220
+ @rotation = Quat.identity
221
+ @velocity = Vec3.zero
222
+ @sync_rate = sync_rate.to_f
223
+ @interpolation_speed = interpolation_speed.to_f
224
+ @target_position = nil
225
+ @target_rotation = nil
226
+ end
227
+
228
+ def set_target(position:, rotation: nil)
229
+ @target_position = position
230
+ @target_rotation = rotation
231
+ end
232
+
233
+ def interpolate(delta)
234
+ return unless @target_position
235
+
236
+ t = [@interpolation_speed * delta, 1.0].min
237
+ @position = Vec3.new(
238
+ @position.x + (@target_position.x - @position.x) * t,
239
+ @position.y + (@target_position.y - @position.y) * t,
240
+ @position.z + (@target_position.z - @position.z) * t
241
+ )
242
+ end
243
+
244
+ def type_name
245
+ 'NetworkTransform'
246
+ end
247
+ end
248
+
249
+ class Rpc
250
+ attr_reader :name, :target, :reliable
251
+
252
+ TARGET_SERVER = :server
253
+ TARGET_CLIENT = :client
254
+ TARGET_ALL = :all
255
+
256
+ def initialize(name:, target: TARGET_SERVER, reliable: true)
257
+ @name = name
258
+ @target = target
259
+ @reliable = reliable
260
+ end
261
+
262
+ def server_rpc?
263
+ @target == TARGET_SERVER
264
+ end
265
+
266
+ def client_rpc?
267
+ @target == TARGET_CLIENT
268
+ end
269
+
270
+ def type_name
271
+ 'Rpc'
272
+ end
273
+ end
274
+
275
+ class NetworkEvent
276
+ attr_reader :event_type, :data, :timestamp
277
+
278
+ CONNECTED = :connected
279
+ DISCONNECTED = :disconnected
280
+ MESSAGE_RECEIVED = :message_received
281
+ CLIENT_CONNECTED = :client_connected
282
+ CLIENT_DISCONNECTED = :client_disconnected
283
+
284
+ def initialize(event_type:, data: nil)
285
+ @event_type = event_type
286
+ @data = data
287
+ @timestamp = ::Time.now
288
+ end
289
+
290
+ def type_name
291
+ 'NetworkEvent'
292
+ end
293
+ end
294
+
295
+ class Lobby
296
+ attr_reader :id, :name, :players, :max_players, :host_id
297
+
298
+ def initialize(name:, max_players: 8)
299
+ @id = rand(1_000_000)
300
+ @name = name
301
+ @max_players = max_players
302
+ @players = []
303
+ @host_id = nil
304
+ end
305
+
306
+ def join(player_id)
307
+ return false if full?
308
+
309
+ @players << player_id
310
+ @host_id ||= player_id
311
+ true
312
+ end
313
+
314
+ def leave(player_id)
315
+ @players.delete(player_id)
316
+ @host_id = @players.first if player_id == @host_id
317
+ end
318
+
319
+ def full?
320
+ @players.size >= @max_players
321
+ end
322
+
323
+ def player_count
324
+ @players.size
325
+ end
326
+
327
+ def host?(player_id)
328
+ @host_id == player_id
329
+ end
330
+
331
+ def type_name
332
+ 'Lobby'
333
+ end
334
+ end
335
+ end
@@ -0,0 +1,337 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bevy
4
+ class Particle
5
+ attr_accessor :position, :velocity, :acceleration
6
+ attr_accessor :lifetime, :age, :size, :rotation, :color
7
+ attr_accessor :alive
8
+
9
+ def initialize(
10
+ position: nil,
11
+ velocity: nil,
12
+ lifetime: 1.0,
13
+ size: 1.0,
14
+ color: nil
15
+ )
16
+ @position = position || Vec3.zero
17
+ @velocity = velocity || Vec3.zero
18
+ @acceleration = Vec3.zero
19
+ @lifetime = lifetime.to_f
20
+ @age = 0.0
21
+ @size = size.to_f
22
+ @rotation = 0.0
23
+ @color = color || Color.white
24
+ @alive = true
25
+ end
26
+
27
+ def update(delta)
28
+ return unless @alive
29
+
30
+ @age += delta
31
+ if @age >= @lifetime
32
+ @alive = false
33
+ return
34
+ end
35
+
36
+ @velocity = Vec3.new(
37
+ @velocity.x + @acceleration.x * delta,
38
+ @velocity.y + @acceleration.y * delta,
39
+ @velocity.z + @acceleration.z * delta
40
+ )
41
+
42
+ @position = Vec3.new(
43
+ @position.x + @velocity.x * delta,
44
+ @position.y + @velocity.y * delta,
45
+ @position.z + @velocity.z * delta
46
+ )
47
+ end
48
+
49
+ def progress
50
+ return 1.0 if @lifetime <= 0
51
+
52
+ (@age / @lifetime).clamp(0.0, 1.0)
53
+ end
54
+
55
+ def remaining_lifetime
56
+ [@lifetime - @age, 0.0].max
57
+ end
58
+
59
+ def type_name
60
+ 'Particle'
61
+ end
62
+ end
63
+
64
+ class ParticleEmitter
65
+ attr_accessor :position, :rate, :lifetime, :speed
66
+ attr_accessor :direction, :spread, :gravity
67
+ attr_accessor :start_size, :end_size
68
+ attr_accessor :start_color, :end_color
69
+ attr_accessor :max_particles, :enabled
70
+
71
+ def initialize(
72
+ position: nil,
73
+ rate: 10.0,
74
+ lifetime: 1.0,
75
+ speed: 100.0,
76
+ direction: nil,
77
+ spread: Math::PI / 4.0,
78
+ gravity: nil,
79
+ start_size: 10.0,
80
+ end_size: 0.0,
81
+ start_color: nil,
82
+ end_color: nil,
83
+ max_particles: 1000
84
+ )
85
+ @position = position || Vec3.zero
86
+ @rate = rate.to_f
87
+ @lifetime = lifetime.to_f
88
+ @speed = speed.to_f
89
+ @direction = direction || Vec3.new(0.0, 1.0, 0.0)
90
+ @spread = spread.to_f
91
+ @gravity = gravity || Vec3.new(0.0, -100.0, 0.0)
92
+ @start_size = start_size.to_f
93
+ @end_size = end_size.to_f
94
+ @start_color = start_color || Color.white
95
+ @end_color = end_color || Color.rgba(1.0, 1.0, 1.0, 0.0)
96
+ @max_particles = max_particles
97
+ @enabled = true
98
+ @emission_accumulator = 0.0
99
+ end
100
+
101
+ def emit_count(delta)
102
+ return 0 unless @enabled
103
+
104
+ @emission_accumulator += @rate * delta
105
+ count = @emission_accumulator.floor
106
+ @emission_accumulator -= count
107
+ count
108
+ end
109
+
110
+ def spawn_particle
111
+ angle = rand * @spread - @spread / 2.0
112
+ cos_a = Math.cos(angle)
113
+ sin_a = Math.sin(angle)
114
+
115
+ vel = Vec3.new(
116
+ @direction.x * cos_a - @direction.y * sin_a,
117
+ @direction.x * sin_a + @direction.y * cos_a,
118
+ @direction.z
119
+ )
120
+
121
+ speed_variance = @speed * (0.8 + rand * 0.4)
122
+ vel = Vec3.new(
123
+ vel.x * speed_variance,
124
+ vel.y * speed_variance,
125
+ vel.z * speed_variance
126
+ )
127
+
128
+ lifetime_variance = @lifetime * (0.8 + rand * 0.4)
129
+
130
+ Particle.new(
131
+ position: Vec3.new(@position.x, @position.y, @position.z),
132
+ velocity: vel,
133
+ lifetime: lifetime_variance,
134
+ size: @start_size,
135
+ color: @start_color
136
+ )
137
+ end
138
+
139
+ def type_name
140
+ 'ParticleEmitter'
141
+ end
142
+ end
143
+
144
+ class ParticleSystem
145
+ attr_reader :particles, :emitter
146
+
147
+ def initialize(emitter: nil)
148
+ @emitter = emitter || ParticleEmitter.new
149
+ @particles = []
150
+ end
151
+
152
+ def update(delta)
153
+ @particles.each do |particle|
154
+ particle.acceleration = @emitter.gravity
155
+ particle.update(delta)
156
+
157
+ if particle.alive
158
+ t = particle.progress
159
+ particle.size = lerp(@emitter.start_size, @emitter.end_size, t)
160
+ particle.color = lerp_color(@emitter.start_color, @emitter.end_color, t)
161
+ end
162
+ end
163
+
164
+ @particles.reject! { |p| !p.alive }
165
+
166
+ spawn_count = @emitter.emit_count(delta)
167
+ spawn_count.times do
168
+ break if @particles.size >= @emitter.max_particles
169
+
170
+ @particles << @emitter.spawn_particle
171
+ end
172
+ end
173
+
174
+ def active_count
175
+ @particles.size
176
+ end
177
+
178
+ def clear
179
+ @particles.clear
180
+ end
181
+
182
+ def burst(count)
183
+ count.times do
184
+ break if @particles.size >= @emitter.max_particles
185
+
186
+ @particles << @emitter.spawn_particle
187
+ end
188
+ end
189
+
190
+ def type_name
191
+ 'ParticleSystem'
192
+ end
193
+
194
+ private
195
+
196
+ def lerp(a, b, t)
197
+ a + (b - a) * t
198
+ end
199
+
200
+ def lerp_color(a, b, t)
201
+ Color.rgba(
202
+ lerp(a.r, b.r, t),
203
+ lerp(a.g, b.g, t),
204
+ lerp(a.b, b.b, t),
205
+ lerp(a.a, b.a, t)
206
+ )
207
+ end
208
+ end
209
+
210
+ class ParticleBundle
211
+ attr_reader :particle_system, :transform
212
+
213
+ def initialize(emitter: nil, transform: nil)
214
+ @particle_system = ParticleSystem.new(emitter: emitter)
215
+ @transform = transform || Transform.identity
216
+ end
217
+
218
+ def type_name
219
+ 'ParticleBundle'
220
+ end
221
+ end
222
+
223
+ module EmitterShape
224
+ POINT = :point
225
+ CIRCLE = :circle
226
+ RECTANGLE = :rectangle
227
+ SPHERE = :sphere
228
+ CONE = :cone
229
+ end
230
+
231
+ class ShapeEmitter
232
+ attr_accessor :shape, :radius, :width, :height, :depth, :angle
233
+
234
+ def initialize(shape: EmitterShape::POINT, radius: 0.0, width: 0.0, height: 0.0, depth: 0.0, angle: 0.0)
235
+ @shape = shape
236
+ @radius = radius.to_f
237
+ @width = width.to_f
238
+ @height = height.to_f
239
+ @depth = depth.to_f
240
+ @angle = angle.to_f
241
+ end
242
+
243
+ def sample_position(center)
244
+ case @shape
245
+ when EmitterShape::POINT
246
+ center
247
+ when EmitterShape::CIRCLE
248
+ angle = rand * 2.0 * Math::PI
249
+ r = Math.sqrt(rand) * @radius
250
+ Vec3.new(
251
+ center.x + r * Math.cos(angle),
252
+ center.y + r * Math.sin(angle),
253
+ center.z
254
+ )
255
+ when EmitterShape::RECTANGLE
256
+ Vec3.new(
257
+ center.x + (rand - 0.5) * @width,
258
+ center.y + (rand - 0.5) * @height,
259
+ center.z
260
+ )
261
+ when EmitterShape::SPHERE
262
+ theta = rand * 2.0 * Math::PI
263
+ phi = Math.acos(2.0 * rand - 1.0)
264
+ r = (rand**(1.0 / 3.0)) * @radius
265
+ Vec3.new(
266
+ center.x + r * Math.sin(phi) * Math.cos(theta),
267
+ center.y + r * Math.sin(phi) * Math.sin(theta),
268
+ center.z + r * Math.cos(phi)
269
+ )
270
+ else
271
+ center
272
+ end
273
+ end
274
+
275
+ def type_name
276
+ 'ShapeEmitter'
277
+ end
278
+ end
279
+
280
+ class ParticleEffect
281
+ attr_reader :name, :emitter_settings, :duration, :looping
282
+
283
+ def initialize(name:, emitter_settings: nil, duration: Float::INFINITY, looping: true)
284
+ @name = name
285
+ @emitter_settings = emitter_settings || {}
286
+ @duration = duration.to_f
287
+ @looping = looping
288
+ end
289
+
290
+ def build_emitter
291
+ ParticleEmitter.new(**@emitter_settings)
292
+ end
293
+
294
+ def type_name
295
+ 'ParticleEffect'
296
+ end
297
+ end
298
+
299
+ class ParticleEffectInstance
300
+ attr_reader :effect, :elapsed, :finished
301
+
302
+ def initialize(effect)
303
+ @effect = effect
304
+ @elapsed = 0.0
305
+ @finished = false
306
+ @system = ParticleSystem.new(emitter: effect.build_emitter)
307
+ end
308
+
309
+ def update(delta)
310
+ return if @finished
311
+
312
+ @elapsed += delta
313
+ @system.update(delta)
314
+
315
+ if @elapsed >= @effect.duration
316
+ if @effect.looping
317
+ @elapsed = 0.0
318
+ else
319
+ @system.emitter.enabled = false
320
+ @finished = true if @system.active_count.zero?
321
+ end
322
+ end
323
+ end
324
+
325
+ def particles
326
+ @system.particles
327
+ end
328
+
329
+ def active_count
330
+ @system.active_count
331
+ end
332
+
333
+ def type_name
334
+ 'ParticleEffectInstance'
335
+ end
336
+ end
337
+ end