cpu_particles_2d.cpp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420
  1. /*************************************************************************/
  2. /* cpu_particles_2d.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 "cpu_particles_2d.h"
  31. #include "particles_2d.h"
  32. #include "scene/2d/canvas_item.h"
  33. #include "scene/resources/particles_material.h"
  34. #include "servers/visual_server.h"
  35. void CPUParticles2D::set_emitting(bool p_emitting) {
  36. emitting = p_emitting;
  37. if (!is_processing_internal()) {
  38. set_process_internal(true);
  39. if (is_inside_tree()) {
  40. #ifndef NO_THREADS
  41. update_mutex->lock();
  42. #endif
  43. VS::get_singleton()->connect("frame_pre_draw", this, "_update_render_thread");
  44. VS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), true);
  45. #ifndef NO_THREADS
  46. update_mutex->unlock();
  47. #endif
  48. }
  49. }
  50. }
  51. void CPUParticles2D::set_amount(int p_amount) {
  52. ERR_FAIL_COND(p_amount < 1);
  53. particles.resize(p_amount);
  54. {
  55. PoolVector<Particle>::Write w = particles.write();
  56. for (int i = 0; i < p_amount; i++) {
  57. w[i].active = false;
  58. }
  59. }
  60. particle_data.resize((8 + 4 + 1) * p_amount);
  61. VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_2D, VS::MULTIMESH_COLOR_8BIT, VS::MULTIMESH_CUSTOM_DATA_FLOAT);
  62. particle_order.resize(p_amount);
  63. }
  64. void CPUParticles2D::set_lifetime(float p_lifetime) {
  65. ERR_FAIL_COND(p_lifetime <= 0);
  66. lifetime = p_lifetime;
  67. }
  68. void CPUParticles2D::set_one_shot(bool p_one_shot) {
  69. one_shot = p_one_shot;
  70. }
  71. void CPUParticles2D::set_pre_process_time(float p_time) {
  72. pre_process_time = p_time;
  73. }
  74. void CPUParticles2D::set_explosiveness_ratio(float p_ratio) {
  75. explosiveness_ratio = p_ratio;
  76. }
  77. void CPUParticles2D::set_randomness_ratio(float p_ratio) {
  78. randomness_ratio = p_ratio;
  79. }
  80. void CPUParticles2D::set_use_local_coordinates(bool p_enable) {
  81. local_coords = p_enable;
  82. }
  83. void CPUParticles2D::set_speed_scale(float p_scale) {
  84. speed_scale = p_scale;
  85. }
  86. bool CPUParticles2D::is_emitting() const {
  87. return emitting;
  88. }
  89. int CPUParticles2D::get_amount() const {
  90. return particles.size();
  91. }
  92. float CPUParticles2D::get_lifetime() const {
  93. return lifetime;
  94. }
  95. bool CPUParticles2D::get_one_shot() const {
  96. return one_shot;
  97. }
  98. float CPUParticles2D::get_pre_process_time() const {
  99. return pre_process_time;
  100. }
  101. float CPUParticles2D::get_explosiveness_ratio() const {
  102. return explosiveness_ratio;
  103. }
  104. float CPUParticles2D::get_randomness_ratio() const {
  105. return randomness_ratio;
  106. }
  107. bool CPUParticles2D::get_use_local_coordinates() const {
  108. return local_coords;
  109. }
  110. float CPUParticles2D::get_speed_scale() const {
  111. return speed_scale;
  112. }
  113. void CPUParticles2D::set_draw_order(DrawOrder p_order) {
  114. draw_order = p_order;
  115. }
  116. CPUParticles2D::DrawOrder CPUParticles2D::get_draw_order() const {
  117. return draw_order;
  118. }
  119. void CPUParticles2D::_update_mesh_texture() {
  120. Size2 tex_size;
  121. if (texture.is_valid()) {
  122. tex_size = texture->get_size();
  123. } else {
  124. tex_size = Size2(1, 1);
  125. }
  126. PoolVector<Vector2> vertices;
  127. vertices.push_back(-tex_size * 0.5);
  128. vertices.push_back(-tex_size * 0.5 + Vector2(tex_size.x, 0));
  129. vertices.push_back(-tex_size * 0.5 + Vector2(tex_size.x, tex_size.y));
  130. vertices.push_back(-tex_size * 0.5 + Vector2(0, tex_size.y));
  131. PoolVector<Vector2> uvs;
  132. uvs.push_back(Vector2(0, 0));
  133. uvs.push_back(Vector2(1, 0));
  134. uvs.push_back(Vector2(1, 1));
  135. uvs.push_back(Vector2(0, 1));
  136. PoolVector<Color> colors;
  137. colors.push_back(Color(1, 1, 1, 1));
  138. colors.push_back(Color(1, 1, 1, 1));
  139. colors.push_back(Color(1, 1, 1, 1));
  140. colors.push_back(Color(1, 1, 1, 1));
  141. PoolVector<int> indices;
  142. indices.push_back(0);
  143. indices.push_back(1);
  144. indices.push_back(2);
  145. indices.push_back(2);
  146. indices.push_back(3);
  147. indices.push_back(0);
  148. Array arr;
  149. arr.resize(VS::ARRAY_MAX);
  150. arr[VS::ARRAY_VERTEX] = vertices;
  151. arr[VS::ARRAY_TEX_UV] = uvs;
  152. arr[VS::ARRAY_COLOR] = colors;
  153. arr[VS::ARRAY_INDEX] = indices;
  154. VS::get_singleton()->mesh_clear(mesh);
  155. VS::get_singleton()->mesh_add_surface_from_arrays(mesh, VS::PRIMITIVE_TRIANGLES, arr);
  156. }
  157. void CPUParticles2D::set_texture(const Ref<Texture> &p_texture) {
  158. texture = p_texture;
  159. update();
  160. _update_mesh_texture();
  161. }
  162. Ref<Texture> CPUParticles2D::get_texture() const {
  163. return texture;
  164. }
  165. void CPUParticles2D::set_normalmap(const Ref<Texture> &p_normalmap) {
  166. normalmap = p_normalmap;
  167. update();
  168. }
  169. Ref<Texture> CPUParticles2D::get_normalmap() const {
  170. return normalmap;
  171. }
  172. void CPUParticles2D::set_fixed_fps(int p_count) {
  173. fixed_fps = p_count;
  174. }
  175. int CPUParticles2D::get_fixed_fps() const {
  176. return fixed_fps;
  177. }
  178. void CPUParticles2D::set_fractional_delta(bool p_enable) {
  179. fractional_delta = p_enable;
  180. }
  181. bool CPUParticles2D::get_fractional_delta() const {
  182. return fractional_delta;
  183. }
  184. String CPUParticles2D::get_configuration_warning() const {
  185. String warnings;
  186. CanvasItemMaterial *mat = Object::cast_to<CanvasItemMaterial>(get_material().ptr());
  187. if (get_material().is_null() || (mat && !mat->get_particles_animation())) {
  188. if (get_param(PARAM_ANIM_SPEED) != 0.0 || get_param(PARAM_ANIM_OFFSET) != 0.0 ||
  189. get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid()) {
  190. if (warnings != String())
  191. warnings += "\n";
  192. warnings += "- " + TTR("CPUParticles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled.");
  193. }
  194. }
  195. return warnings;
  196. }
  197. void CPUParticles2D::restart() {
  198. time = 0;
  199. inactive_time = 0;
  200. frame_remainder = 0;
  201. cycle = 0;
  202. {
  203. int pc = particles.size();
  204. PoolVector<Particle>::Write w = particles.write();
  205. for (int i = 0; i < pc; i++) {
  206. w[i].active = false;
  207. }
  208. }
  209. }
  210. void CPUParticles2D::set_spread(float p_spread) {
  211. spread = p_spread;
  212. }
  213. float CPUParticles2D::get_spread() const {
  214. return spread;
  215. }
  216. void CPUParticles2D::set_flatness(float p_flatness) {
  217. flatness = p_flatness;
  218. }
  219. float CPUParticles2D::get_flatness() const {
  220. return flatness;
  221. }
  222. void CPUParticles2D::set_param(Parameter p_param, float p_value) {
  223. ERR_FAIL_INDEX(p_param, PARAM_MAX);
  224. parameters[p_param] = p_value;
  225. }
  226. float CPUParticles2D::get_param(Parameter p_param) const {
  227. ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
  228. return parameters[p_param];
  229. }
  230. void CPUParticles2D::set_param_randomness(Parameter p_param, float p_value) {
  231. ERR_FAIL_INDEX(p_param, PARAM_MAX);
  232. randomness[p_param] = p_value;
  233. }
  234. float CPUParticles2D::get_param_randomness(Parameter p_param) const {
  235. ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
  236. return randomness[p_param];
  237. }
  238. static void _adjust_curve_range(const Ref<Curve> &p_curve, float p_min, float p_max) {
  239. Ref<Curve> curve = p_curve;
  240. if (!curve.is_valid())
  241. return;
  242. curve->ensure_default_setup(p_min, p_max);
  243. }
  244. void CPUParticles2D::set_param_curve(Parameter p_param, const Ref<Curve> &p_curve) {
  245. ERR_FAIL_INDEX(p_param, PARAM_MAX);
  246. curve_parameters[p_param] = p_curve;
  247. switch (p_param) {
  248. case PARAM_INITIAL_LINEAR_VELOCITY: {
  249. //do none for this one
  250. } break;
  251. case PARAM_ANGULAR_VELOCITY: {
  252. _adjust_curve_range(p_curve, -360, 360);
  253. } break;
  254. /*case PARAM_ORBIT_VELOCITY: {
  255. _adjust_curve_range(p_curve, -500, 500);
  256. } break;*/
  257. case PARAM_LINEAR_ACCEL: {
  258. _adjust_curve_range(p_curve, -200, 200);
  259. } break;
  260. case PARAM_RADIAL_ACCEL: {
  261. _adjust_curve_range(p_curve, -200, 200);
  262. } break;
  263. case PARAM_TANGENTIAL_ACCEL: {
  264. _adjust_curve_range(p_curve, -200, 200);
  265. } break;
  266. case PARAM_DAMPING: {
  267. _adjust_curve_range(p_curve, 0, 100);
  268. } break;
  269. case PARAM_ANGLE: {
  270. _adjust_curve_range(p_curve, -360, 360);
  271. } break;
  272. case PARAM_SCALE: {
  273. } break;
  274. case PARAM_HUE_VARIATION: {
  275. _adjust_curve_range(p_curve, -1, 1);
  276. } break;
  277. case PARAM_ANIM_SPEED: {
  278. _adjust_curve_range(p_curve, 0, 200);
  279. } break;
  280. case PARAM_ANIM_OFFSET: {
  281. } break;
  282. default: {}
  283. }
  284. }
  285. Ref<Curve> CPUParticles2D::get_param_curve(Parameter p_param) const {
  286. ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref<Curve>());
  287. return curve_parameters[p_param];
  288. }
  289. void CPUParticles2D::set_color(const Color &p_color) {
  290. color = p_color;
  291. }
  292. Color CPUParticles2D::get_color() const {
  293. return color;
  294. }
  295. void CPUParticles2D::set_color_ramp(const Ref<Gradient> &p_ramp) {
  296. color_ramp = p_ramp;
  297. }
  298. Ref<Gradient> CPUParticles2D::get_color_ramp() const {
  299. return color_ramp;
  300. }
  301. void CPUParticles2D::set_particle_flag(Flags p_flag, bool p_enable) {
  302. ERR_FAIL_INDEX(p_flag, FLAG_MAX);
  303. flags[p_flag] = p_enable;
  304. }
  305. bool CPUParticles2D::get_particle_flag(Flags p_flag) const {
  306. ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
  307. return flags[p_flag];
  308. }
  309. void CPUParticles2D::set_emission_shape(EmissionShape p_shape) {
  310. emission_shape = p_shape;
  311. _change_notify();
  312. }
  313. void CPUParticles2D::set_emission_sphere_radius(float p_radius) {
  314. emission_sphere_radius = p_radius;
  315. }
  316. void CPUParticles2D::set_emission_rect_extents(Vector2 p_extents) {
  317. emission_rect_extents = p_extents;
  318. }
  319. void CPUParticles2D::set_emission_points(const PoolVector<Vector2> &p_points) {
  320. emission_points = p_points;
  321. }
  322. void CPUParticles2D::set_emission_normals(const PoolVector<Vector2> &p_normals) {
  323. emission_normals = p_normals;
  324. }
  325. void CPUParticles2D::set_emission_colors(const PoolVector<Color> &p_colors) {
  326. emission_colors = p_colors;
  327. }
  328. float CPUParticles2D::get_emission_sphere_radius() const {
  329. return emission_sphere_radius;
  330. }
  331. Vector2 CPUParticles2D::get_emission_rect_extents() const {
  332. return emission_rect_extents;
  333. }
  334. PoolVector<Vector2> CPUParticles2D::get_emission_points() const {
  335. return emission_points;
  336. }
  337. PoolVector<Vector2> CPUParticles2D::get_emission_normals() const {
  338. return emission_normals;
  339. }
  340. PoolVector<Color> CPUParticles2D::get_emission_colors() const {
  341. return emission_colors;
  342. }
  343. CPUParticles2D::EmissionShape CPUParticles2D::get_emission_shape() const {
  344. return emission_shape;
  345. }
  346. void CPUParticles2D::set_gravity(const Vector2 &p_gravity) {
  347. gravity = p_gravity;
  348. }
  349. Vector2 CPUParticles2D::get_gravity() const {
  350. return gravity;
  351. }
  352. void CPUParticles2D::_validate_property(PropertyInfo &property) const {
  353. if (property.name == "color" && color_ramp.is_valid()) {
  354. property.usage = 0;
  355. }
  356. if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_CIRCLE) {
  357. property.usage = 0;
  358. }
  359. if (property.name == "emission_rect_extents" && emission_shape != EMISSION_SHAPE_RECTANGLE) {
  360. property.usage = 0;
  361. }
  362. if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) {
  363. property.usage = 0;
  364. }
  365. if (property.name == "emission_normals" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
  366. property.usage = 0;
  367. }
  368. if (property.name == "emission_points" && emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
  369. property.usage = 0;
  370. }
  371. if (property.name == "emission_colors" && emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
  372. property.usage = 0;
  373. }
  374. /*
  375. if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) {
  376. property.usage = 0;
  377. }
  378. */
  379. }
  380. static uint32_t idhash(uint32_t x) {
  381. x = ((x >> uint32_t(16)) ^ x) * uint32_t(0x45d9f3b);
  382. x = ((x >> uint32_t(16)) ^ x) * uint32_t(0x45d9f3b);
  383. x = (x >> uint32_t(16)) ^ x;
  384. return x;
  385. }
  386. static float rand_from_seed(uint32_t &seed) {
  387. int k;
  388. int s = int(seed);
  389. if (s == 0)
  390. s = 305420679;
  391. k = s / 127773;
  392. s = 16807 * (s - k * 127773) - 2836 * k;
  393. if (s < 0)
  394. s += 2147483647;
  395. seed = uint32_t(s);
  396. return float(seed % uint32_t(65536)) / 65535.0;
  397. }
  398. void CPUParticles2D::_particles_process(float p_delta) {
  399. p_delta *= speed_scale;
  400. int pcount = particles.size();
  401. PoolVector<Particle>::Write w = particles.write();
  402. Particle *parray = w.ptr();
  403. float prev_time = time;
  404. time += p_delta;
  405. if (time > lifetime) {
  406. time = Math::fmod(time, lifetime);
  407. cycle++;
  408. if (one_shot && cycle > 0) {
  409. emitting = false;
  410. }
  411. }
  412. Transform2D emission_xform;
  413. Transform2D velocity_xform;
  414. if (!local_coords) {
  415. emission_xform = get_global_transform();
  416. velocity_xform = emission_xform;
  417. velocity_xform[2] = Vector2();
  418. }
  419. for (int i = 0; i < pcount; i++) {
  420. Particle &p = parray[i];
  421. if (!emitting && !p.active)
  422. continue;
  423. float restart_time = (float(i) / float(pcount)) * lifetime;
  424. float local_delta = p_delta;
  425. if (randomness_ratio > 0.0) {
  426. uint32_t seed = cycle;
  427. if (restart_time >= time) {
  428. seed -= uint32_t(1);
  429. }
  430. seed *= uint32_t(pcount);
  431. seed += uint32_t(i);
  432. float random = float(idhash(seed) % uint32_t(65536)) / 65536.0;
  433. restart_time += randomness_ratio * random * 1.0 / float(pcount);
  434. }
  435. restart_time *= (1.0 - explosiveness_ratio);
  436. bool restart = false;
  437. if (time > prev_time) {
  438. // restart_time >= prev_time is used so particles emit in the first frame they are processed
  439. if (restart_time >= prev_time && restart_time < time) {
  440. restart = true;
  441. if (fractional_delta) {
  442. local_delta = (time - restart_time) * lifetime;
  443. }
  444. }
  445. } else if (local_delta > 0.0) {
  446. if (restart_time >= prev_time) {
  447. restart = true;
  448. if (fractional_delta) {
  449. local_delta = (1.0 - restart_time + time) * lifetime;
  450. }
  451. } else if (restart_time < time) {
  452. restart = true;
  453. if (fractional_delta) {
  454. local_delta = (time - restart_time) * lifetime;
  455. }
  456. }
  457. }
  458. if (restart) {
  459. if (!emitting) {
  460. p.active = false;
  461. continue;
  462. }
  463. p.active = true;
  464. /*float tex_linear_velocity = 0;
  465. if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
  466. tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(0);
  467. }*/
  468. float tex_angle = 0.0;
  469. if (curve_parameters[PARAM_ANGLE].is_valid()) {
  470. tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(0);
  471. }
  472. float tex_anim_offset = 0.0;
  473. if (curve_parameters[PARAM_ANGLE].is_valid()) {
  474. tex_anim_offset = curve_parameters[PARAM_ANGLE]->interpolate(0);
  475. }
  476. p.seed = Math::rand();
  477. p.angle_rand = Math::randf();
  478. p.scale_rand = Math::randf();
  479. p.hue_rot_rand = Math::randf();
  480. p.anim_offset_rand = Math::randf();
  481. float angle1_rad = (Math::randf() * 2.0 - 1.0) * Math_PI * spread / 180.0;
  482. Vector2 rot = Vector2(Math::cos(angle1_rad), Math::sin(angle1_rad));
  483. p.velocity = rot * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]);
  484. float base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp(1.0f, p.angle_rand, randomness[PARAM_ANGLE]);
  485. p.rotation = Math::deg2rad(base_angle);
  486. p.custom[0] = 0.0; // unused
  487. p.custom[1] = 0.0; // phase [0..1]
  488. p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]); //animation phase [0..1]
  489. p.custom[3] = 0.0;
  490. p.transform = Transform2D();
  491. p.time = 0;
  492. p.base_color = Color(1, 1, 1, 1);
  493. switch (emission_shape) {
  494. case EMISSION_SHAPE_POINT: {
  495. //do none
  496. } break;
  497. case EMISSION_SHAPE_CIRCLE: {
  498. p.transform[2] = Vector2(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0).normalized() * emission_sphere_radius;
  499. } break;
  500. case EMISSION_SHAPE_RECTANGLE: {
  501. p.transform[2] = Vector2(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0) * emission_rect_extents;
  502. } break;
  503. case EMISSION_SHAPE_POINTS:
  504. case EMISSION_SHAPE_DIRECTED_POINTS: {
  505. int pc = emission_points.size();
  506. if (pc == 0)
  507. break;
  508. int random_idx = Math::rand() % pc;
  509. p.transform[2] = emission_points.get(random_idx);
  510. if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS && emission_normals.size() == pc) {
  511. p.velocity = emission_normals.get(random_idx);
  512. }
  513. if (emission_colors.size() == pc) {
  514. p.base_color = emission_colors.get(random_idx);
  515. }
  516. } break;
  517. }
  518. if (!local_coords) {
  519. p.velocity = velocity_xform.xform(p.velocity);
  520. p.transform = emission_xform * p.transform;
  521. }
  522. } else if (!p.active) {
  523. continue;
  524. } else {
  525. uint32_t alt_seed = p.seed;
  526. p.time += local_delta;
  527. p.custom[1] = p.time / lifetime;
  528. float tex_linear_velocity = 0.0;
  529. if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
  530. tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(p.custom[1]);
  531. }
  532. /*
  533. float tex_orbit_velocity = 0.0;
  534. if (flags[FLAG_DISABLE_Z]) {
  535. if (curve_parameters[PARAM_INITIAL_ORBIT_VELOCITY].is_valid()) {
  536. tex_orbit_velocity = curve_parameters[PARAM_INITIAL_ORBIT_VELOCITY]->interpolate(p.custom[1]);
  537. }
  538. }
  539. */
  540. float tex_angular_velocity = 0.0;
  541. if (curve_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) {
  542. tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->interpolate(p.custom[1]);
  543. }
  544. float tex_linear_accel = 0.0;
  545. if (curve_parameters[PARAM_LINEAR_ACCEL].is_valid()) {
  546. tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->interpolate(p.custom[1]);
  547. }
  548. float tex_tangential_accel = 0.0;
  549. if (curve_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) {
  550. tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->interpolate(p.custom[1]);
  551. }
  552. float tex_radial_accel = 0.0;
  553. if (curve_parameters[PARAM_RADIAL_ACCEL].is_valid()) {
  554. tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->interpolate(p.custom[1]);
  555. }
  556. float tex_damping = 0.0;
  557. if (curve_parameters[PARAM_DAMPING].is_valid()) {
  558. tex_damping = curve_parameters[PARAM_DAMPING]->interpolate(p.custom[1]);
  559. }
  560. float tex_angle = 0.0;
  561. if (curve_parameters[PARAM_ANGLE].is_valid()) {
  562. tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(p.custom[1]);
  563. }
  564. float tex_anim_speed = 0.0;
  565. if (curve_parameters[PARAM_ANIM_SPEED].is_valid()) {
  566. tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->interpolate(p.custom[1]);
  567. }
  568. float tex_anim_offset = 0.0;
  569. if (curve_parameters[PARAM_ANIM_OFFSET].is_valid()) {
  570. tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->interpolate(p.custom[1]);
  571. }
  572. Vector2 force = gravity;
  573. Vector2 pos = p.transform[2];
  574. //apply linear acceleration
  575. force += p.velocity.length() > 0.0 ? p.velocity.normalized() * (parameters[PARAM_LINEAR_ACCEL] + tex_linear_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_LINEAR_ACCEL]) : Vector2();
  576. //apply radial acceleration
  577. Vector2 org = emission_xform[2];
  578. Vector2 diff = pos - org;
  579. force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector2();
  580. //apply tangential acceleration;
  581. Vector2 yx = Vector2(diff.y, diff.x);
  582. force += yx.length() > 0.0 ? (yx * Vector2(-1.0, 1.0)) * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector2();
  583. //apply attractor forces
  584. p.velocity += force * local_delta;
  585. //orbit velocity
  586. #if 0
  587. if (flags[FLAG_DISABLE_Z]) {
  588. float orbit_amount = (orbit_velocity + tex_orbit_velocity) * mix(1.0, rand_from_seed(alt_seed), orbit_velocity_random);
  589. if (orbit_amount != 0.0) {
  590. float ang = orbit_amount * DELTA * pi * 2.0;
  591. mat2 rot = mat2(vec2(cos(ang), -sin(ang)), vec2(sin(ang), cos(ang)));
  592. TRANSFORM[3].xy -= diff.xy;
  593. TRANSFORM[3].xy += rot * diff.xy;
  594. }
  595. }
  596. #endif
  597. if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
  598. p.velocity = p.velocity.normalized() * tex_linear_velocity;
  599. }
  600. if (parameters[PARAM_DAMPING] + tex_damping > 0.0) {
  601. float v = p.velocity.length();
  602. float damp = (parameters[PARAM_DAMPING] + tex_damping) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_DAMPING]);
  603. v -= damp * local_delta;
  604. if (v < 0.0) {
  605. p.velocity = Vector2();
  606. } else {
  607. p.velocity = p.velocity.normalized() * v;
  608. }
  609. }
  610. float base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp(1.0f, p.angle_rand, randomness[PARAM_ANGLE]);
  611. base_angle += p.custom[1] * lifetime * (parameters[PARAM_ANGULAR_VELOCITY] + tex_angular_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed) * 2.0f - 1.0f, randomness[PARAM_ANGULAR_VELOCITY]);
  612. p.rotation = Math::deg2rad(base_angle); //angle
  613. float animation_phase = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]) + p.custom[1] * (parameters[PARAM_ANIM_SPEED] + tex_anim_speed) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ANIM_SPEED]);
  614. p.custom[2] = animation_phase;
  615. }
  616. //apply color
  617. //apply hue rotation
  618. float tex_scale = 1.0;
  619. if (curve_parameters[PARAM_SCALE].is_valid()) {
  620. tex_scale = curve_parameters[PARAM_SCALE]->interpolate(p.custom[1]);
  621. }
  622. float tex_hue_variation = 0.0;
  623. if (curve_parameters[PARAM_HUE_VARIATION].is_valid()) {
  624. tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->interpolate(p.custom[1]);
  625. }
  626. float hue_rot_angle = (parameters[PARAM_HUE_VARIATION] + tex_hue_variation) * Math_PI * 2.0 * Math::lerp(1.0f, p.hue_rot_rand * 2.0f - 1.0f, randomness[PARAM_HUE_VARIATION]);
  627. float hue_rot_c = Math::cos(hue_rot_angle);
  628. float hue_rot_s = Math::sin(hue_rot_angle);
  629. Basis hue_rot_mat;
  630. {
  631. Basis mat1(0.299, 0.587, 0.114, 0.299, 0.587, 0.114, 0.299, 0.587, 0.114);
  632. Basis mat2(0.701, -0.587, -0.114, -0.299, 0.413, -0.114, -0.300, -0.588, 0.886);
  633. Basis mat3(0.168, 0.330, -0.497, -0.328, 0.035, 0.292, 1.250, -1.050, -0.203);
  634. for (int j = 0; j < 3; j++) {
  635. hue_rot_mat[j] = mat1[j] + mat2[j] * hue_rot_c + mat3[j] * hue_rot_s;
  636. }
  637. }
  638. if (color_ramp.is_valid()) {
  639. p.color = color_ramp->get_color_at_offset(p.custom[1]) * color;
  640. } else {
  641. p.color = color;
  642. }
  643. Vector3 color_rgb = hue_rot_mat.xform_inv(Vector3(p.color.r, p.color.g, p.color.b));
  644. p.color.r = color_rgb.x;
  645. p.color.g = color_rgb.y;
  646. p.color.b = color_rgb.z;
  647. p.color *= p.base_color;
  648. if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) {
  649. if (p.velocity.length() > 0.0) {
  650. p.transform.elements[0] = p.velocity.normalized();
  651. p.transform.elements[0] = p.transform.elements[1].tangent();
  652. }
  653. } else {
  654. p.transform.elements[0] = Vector2(Math::cos(p.rotation), -Math::sin(p.rotation));
  655. p.transform.elements[1] = Vector2(Math::sin(p.rotation), Math::cos(p.rotation));
  656. }
  657. //scale by scale
  658. float base_scale = Math::lerp(parameters[PARAM_SCALE] * tex_scale, 1.0f, p.scale_rand * randomness[PARAM_SCALE]);
  659. if (base_scale == 0.0) base_scale = 0.000001;
  660. p.transform.elements[0] *= base_scale;
  661. p.transform.elements[1] *= base_scale;
  662. p.transform[2] += p.velocity * local_delta;
  663. }
  664. }
  665. void CPUParticles2D::_update_particle_data_buffer() {
  666. #ifndef NO_THREADS
  667. update_mutex->lock();
  668. #endif
  669. {
  670. int pc = particles.size();
  671. PoolVector<int>::Write ow;
  672. int *order = NULL;
  673. PoolVector<float>::Write w = particle_data.write();
  674. PoolVector<Particle>::Read r = particles.read();
  675. float *ptr = w.ptr();
  676. Transform2D un_transform;
  677. if (!local_coords) {
  678. un_transform = get_global_transform().affine_inverse();
  679. }
  680. if (draw_order != DRAW_ORDER_INDEX) {
  681. ow = particle_order.write();
  682. order = ow.ptr();
  683. for (int i = 0; i < pc; i++) {
  684. order[i] = i;
  685. }
  686. if (draw_order == DRAW_ORDER_LIFETIME) {
  687. SortArray<int, SortLifetime> sorter;
  688. sorter.compare.particles = r.ptr();
  689. sorter.sort(order, pc);
  690. }
  691. }
  692. for (int i = 0; i < pc; i++) {
  693. int idx = order ? order[i] : i;
  694. Transform2D t = r[idx].transform;
  695. if (!local_coords) {
  696. t = un_transform * t;
  697. }
  698. if (r[idx].active) {
  699. ptr[0] = t.elements[0][0];
  700. ptr[1] = t.elements[1][0];
  701. ptr[2] = 0;
  702. ptr[3] = t.elements[2][0];
  703. ptr[4] = t.elements[0][1];
  704. ptr[5] = t.elements[1][1];
  705. ptr[6] = 0;
  706. ptr[7] = t.elements[2][1];
  707. } else {
  708. zeromem(ptr, sizeof(float) * 8);
  709. }
  710. Color c = r[idx].color;
  711. uint8_t *data8 = (uint8_t *)&ptr[8];
  712. data8[0] = CLAMP(c.r * 255.0, 0, 255);
  713. data8[1] = CLAMP(c.g * 255.0, 0, 255);
  714. data8[2] = CLAMP(c.b * 255.0, 0, 255);
  715. data8[3] = CLAMP(c.a * 255.0, 0, 255);
  716. ptr[9] = r[idx].custom[0];
  717. ptr[10] = r[idx].custom[1];
  718. ptr[11] = r[idx].custom[2];
  719. ptr[12] = r[idx].custom[3];
  720. ptr += 13;
  721. }
  722. }
  723. #ifndef NO_THREADS
  724. update_mutex->unlock();
  725. #endif
  726. }
  727. void CPUParticles2D::_update_render_thread() {
  728. #ifndef NO_THREADS
  729. update_mutex->lock();
  730. #endif
  731. VS::get_singleton()->multimesh_set_as_bulk_array(multimesh, particle_data);
  732. #ifndef NO_THREADS
  733. update_mutex->unlock();
  734. #endif
  735. }
  736. void CPUParticles2D::_notification(int p_what) {
  737. if (p_what == NOTIFICATION_ENTER_TREE) {
  738. if (is_processing_internal()) {
  739. #ifndef NO_THREADS
  740. update_mutex->lock();
  741. #endif
  742. VS::get_singleton()->connect("frame_pre_draw", this, "_update_render_thread");
  743. VS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), true);
  744. #ifndef NO_THREADS
  745. update_mutex->unlock();
  746. #endif
  747. }
  748. }
  749. if (p_what == NOTIFICATION_EXIT_TREE) {
  750. if (is_processing_internal()) {
  751. #ifndef NO_THREADS
  752. update_mutex->lock();
  753. #endif
  754. VS::get_singleton()->disconnect("frame_pre_draw", this, "_update_render_thread");
  755. VS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), false);
  756. #ifndef NO_THREADS
  757. update_mutex->unlock();
  758. #endif
  759. }
  760. }
  761. if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) {
  762. }
  763. if (p_what == NOTIFICATION_DRAW) {
  764. RID texrid;
  765. if (texture.is_valid()) {
  766. texrid = texture->get_rid();
  767. }
  768. RID normrid;
  769. if (normalmap.is_valid()) {
  770. normrid = normalmap->get_rid();
  771. }
  772. VS::get_singleton()->canvas_item_add_multimesh(get_canvas_item(), multimesh, texrid, normrid);
  773. }
  774. if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
  775. if (particles.size() == 0 || !is_visible_in_tree())
  776. return;
  777. float delta = get_process_delta_time();
  778. if (emitting) {
  779. inactive_time = 0;
  780. } else {
  781. inactive_time += delta;
  782. if (inactive_time > lifetime * 1.2) {
  783. set_process_internal(false);
  784. #ifndef NO_THREADS
  785. update_mutex->lock();
  786. #endif
  787. VS::get_singleton()->disconnect("frame_pre_draw", this, "_update_render_thread");
  788. VS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), false);
  789. #ifndef NO_THREADS
  790. update_mutex->unlock();
  791. #endif
  792. //reset variables
  793. time = 0;
  794. inactive_time = 0;
  795. frame_remainder = 0;
  796. cycle = 0;
  797. return;
  798. }
  799. }
  800. if (time == 0 && pre_process_time > 0.0) {
  801. float frame_time;
  802. if (fixed_fps > 0)
  803. frame_time = 1.0 / fixed_fps;
  804. else
  805. frame_time = 1.0 / 30.0;
  806. float todo = pre_process_time;
  807. while (todo >= 0) {
  808. _particles_process(frame_time);
  809. todo -= frame_time;
  810. }
  811. }
  812. if (fixed_fps > 0) {
  813. float frame_time = 1.0 / fixed_fps;
  814. float decr = frame_time;
  815. float ldelta = delta;
  816. if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10
  817. ldelta = 0.1;
  818. } else if (ldelta <= 0.0) { //unlikely but..
  819. ldelta = 0.001;
  820. }
  821. float todo = frame_remainder + ldelta;
  822. while (todo >= frame_time) {
  823. _particles_process(frame_time);
  824. todo -= decr;
  825. }
  826. frame_remainder = todo;
  827. } else {
  828. _particles_process(delta);
  829. }
  830. _update_particle_data_buffer();
  831. }
  832. }
  833. void CPUParticles2D::convert_from_particles(Node *p_particles) {
  834. Particles2D *particles = Object::cast_to<Particles2D>(p_particles);
  835. ERR_FAIL_COND(!particles);
  836. set_emitting(particles->is_emitting());
  837. set_amount(particles->get_amount());
  838. set_lifetime(particles->get_lifetime());
  839. set_one_shot(particles->get_one_shot());
  840. set_pre_process_time(particles->get_pre_process_time());
  841. set_explosiveness_ratio(particles->get_explosiveness_ratio());
  842. set_randomness_ratio(particles->get_randomness_ratio());
  843. set_use_local_coordinates(particles->get_use_local_coordinates());
  844. set_fixed_fps(particles->get_fixed_fps());
  845. set_fractional_delta(particles->get_fractional_delta());
  846. set_speed_scale(particles->get_speed_scale());
  847. set_draw_order(DrawOrder(particles->get_draw_order()));
  848. set_texture(particles->get_texture());
  849. Ref<Material> mat = particles->get_material();
  850. if (mat.is_valid()) {
  851. set_material(mat);
  852. }
  853. Ref<ParticlesMaterial> material = particles->get_process_material();
  854. if (material.is_null())
  855. return;
  856. set_spread(material->get_spread());
  857. set_flatness(material->get_flatness());
  858. set_color(material->get_color());
  859. Ref<GradientTexture> gt = material->get_color_ramp();
  860. if (gt.is_valid()) {
  861. set_color_ramp(gt->get_gradient());
  862. }
  863. set_particle_flag(FLAG_ALIGN_Y_TO_VELOCITY, material->get_flag(ParticlesMaterial::FLAG_ALIGN_Y_TO_VELOCITY));
  864. set_emission_shape(EmissionShape(material->get_emission_shape()));
  865. set_emission_sphere_radius(material->get_emission_sphere_radius());
  866. Vector2 rect_extents = Vector2(material->get_emission_box_extents().x, material->get_emission_box_extents().y);
  867. set_emission_rect_extents(rect_extents);
  868. Vector2 gravity = Vector2(material->get_gravity().x, material->get_gravity().y);
  869. set_gravity(gravity);
  870. #define CONVERT_PARAM(m_param) \
  871. set_param(m_param, material->get_param(ParticlesMaterial::m_param)); \
  872. { \
  873. Ref<CurveTexture> ctex = material->get_param_texture(ParticlesMaterial::m_param); \
  874. if (ctex.is_valid()) set_param_curve(m_param, ctex->get_curve()); \
  875. } \
  876. set_param_randomness(m_param, material->get_param_randomness(ParticlesMaterial::m_param));
  877. CONVERT_PARAM(PARAM_INITIAL_LINEAR_VELOCITY);
  878. CONVERT_PARAM(PARAM_ANGULAR_VELOCITY);
  879. CONVERT_PARAM(PARAM_ORBIT_VELOCITY);
  880. CONVERT_PARAM(PARAM_LINEAR_ACCEL);
  881. CONVERT_PARAM(PARAM_RADIAL_ACCEL);
  882. CONVERT_PARAM(PARAM_TANGENTIAL_ACCEL);
  883. CONVERT_PARAM(PARAM_DAMPING);
  884. CONVERT_PARAM(PARAM_ANGLE);
  885. CONVERT_PARAM(PARAM_SCALE);
  886. CONVERT_PARAM(PARAM_HUE_VARIATION);
  887. CONVERT_PARAM(PARAM_ANIM_SPEED);
  888. CONVERT_PARAM(PARAM_ANIM_OFFSET);
  889. #undef CONVERT_PARAM
  890. }
  891. void CPUParticles2D::_bind_methods() {
  892. ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &CPUParticles2D::set_emitting);
  893. ClassDB::bind_method(D_METHOD("set_amount", "amount"), &CPUParticles2D::set_amount);
  894. ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &CPUParticles2D::set_lifetime);
  895. ClassDB::bind_method(D_METHOD("set_one_shot", "enable"), &CPUParticles2D::set_one_shot);
  896. ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &CPUParticles2D::set_pre_process_time);
  897. ClassDB::bind_method(D_METHOD("set_explosiveness_ratio", "ratio"), &CPUParticles2D::set_explosiveness_ratio);
  898. ClassDB::bind_method(D_METHOD("set_randomness_ratio", "ratio"), &CPUParticles2D::set_randomness_ratio);
  899. ClassDB::bind_method(D_METHOD("set_use_local_coordinates", "enable"), &CPUParticles2D::set_use_local_coordinates);
  900. ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &CPUParticles2D::set_fixed_fps);
  901. ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &CPUParticles2D::set_fractional_delta);
  902. ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &CPUParticles2D::set_speed_scale);
  903. ClassDB::bind_method(D_METHOD("is_emitting"), &CPUParticles2D::is_emitting);
  904. ClassDB::bind_method(D_METHOD("get_amount"), &CPUParticles2D::get_amount);
  905. ClassDB::bind_method(D_METHOD("get_lifetime"), &CPUParticles2D::get_lifetime);
  906. ClassDB::bind_method(D_METHOD("get_one_shot"), &CPUParticles2D::get_one_shot);
  907. ClassDB::bind_method(D_METHOD("get_pre_process_time"), &CPUParticles2D::get_pre_process_time);
  908. ClassDB::bind_method(D_METHOD("get_explosiveness_ratio"), &CPUParticles2D::get_explosiveness_ratio);
  909. ClassDB::bind_method(D_METHOD("get_randomness_ratio"), &CPUParticles2D::get_randomness_ratio);
  910. ClassDB::bind_method(D_METHOD("get_use_local_coordinates"), &CPUParticles2D::get_use_local_coordinates);
  911. ClassDB::bind_method(D_METHOD("get_fixed_fps"), &CPUParticles2D::get_fixed_fps);
  912. ClassDB::bind_method(D_METHOD("get_fractional_delta"), &CPUParticles2D::get_fractional_delta);
  913. ClassDB::bind_method(D_METHOD("get_speed_scale"), &CPUParticles2D::get_speed_scale);
  914. ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &CPUParticles2D::set_draw_order);
  915. ClassDB::bind_method(D_METHOD("get_draw_order"), &CPUParticles2D::get_draw_order);
  916. ClassDB::bind_method(D_METHOD("set_texture", "texture"), &CPUParticles2D::set_texture);
  917. ClassDB::bind_method(D_METHOD("get_texture"), &CPUParticles2D::get_texture);
  918. ClassDB::bind_method(D_METHOD("set_normalmap", "normalmap"), &CPUParticles2D::set_normalmap);
  919. ClassDB::bind_method(D_METHOD("get_normalmap"), &CPUParticles2D::get_normalmap);
  920. ClassDB::bind_method(D_METHOD("restart"), &CPUParticles2D::restart);
  921. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
  922. ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
  923. ADD_GROUP("Time", "");
  924. ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01"), "set_lifetime", "get_lifetime");
  925. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
  926. ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
  927. ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale");
  928. ADD_PROPERTY(PropertyInfo(Variant::REAL, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
  929. ADD_PROPERTY(PropertyInfo(Variant::REAL, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
  930. ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps");
  931. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
  932. ADD_GROUP("Drawing", "");
  933. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
  934. ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime"), "set_draw_order", "get_draw_order");
  935. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
  936. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normalmap", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normalmap", "get_normalmap");
  937. BIND_ENUM_CONSTANT(DRAW_ORDER_INDEX);
  938. BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME);
  939. ////////////////////////////////
  940. ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &CPUParticles2D::set_spread);
  941. ClassDB::bind_method(D_METHOD("get_spread"), &CPUParticles2D::get_spread);
  942. ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &CPUParticles2D::set_flatness);
  943. ClassDB::bind_method(D_METHOD("get_flatness"), &CPUParticles2D::get_flatness);
  944. ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &CPUParticles2D::set_param);
  945. ClassDB::bind_method(D_METHOD("get_param", "param"), &CPUParticles2D::get_param);
  946. ClassDB::bind_method(D_METHOD("set_param_randomness", "param", "randomness"), &CPUParticles2D::set_param_randomness);
  947. ClassDB::bind_method(D_METHOD("get_param_randomness", "param"), &CPUParticles2D::get_param_randomness);
  948. ClassDB::bind_method(D_METHOD("set_param_curve", "param", "curve"), &CPUParticles2D::set_param_curve);
  949. ClassDB::bind_method(D_METHOD("get_param_curve", "param"), &CPUParticles2D::get_param_curve);
  950. ClassDB::bind_method(D_METHOD("set_color", "color"), &CPUParticles2D::set_color);
  951. ClassDB::bind_method(D_METHOD("get_color"), &CPUParticles2D::get_color);
  952. ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp"), &CPUParticles2D::set_color_ramp);
  953. ClassDB::bind_method(D_METHOD("get_color_ramp"), &CPUParticles2D::get_color_ramp);
  954. ClassDB::bind_method(D_METHOD("set_particle_flag", "flag", "enable"), &CPUParticles2D::set_particle_flag);
  955. ClassDB::bind_method(D_METHOD("get_particle_flag", "flag"), &CPUParticles2D::get_particle_flag);
  956. ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &CPUParticles2D::set_emission_shape);
  957. ClassDB::bind_method(D_METHOD("get_emission_shape"), &CPUParticles2D::get_emission_shape);
  958. ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &CPUParticles2D::set_emission_sphere_radius);
  959. ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &CPUParticles2D::get_emission_sphere_radius);
  960. ClassDB::bind_method(D_METHOD("set_emission_rect_extents", "extents"), &CPUParticles2D::set_emission_rect_extents);
  961. ClassDB::bind_method(D_METHOD("get_emission_rect_extents"), &CPUParticles2D::get_emission_rect_extents);
  962. ClassDB::bind_method(D_METHOD("set_emission_points", "array"), &CPUParticles2D::set_emission_points);
  963. ClassDB::bind_method(D_METHOD("get_emission_points"), &CPUParticles2D::get_emission_points);
  964. ClassDB::bind_method(D_METHOD("set_emission_normals", "array"), &CPUParticles2D::set_emission_normals);
  965. ClassDB::bind_method(D_METHOD("get_emission_normals"), &CPUParticles2D::get_emission_normals);
  966. ClassDB::bind_method(D_METHOD("set_emission_colors", "array"), &CPUParticles2D::set_emission_colors);
  967. ClassDB::bind_method(D_METHOD("get_emission_colors"), &CPUParticles2D::get_emission_colors);
  968. ClassDB::bind_method(D_METHOD("get_gravity"), &CPUParticles2D::get_gravity);
  969. ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &CPUParticles2D::set_gravity);
  970. ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles2D::convert_from_particles);
  971. ClassDB::bind_method(D_METHOD("_update_render_thread"), &CPUParticles2D::_update_render_thread);
  972. ADD_GROUP("Emission Shape", "emission_");
  973. ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape");
  974. ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius");
  975. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "emission_rect_extents"), "set_emission_rect_extents", "get_emission_rect_extents");
  976. ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "emission_points"), "set_emission_points", "get_emission_points");
  977. ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals");
  978. ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "emission_colors"), "set_emission_colors", "get_emission_colors");
  979. ADD_GROUP("Flags", "flag_");
  980. ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_align_y"), "set_particle_flag", "get_particle_flag", FLAG_ALIGN_Y_TO_VELOCITY);
  981. ADD_GROUP("Spread", "");
  982. ADD_PROPERTY(PropertyInfo(Variant::REAL, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread");
  983. ADD_PROPERTY(PropertyInfo(Variant::REAL, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness");
  984. ADD_GROUP("Gravity", "");
  985. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity"), "set_gravity", "get_gravity");
  986. ADD_GROUP("Initial Velocity", "initial_");
  987. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_INITIAL_LINEAR_VELOCITY);
  988. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_INITIAL_LINEAR_VELOCITY);
  989. ADD_GROUP("Angular Velocity", "angular_");
  990. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity", PROPERTY_HINT_RANGE, "-720,720,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGULAR_VELOCITY);
  991. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGULAR_VELOCITY);
  992. ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angular_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGULAR_VELOCITY);
  993. /*
  994. ADD_GROUP("Orbit Velocity", "orbit_");
  995. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ORBIT_VELOCITY);
  996. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ORBIT_VELOCITY);
  997. ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orbit_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ORBIT_VELOCITY);
  998. */
  999. ADD_GROUP("Linear Accel", "linear_");
  1000. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_LINEAR_ACCEL);
  1001. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_LINEAR_ACCEL);
  1002. ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "linear_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_LINEAR_ACCEL);
  1003. ADD_GROUP("Radial Accel", "radial_");
  1004. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_RADIAL_ACCEL);
  1005. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_RADIAL_ACCEL);
  1006. ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "radial_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_RADIAL_ACCEL);
  1007. ADD_GROUP("Tangential Accel", "tangential_");
  1008. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_TANGENTIAL_ACCEL);
  1009. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL);
  1010. ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_TANGENTIAL_ACCEL);
  1011. ADD_GROUP("Damping", "");
  1012. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param", "get_param", PARAM_DAMPING);
  1013. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING);
  1014. ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_DAMPING);
  1015. ADD_GROUP("Angle", "");
  1016. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGLE);
  1017. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE);
  1018. ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGLE);
  1019. ADD_GROUP("Scale", "");
  1020. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale_amount", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_SCALE);
  1021. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale_amount_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_SCALE);
  1022. ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "scale_amount_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_SCALE);
  1023. ADD_GROUP("Color", "");
  1024. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
  1025. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_color_ramp", "get_color_ramp");
  1026. ADD_GROUP("Hue Variation", "hue_");
  1027. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION);
  1028. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION);
  1029. ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_HUE_VARIATION);
  1030. ADD_GROUP("Animation", "anim_");
  1031. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_param", "get_param", PARAM_ANIM_SPEED);
  1032. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_SPEED);
  1033. ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_speed_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANIM_SPEED);
  1034. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_ANIM_OFFSET);
  1035. ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET);
  1036. ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANIM_OFFSET);
  1037. BIND_ENUM_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY);
  1038. BIND_ENUM_CONSTANT(PARAM_ANGULAR_VELOCITY);
  1039. BIND_ENUM_CONSTANT(PARAM_ORBIT_VELOCITY);
  1040. BIND_ENUM_CONSTANT(PARAM_LINEAR_ACCEL);
  1041. BIND_ENUM_CONSTANT(PARAM_RADIAL_ACCEL);
  1042. BIND_ENUM_CONSTANT(PARAM_TANGENTIAL_ACCEL);
  1043. BIND_ENUM_CONSTANT(PARAM_DAMPING);
  1044. BIND_ENUM_CONSTANT(PARAM_ANGLE);
  1045. BIND_ENUM_CONSTANT(PARAM_SCALE);
  1046. BIND_ENUM_CONSTANT(PARAM_HUE_VARIATION);
  1047. BIND_ENUM_CONSTANT(PARAM_ANIM_SPEED);
  1048. BIND_ENUM_CONSTANT(PARAM_ANIM_OFFSET);
  1049. BIND_ENUM_CONSTANT(PARAM_MAX);
  1050. BIND_ENUM_CONSTANT(FLAG_ALIGN_Y_TO_VELOCITY);
  1051. BIND_ENUM_CONSTANT(FLAG_MAX);
  1052. BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINT);
  1053. BIND_ENUM_CONSTANT(EMISSION_SHAPE_CIRCLE);
  1054. BIND_ENUM_CONSTANT(EMISSION_SHAPE_RECTANGLE);
  1055. BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS);
  1056. BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS);
  1057. }
  1058. CPUParticles2D::CPUParticles2D() {
  1059. time = 0;
  1060. inactive_time = 0;
  1061. frame_remainder = 0;
  1062. cycle = 0;
  1063. mesh = VisualServer::get_singleton()->mesh_create();
  1064. multimesh = VisualServer::get_singleton()->multimesh_create();
  1065. VisualServer::get_singleton()->multimesh_set_mesh(multimesh, mesh);
  1066. set_emitting(true);
  1067. set_one_shot(false);
  1068. set_amount(8);
  1069. set_lifetime(1);
  1070. set_fixed_fps(0);
  1071. set_fractional_delta(true);
  1072. set_pre_process_time(0);
  1073. set_explosiveness_ratio(0);
  1074. set_randomness_ratio(0);
  1075. set_use_local_coordinates(true);
  1076. set_draw_order(DRAW_ORDER_INDEX);
  1077. set_speed_scale(1);
  1078. set_spread(45);
  1079. set_flatness(0);
  1080. set_param(PARAM_INITIAL_LINEAR_VELOCITY, 1);
  1081. //set_param(PARAM_ORBIT_VELOCITY, 0);
  1082. set_param(PARAM_LINEAR_ACCEL, 0);
  1083. set_param(PARAM_RADIAL_ACCEL, 0);
  1084. set_param(PARAM_TANGENTIAL_ACCEL, 0);
  1085. set_param(PARAM_DAMPING, 0);
  1086. set_param(PARAM_ANGLE, 0);
  1087. set_param(PARAM_SCALE, 1);
  1088. set_param(PARAM_HUE_VARIATION, 0);
  1089. set_param(PARAM_ANIM_SPEED, 0);
  1090. set_param(PARAM_ANIM_OFFSET, 0);
  1091. set_emission_shape(EMISSION_SHAPE_POINT);
  1092. set_emission_sphere_radius(1);
  1093. set_emission_rect_extents(Vector2(1, 1));
  1094. set_gravity(Vector2(0, 98.8));
  1095. for (int i = 0; i < PARAM_MAX; i++) {
  1096. set_param_randomness(Parameter(i), 0);
  1097. }
  1098. for (int i = 0; i < FLAG_MAX; i++) {
  1099. flags[i] = false;
  1100. }
  1101. set_color(Color(1, 1, 1, 1));
  1102. #ifndef NO_THREADS
  1103. update_mutex = Mutex::create();
  1104. #endif
  1105. _update_mesh_texture();
  1106. }
  1107. CPUParticles2D::~CPUParticles2D() {
  1108. VS::get_singleton()->free(multimesh);
  1109. VS::get_singleton()->free(mesh);
  1110. #ifndef NO_THREADS
  1111. memdelete(update_mutex);
  1112. #endif
  1113. }