1 /*************************************************************************/
2 /*  particles.cpp                                                        */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 #include "particles.h"
31 #include "scene/resources/surface_tool.h"
32 #include "servers/visual_server.h"
33 
34 /*
35 static const char* _var_names[Particles::VAR_MAX]={
36 	"vars/lifetime",
37 	"vars/spread",
38 	"vars/gravity",
39 	"vars/linear_vel",
40 	"vars/angular_vel",
41 	"vars/linear_accel",
42 	"vars/radial_accel",
43 	"vars/tan_accel",
44 	"vars/initial_size",
45 	"vars/final_size",
46 	"vars/initial_angle",
47 	"vars/height",
48 	"vars/height_speed_scale",
49 };
50 */
51 static const char *_rand_names[Particles::VAR_MAX] = {
52 	"rand/lifetime",
53 	"rand/spread",
54 	"rand/gravity",
55 	"rand/linear_vel",
56 	"rand/angular_vel",
57 	"rand/linear_accel",
58 	"rand/radial_accel",
59 	"rand/tan_accel",
60 	"rand/damping",
61 	"rand/initial_size",
62 	"rand/final_size",
63 	"rand/initial_angle",
64 	"rand/height",
65 	"rand/height_speed_scale",
66 };
67 
68 static const Particles::Variable _var_indices[Particles::VAR_MAX] = {
69 	Particles::VAR_LIFETIME,
70 	Particles::VAR_SPREAD,
71 	Particles::VAR_GRAVITY,
72 	Particles::VAR_LINEAR_VELOCITY,
73 	Particles::VAR_ANGULAR_VELOCITY,
74 	Particles::VAR_LINEAR_ACCELERATION,
75 	Particles::VAR_DRAG,
76 	Particles::VAR_TANGENTIAL_ACCELERATION,
77 	Particles::VAR_DAMPING,
78 	Particles::VAR_INITIAL_SIZE,
79 	Particles::VAR_FINAL_SIZE,
80 	Particles::VAR_INITIAL_ANGLE,
81 	Particles::VAR_HEIGHT,
82 	Particles::VAR_HEIGHT_SPEED_SCALE,
83 };
84 
get_aabb() const85 AABB Particles::get_aabb() const {
86 
87 	return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
88 }
get_faces(uint32_t p_usage_flags) const89 DVector<Face3> Particles::get_faces(uint32_t p_usage_flags) const {
90 
91 	return DVector<Face3>();
92 }
93 
set_amount(int p_amount)94 void Particles::set_amount(int p_amount) {
95 
96 	ERR_FAIL_INDEX(p_amount, 1024);
97 	amount = p_amount;
98 	VisualServer::get_singleton()->particles_set_amount(particles, p_amount);
99 }
get_amount() const100 int Particles::get_amount() const {
101 
102 	return amount;
103 }
104 
set_emitting(bool p_emitting)105 void Particles::set_emitting(bool p_emitting) {
106 
107 	emitting = p_emitting;
108 	VisualServer::get_singleton()->particles_set_emitting(particles, p_emitting);
109 
110 	setup_timer();
111 }
is_emitting() const112 bool Particles::is_emitting() const {
113 
114 	return emitting;
115 }
116 
set_visibility_aabb(const AABB & p_aabb)117 void Particles::set_visibility_aabb(const AABB &p_aabb) {
118 
119 	visibility_aabb = p_aabb;
120 	VisualServer::get_singleton()->particles_set_visibility_aabb(particles, p_aabb);
121 	update_gizmo();
122 }
get_visibility_aabb() const123 AABB Particles::get_visibility_aabb() const {
124 
125 	return visibility_aabb;
126 }
127 
set_emission_points(const DVector<Vector3> & p_points)128 void Particles::set_emission_points(const DVector<Vector3> &p_points) {
129 
130 	using_points = p_points.size();
131 	VisualServer::get_singleton()->particles_set_emission_points(particles, p_points);
132 }
133 
get_emission_points() const134 DVector<Vector3> Particles::get_emission_points() const {
135 
136 	if (!using_points)
137 		return DVector<Vector3>();
138 
139 	return VisualServer::get_singleton()->particles_get_emission_points(particles);
140 }
141 
set_emission_half_extents(const Vector3 & p_half_extents)142 void Particles::set_emission_half_extents(const Vector3 &p_half_extents) {
143 
144 	emission_half_extents = p_half_extents;
145 	VisualServer::get_singleton()->particles_set_emission_half_extents(particles, p_half_extents);
146 }
147 
get_emission_half_extents() const148 Vector3 Particles::get_emission_half_extents() const {
149 
150 	return emission_half_extents;
151 }
152 
set_emission_base_velocity(const Vector3 & p_base_velocity)153 void Particles::set_emission_base_velocity(const Vector3 &p_base_velocity) {
154 
155 	emission_base_velocity = p_base_velocity;
156 	VisualServer::get_singleton()->particles_set_emission_base_velocity(particles, p_base_velocity);
157 }
158 
get_emission_base_velocity() const159 Vector3 Particles::get_emission_base_velocity() const {
160 
161 	return emission_base_velocity;
162 }
163 
set_gravity_normal(const Vector3 & p_normal)164 void Particles::set_gravity_normal(const Vector3 &p_normal) {
165 
166 	gravity_normal = p_normal;
167 	VisualServer::get_singleton()->particles_set_gravity_normal(particles, p_normal);
168 }
169 
get_gravity_normal() const170 Vector3 Particles::get_gravity_normal() const {
171 
172 	return gravity_normal;
173 }
174 
set_variable(Variable p_variable,float p_value)175 void Particles::set_variable(Variable p_variable, float p_value) {
176 
177 	ERR_FAIL_INDEX(p_variable, VAR_MAX);
178 	var[p_variable] = p_value;
179 	VisualServer::get_singleton()->particles_set_variable(particles, (VS::ParticleVariable)p_variable, p_value);
180 	if (p_variable == VAR_SPREAD)
181 		update_gizmo();
182 }
183 
get_variable(Variable p_variable) const184 float Particles::get_variable(Variable p_variable) const {
185 
186 	ERR_FAIL_INDEX_V(p_variable, VAR_MAX, -1);
187 	return var[p_variable];
188 }
189 
set_randomness(Variable p_variable,float p_randomness)190 void Particles::set_randomness(Variable p_variable, float p_randomness) {
191 
192 	ERR_FAIL_INDEX(p_variable, VAR_MAX);
193 	var_random[p_variable] = p_randomness;
194 	VisualServer::get_singleton()->particles_set_randomness(particles, (VS::ParticleVariable)p_variable, p_randomness);
195 }
get_randomness(Variable p_variable) const196 float Particles::get_randomness(Variable p_variable) const {
197 
198 	ERR_FAIL_INDEX_V(p_variable, VAR_MAX, -1);
199 	return var_random[p_variable];
200 }
201 
set_color_phase_pos(int p_phase,float p_pos)202 void Particles::set_color_phase_pos(int p_phase, float p_pos) {
203 
204 	ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES);
205 	color_phase[p_phase].pos = p_pos;
206 	VisualServer::get_singleton()->particles_set_color_phase_pos(particles, p_phase, p_pos);
207 }
get_color_phase_pos(int p_phase) const208 float Particles::get_color_phase_pos(int p_phase) const {
209 
210 	ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, -1);
211 	return color_phase[p_phase].pos;
212 }
213 
set_color_phase_color(int p_phase,const Color & p_color)214 void Particles::set_color_phase_color(int p_phase, const Color &p_color) {
215 
216 	ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES);
217 	color_phase[p_phase].color = p_color;
218 	VisualServer::get_singleton()->particles_set_color_phase_color(particles, p_phase, p_color);
219 }
get_color_phase_color(int p_phase) const220 Color Particles::get_color_phase_color(int p_phase) const {
221 
222 	ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, Color());
223 	return color_phase[p_phase].color;
224 }
225 
set_material(const Ref<Material> & p_material)226 void Particles::set_material(const Ref<Material> &p_material) {
227 
228 	material = p_material;
229 	if (material.is_null()) {
230 		VisualServer::get_singleton()->particles_set_material(particles, RID());
231 	} else {
232 		VisualServer::get_singleton()->particles_set_material(particles, material->get_rid());
233 	}
234 }
235 
setup_timer()236 void Particles::setup_timer() {
237 
238 	if (emitting && emit_timeout > 0) {
239 
240 		timer->set_wait_time(emit_timeout);
241 		timer->start();
242 		timer->set_one_shot(true);
243 	};
244 };
245 
set_emit_timeout(float p_timeout)246 void Particles::set_emit_timeout(float p_timeout) {
247 
248 	emit_timeout = p_timeout;
249 	setup_timer();
250 };
251 
get_emit_timeout() const252 float Particles::get_emit_timeout() const {
253 
254 	return emit_timeout;
255 };
256 
get_material() const257 Ref<Material> Particles::get_material() const {
258 
259 	return material;
260 }
261 
set_height_from_velocity(bool p_enable)262 void Particles::set_height_from_velocity(bool p_enable) {
263 
264 	height_from_velocity = p_enable;
265 	VisualServer::get_singleton()->particles_set_height_from_velocity(particles, height_from_velocity);
266 }
267 
has_height_from_velocity() const268 bool Particles::has_height_from_velocity() const {
269 
270 	return height_from_velocity;
271 }
272 
set_color_phases(int p_phases)273 void Particles::set_color_phases(int p_phases) {
274 
275 	color_phase_count = p_phases;
276 	VisualServer::get_singleton()->particles_set_color_phases(particles, p_phases);
277 }
278 
get_color_phases() const279 int Particles::get_color_phases() const {
280 
281 	return color_phase_count;
282 }
283 
_can_gizmo_scale() const284 bool Particles::_can_gizmo_scale() const {
285 
286 	return false;
287 }
288 
set_use_local_coordinates(bool p_use)289 void Particles::set_use_local_coordinates(bool p_use) {
290 
291 	local_coordinates = p_use;
292 	VisualServer::get_singleton()->particles_set_use_local_coordinates(particles, local_coordinates);
293 }
294 
is_using_local_coordinates() const295 bool Particles::is_using_local_coordinates() const {
296 
297 	return local_coordinates;
298 }
299 
_get_gizmo_geometry() const300 RES Particles::_get_gizmo_geometry() const {
301 
302 	Ref<SurfaceTool> surface_tool(memnew(SurfaceTool));
303 
304 	Ref<FixedMaterial> mat(memnew(FixedMaterial));
305 
306 	mat->set_parameter(FixedMaterial::PARAM_DIFFUSE, Color(0.0, 0.6, 0.7, 0.2));
307 	mat->set_parameter(FixedMaterial::PARAM_EMISSION, Color(0.5, 0.7, 0.8));
308 	mat->set_blend_mode(Material::BLEND_MODE_ADD);
309 	mat->set_flag(Material::FLAG_DOUBLE_SIDED, true);
310 	//	mat->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
311 
312 	surface_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
313 	surface_tool->set_material(mat);
314 
315 	int sides = 16;
316 	int sections = 24;
317 
318 	//	float len=1;
319 	float deg = Math::deg2rad(var[VAR_SPREAD] * 180);
320 	if (deg == 180)
321 		deg = 179.5;
322 
323 	Vector3 to = Vector3(0, 0, -1);
324 
325 	for (int j = 0; j < sections; j++) {
326 
327 		Vector3 p1 = Matrix3(Vector3(1, 0, 0), deg * j / sections).xform(to);
328 		Vector3 p2 = Matrix3(Vector3(1, 0, 0), deg * (j + 1) / sections).xform(to);
329 
330 		for (int i = 0; i < sides; i++) {
331 
332 			Vector3 p1r = Matrix3(Vector3(0, 0, 1), Math_PI * 2 * float(i) / sides).xform(p1);
333 			Vector3 p1s = Matrix3(Vector3(0, 0, 1), Math_PI * 2 * float(i + 1) / sides).xform(p1);
334 			Vector3 p2s = Matrix3(Vector3(0, 0, 1), Math_PI * 2 * float(i + 1) / sides).xform(p2);
335 			Vector3 p2r = Matrix3(Vector3(0, 0, 1), Math_PI * 2 * float(i) / sides).xform(p2);
336 
337 			surface_tool->add_normal(p1r.normalized());
338 			surface_tool->add_vertex(p1r);
339 			surface_tool->add_normal(p1s.normalized());
340 			surface_tool->add_vertex(p1s);
341 			surface_tool->add_normal(p2s.normalized());
342 			surface_tool->add_vertex(p2s);
343 
344 			surface_tool->add_normal(p1r.normalized());
345 			surface_tool->add_vertex(p1r);
346 			surface_tool->add_normal(p2s.normalized());
347 			surface_tool->add_vertex(p2s);
348 			surface_tool->add_normal(p2r.normalized());
349 			surface_tool->add_vertex(p2r);
350 
351 			if (j == sections - 1) {
352 
353 				surface_tool->add_normal(p2r.normalized());
354 				surface_tool->add_vertex(p2r);
355 				surface_tool->add_normal(p2s.normalized());
356 				surface_tool->add_vertex(p2s);
357 				surface_tool->add_normal(Vector3(0, 0, 1));
358 				surface_tool->add_vertex(Vector3());
359 			}
360 		}
361 	}
362 
363 	Ref<Mesh> mesh = surface_tool->commit();
364 
365 	Ref<FixedMaterial> mat_aabb(memnew(FixedMaterial));
366 
367 	mat_aabb->set_parameter(FixedMaterial::PARAM_DIFFUSE, Color(0.8, 0.8, 0.9, 0.7));
368 	mat_aabb->set_line_width(3);
369 	mat_aabb->set_flag(Material::FLAG_UNSHADED, true);
370 
371 	surface_tool->begin(Mesh::PRIMITIVE_LINES);
372 	surface_tool->set_material(mat_aabb);
373 
374 	for (int i = 0; i < 12; i++) {
375 
376 		Vector3 f, t;
377 		visibility_aabb.get_edge(i, f, t);
378 		surface_tool->add_vertex(f);
379 		surface_tool->add_vertex(t);
380 	}
381 
382 	return surface_tool->commit(mesh);
383 }
384 
_bind_methods()385 void Particles::_bind_methods() {
386 
387 	ObjectTypeDB::bind_method(_MD("set_amount", "amount"), &Particles::set_amount);
388 	ObjectTypeDB::bind_method(_MD("get_amount"), &Particles::get_amount);
389 	ObjectTypeDB::bind_method(_MD("set_emitting", "enabled"), &Particles::set_emitting);
390 	ObjectTypeDB::bind_method(_MD("is_emitting"), &Particles::is_emitting);
391 	ObjectTypeDB::bind_method(_MD("set_visibility_aabb", "aabb"), &Particles::set_visibility_aabb);
392 	ObjectTypeDB::bind_method(_MD("get_visibility_aabb"), &Particles::get_visibility_aabb);
393 	ObjectTypeDB::bind_method(_MD("set_emission_half_extents", "half_extents"), &Particles::set_emission_half_extents);
394 	ObjectTypeDB::bind_method(_MD("get_emission_half_extents"), &Particles::get_emission_half_extents);
395 	ObjectTypeDB::bind_method(_MD("set_emission_base_velocity", "base_velocity"), &Particles::set_emission_base_velocity);
396 	ObjectTypeDB::bind_method(_MD("get_emission_base_velocity"), &Particles::get_emission_base_velocity);
397 	ObjectTypeDB::bind_method(_MD("set_emission_points", "points"), &Particles::set_emission_points);
398 	ObjectTypeDB::bind_method(_MD("get_emission_points"), &Particles::get_emission_points);
399 	ObjectTypeDB::bind_method(_MD("set_gravity_normal", "normal"), &Particles::set_gravity_normal);
400 	ObjectTypeDB::bind_method(_MD("get_gravity_normal"), &Particles::get_gravity_normal);
401 	ObjectTypeDB::bind_method(_MD("set_variable", "variable", "value"), &Particles::set_variable);
402 	ObjectTypeDB::bind_method(_MD("get_variable", "variable"), &Particles::get_variable);
403 	ObjectTypeDB::bind_method(_MD("set_randomness", "variable", "randomness"), &Particles::set_randomness);
404 	ObjectTypeDB::bind_method(_MD("get_randomness", "variable"), &Particles::get_randomness);
405 	ObjectTypeDB::bind_method(_MD("set_color_phase_pos", "phase", "pos"), &Particles::set_color_phase_pos);
406 	ObjectTypeDB::bind_method(_MD("get_color_phase_pos", "phase"), &Particles::get_color_phase_pos);
407 	ObjectTypeDB::bind_method(_MD("set_color_phase_color", "phase", "color"), &Particles::set_color_phase_color);
408 	ObjectTypeDB::bind_method(_MD("get_color_phase_color", "phase"), &Particles::get_color_phase_color);
409 	ObjectTypeDB::bind_method(_MD("set_material", "material:Material"), &Particles::set_material);
410 	ObjectTypeDB::bind_method(_MD("get_material:Material"), &Particles::get_material);
411 	ObjectTypeDB::bind_method(_MD("set_emit_timeout", "timeout"), &Particles::set_emit_timeout);
412 	ObjectTypeDB::bind_method(_MD("get_emit_timeout"), &Particles::get_emit_timeout);
413 	ObjectTypeDB::bind_method(_MD("set_height_from_velocity", "enable"), &Particles::set_height_from_velocity);
414 	ObjectTypeDB::bind_method(_MD("has_height_from_velocity"), &Particles::has_height_from_velocity);
415 	ObjectTypeDB::bind_method(_MD("set_use_local_coordinates", "enable"), &Particles::set_use_local_coordinates);
416 	ObjectTypeDB::bind_method(_MD("is_using_local_coordinates"), &Particles::is_using_local_coordinates);
417 
418 	ObjectTypeDB::bind_method(_MD("set_color_phases", "count"), &Particles::set_color_phases);
419 	ObjectTypeDB::bind_method(_MD("get_color_phases"), &Particles::get_color_phases);
420 
421 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "Material"), _SCS("set_material"), _SCS("get_material"));
422 
423 	ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1024,1"), _SCS("set_amount"), _SCS("get_amount"));
424 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), _SCS("set_emitting"), _SCS("is_emitting"));
425 	ADD_PROPERTY(PropertyInfo(Variant::_AABB, "visibility"), _SCS("set_visibility_aabb"), _SCS("get_visibility_aabb"));
426 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_extents"), _SCS("set_emission_half_extents"), _SCS("get_emission_half_extents"));
427 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_base_velocity"), _SCS("set_emission_base_velocity"), _SCS("get_emission_base_velocity"));
428 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3_ARRAY, "emission_points"), _SCS("set_emission_points"), _SCS("get_emission_points"));
429 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_normal"), _SCS("set_gravity_normal"), _SCS("get_gravity_normal"));
430 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), _SCS("set_use_local_coordinates"), _SCS("is_using_local_coordinates"));
431 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "emit_timeout", PROPERTY_HINT_RANGE, "0,256,0.01"), _SCS("set_emit_timeout"), _SCS("get_emit_timeout"));
432 
433 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/lifetime", PROPERTY_HINT_RANGE, "0.1,60,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_LIFETIME);
434 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/spread", PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_SPREAD);
435 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/gravity", PROPERTY_HINT_RANGE, "-48,48,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_GRAVITY);
436 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/linear_vel", PROPERTY_HINT_RANGE, "-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_LINEAR_VELOCITY);
437 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/angular_vel", PROPERTY_HINT_RANGE, "-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_ANGULAR_VELOCITY);
438 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_LINEAR_ACCELERATION);
439 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/radial_accel", PROPERTY_HINT_RANGE, "-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_DRAG);
440 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/tan_accel", PROPERTY_HINT_RANGE, "-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_TANGENTIAL_ACCELERATION);
441 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/damping", PROPERTY_HINT_RANGE, "0,128,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_DAMPING);
442 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/initial_size", PROPERTY_HINT_RANGE, "0,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_INITIAL_SIZE);
443 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/final_size", PROPERTY_HINT_RANGE, "0,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_FINAL_SIZE);
444 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/initial_angle", PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_INITIAL_ANGLE);
445 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vars/height_from_velocity"), _SCS("set_height_from_velocity"), _SCS("has_height_from_velocity"));
446 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/height", PROPERTY_HINT_RANGE, "0,4096,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_HEIGHT);
447 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "vars/height_speed_scale", PROPERTY_HINT_RANGE, "0,4096,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_HEIGHT_SPEED_SCALE);
448 
449 	for (int i = 0; i < VAR_MAX; i++)
450 		ADD_PROPERTYI(PropertyInfo(Variant::REAL, _rand_names[i], PROPERTY_HINT_RANGE, "-16.0,16.0,0.01"), _SCS("set_randomness"), _SCS("get_randomness"), _var_indices[i]);
451 
452 	ADD_PROPERTY(PropertyInfo(Variant::INT, "color_phases/count", PROPERTY_HINT_RANGE, "0,4,1"), _SCS("set_color_phases"), _SCS("get_color_phases"));
453 
454 	for (int i = 0; i < VS::MAX_PARTICLE_COLOR_PHASES; i++) {
455 		String phase = "phase_" + itos(i) + "/";
456 		ADD_PROPERTYI(PropertyInfo(Variant::REAL, phase + "pos", PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_color_phase_pos"), _SCS("get_color_phase_pos"), i);
457 		ADD_PROPERTYI(PropertyInfo(Variant::COLOR, phase + "color"), _SCS("set_color_phase_color"), _SCS("get_color_phase_color"), i);
458 	}
459 
460 	BIND_CONSTANT(VAR_LIFETIME);
461 	BIND_CONSTANT(VAR_SPREAD);
462 	BIND_CONSTANT(VAR_GRAVITY);
463 	BIND_CONSTANT(VAR_LINEAR_VELOCITY);
464 	BIND_CONSTANT(VAR_ANGULAR_VELOCITY);
465 	BIND_CONSTANT(VAR_LINEAR_ACCELERATION);
466 	BIND_CONSTANT(VAR_DRAG);
467 	BIND_CONSTANT(VAR_TANGENTIAL_ACCELERATION);
468 	BIND_CONSTANT(VAR_INITIAL_SIZE);
469 	BIND_CONSTANT(VAR_FINAL_SIZE);
470 	BIND_CONSTANT(VAR_INITIAL_ANGLE);
471 	BIND_CONSTANT(VAR_HEIGHT);
472 	BIND_CONSTANT(VAR_HEIGHT_SPEED_SCALE);
473 	BIND_CONSTANT(VAR_MAX);
474 }
475 
Particles()476 Particles::Particles() {
477 
478 	particles = VisualServer::get_singleton()->particles_create();
479 	timer = memnew(Timer);
480 	add_child(timer);
481 	emit_timeout = 0;
482 
483 	set_amount(64);
484 	set_emitting(true);
485 	set_visibility_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)));
486 
487 	for (int i = 0; i < VAR_MAX; i++) {
488 		set_randomness((Variable)i, 0.0);
489 	}
490 
491 	set_variable(VAR_LIFETIME, 5.0);
492 	set_variable(VAR_SPREAD, 0.2);
493 	set_variable(VAR_GRAVITY, 9.8);
494 	set_variable(VAR_LINEAR_VELOCITY, 0.2);
495 	set_variable(VAR_ANGULAR_VELOCITY, 0.0);
496 	set_variable(VAR_LINEAR_ACCELERATION, 0.0);
497 	set_variable(VAR_DRAG, 0.0);
498 	set_variable(VAR_TANGENTIAL_ACCELERATION, 0.0);
499 	set_variable(VAR_DAMPING, 0.0);
500 	set_variable(VAR_INITIAL_SIZE, 1.0);
501 	set_variable(VAR_FINAL_SIZE, 1.0);
502 	set_variable(VAR_INITIAL_ANGLE, 0.0);
503 	set_variable(VAR_HEIGHT, 1.0);
504 	set_variable(VAR_HEIGHT_SPEED_SCALE, 0.0);
505 
506 	color_phase_count = 0;
507 
508 	set_color_phase_pos(0, 0.0);
509 	set_color_phase_pos(1, 1.0);
510 	set_color_phase_pos(2, 1.0);
511 	set_color_phase_pos(3, 1.0);
512 
513 	set_color_phase_color(0, Color(1, 1, 1));
514 	set_color_phase_color(1, Color(0, 0, 0));
515 	set_color_phase_color(2, Color(0, 0, 0));
516 	set_color_phase_color(3, Color(0, 0, 0));
517 
518 	set_gravity_normal(Vector3(0, -1.0, 0));
519 	set_emission_half_extents(Vector3(0.1, 0.1, 0.1));
520 
521 	height_from_velocity = false;
522 
523 	Vector<Variant> pars;
524 	pars.push_back(false);
525 	timer->connect("timeout", this, "set_emitting", pars);
526 	set_base(particles);
527 	local_coordinates = false;
528 }
529 
~Particles()530 Particles::~Particles() {
531 
532 	VisualServer::get_singleton()->free(particles);
533 }
534