2018-08-29 22:38:13 +02:00
|
|
|
/*************************************************************************/
|
2020-03-26 22:49:16 +01:00
|
|
|
/* cpu_particles_3d.cpp */
|
2018-08-29 22:38:13 +02:00
|
|
|
/*************************************************************************/
|
|
|
|
/* This file is part of: */
|
|
|
|
/* GODOT ENGINE */
|
|
|
|
/* https://godotengine.org */
|
|
|
|
/*************************************************************************/
|
2021-01-01 20:13:46 +01:00
|
|
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
|
|
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
2018-08-29 22:38:13 +02:00
|
|
|
/* */
|
|
|
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
|
|
/* a copy of this software and associated documentation files (the */
|
|
|
|
/* "Software"), to deal in the Software without restriction, including */
|
|
|
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
|
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
|
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
|
|
/* the following conditions: */
|
|
|
|
/* */
|
|
|
|
/* The above copyright notice and this permission notice shall be */
|
|
|
|
/* included in all copies or substantial portions of the Software. */
|
|
|
|
/* */
|
|
|
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
|
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
|
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
|
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
|
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
|
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
#include "cpu_particles_3d.h"
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
#include "scene/3d/camera_3d.h"
|
|
|
|
#include "scene/3d/gpu_particles_3d.h"
|
2021-08-13 01:05:59 +02:00
|
|
|
#include "scene/main/viewport.h"
|
2018-09-04 11:30:04 +02:00
|
|
|
#include "scene/resources/particles_material.h"
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
AABB CPUParticles3D::get_aabb() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return AABB();
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2020-12-05 00:35:57 +01:00
|
|
|
Vector<Face3> CPUParticles3D::get_faces(uint32_t p_usage_particle_flags) const {
|
2020-02-17 22:06:54 +01:00
|
|
|
return Vector<Face3>();
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_emitting(bool p_emitting) {
|
2020-05-14 16:41:43 +02:00
|
|
|
if (emitting == p_emitting) {
|
2019-10-19 17:30:13 +02:00
|
|
|
return;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2019-10-19 17:30:13 +02:00
|
|
|
|
2018-07-07 01:21:13 +02:00
|
|
|
emitting = p_emitting;
|
2019-10-19 17:30:13 +02:00
|
|
|
if (emitting) {
|
2019-03-20 10:50:56 +01:00
|
|
|
set_process_internal(true);
|
2019-10-19 17:30:13 +02:00
|
|
|
|
|
|
|
// first update before rendering to avoid one frame delay after emitting starts
|
2020-05-14 16:41:43 +02:00
|
|
|
if (time == 0) {
|
2019-10-19 17:30:13 +02:00
|
|
|
_update_internal();
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2019-10-19 17:30:13 +02:00
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_amount(int p_amount) {
|
2019-09-25 10:28:50 +02:00
|
|
|
ERR_FAIL_COND_MSG(p_amount < 1, "Amount of particles must be greater than 0.");
|
2018-07-07 01:21:13 +02:00
|
|
|
|
|
|
|
particles.resize(p_amount);
|
|
|
|
{
|
2020-02-17 22:06:54 +01:00
|
|
|
Particle *w = particles.ptrw();
|
2018-07-07 01:21:13 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < p_amount; i++) {
|
|
|
|
w[i].active = false;
|
2020-02-06 12:06:05 +01:00
|
|
|
w[i].custom[3] = 0.0; // Make sure w component isn't garbage data
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-05 16:35:10 +02:00
|
|
|
particle_data.resize((12 + 4 + 4) * p_amount);
|
2021-02-09 17:19:03 +01:00
|
|
|
RS::get_singleton()->multimesh_allocate_data(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_3D, true, true);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
|
|
|
particle_order.resize(p_amount);
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
void CPUParticles3D::set_lifetime(double p_lifetime) {
|
2019-09-25 10:28:50 +02:00
|
|
|
ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0.");
|
2018-07-07 01:21:13 +02:00
|
|
|
lifetime = p_lifetime;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_one_shot(bool p_one_shot) {
|
2018-07-07 01:21:13 +02:00
|
|
|
one_shot = p_one_shot;
|
|
|
|
}
|
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
void CPUParticles3D::set_pre_process_time(double p_time) {
|
2018-07-07 01:21:13 +02:00
|
|
|
pre_process_time = p_time;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
void CPUParticles3D::set_explosiveness_ratio(real_t p_ratio) {
|
2018-07-07 01:21:13 +02:00
|
|
|
explosiveness_ratio = p_ratio;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
void CPUParticles3D::set_randomness_ratio(real_t p_ratio) {
|
2018-07-07 01:21:13 +02:00
|
|
|
randomness_ratio = p_ratio;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
void CPUParticles3D::set_lifetime_randomness(double p_random) {
|
2019-07-15 06:48:20 +02:00
|
|
|
lifetime_randomness = p_random;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_use_local_coordinates(bool p_enable) {
|
2018-07-07 01:21:13 +02:00
|
|
|
local_coords = p_enable;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
void CPUParticles3D::set_speed_scale(double p_scale) {
|
2018-07-07 01:21:13 +02:00
|
|
|
speed_scale = p_scale;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
bool CPUParticles3D::is_emitting() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return emitting;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
int CPUParticles3D::get_amount() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return particles.size();
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
double CPUParticles3D::get_lifetime() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return lifetime;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
bool CPUParticles3D::get_one_shot() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return one_shot;
|
|
|
|
}
|
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
double CPUParticles3D::get_pre_process_time() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return pre_process_time;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t CPUParticles3D::get_explosiveness_ratio() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return explosiveness_ratio;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t CPUParticles3D::get_randomness_ratio() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return randomness_ratio;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
double CPUParticles3D::get_lifetime_randomness() const {
|
2019-07-15 06:48:20 +02:00
|
|
|
return lifetime_randomness;
|
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
bool CPUParticles3D::get_use_local_coordinates() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return local_coords;
|
|
|
|
}
|
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
double CPUParticles3D::get_speed_scale() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return speed_scale;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_draw_order(DrawOrder p_order) {
|
2021-02-17 15:30:03 +01:00
|
|
|
ERR_FAIL_INDEX(p_order, DRAW_ORDER_MAX);
|
2018-07-07 01:21:13 +02:00
|
|
|
draw_order = p_order;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
CPUParticles3D::DrawOrder CPUParticles3D::get_draw_order() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return draw_order;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_mesh(const Ref<Mesh> &p_mesh) {
|
2018-07-07 01:21:13 +02:00
|
|
|
mesh = p_mesh;
|
|
|
|
if (mesh.is_valid()) {
|
2020-03-27 19:21:27 +01:00
|
|
|
RS::get_singleton()->multimesh_set_mesh(multimesh, mesh->get_rid());
|
2018-07-07 01:21:13 +02:00
|
|
|
} else {
|
2020-03-27 19:21:27 +01:00
|
|
|
RS::get_singleton()->multimesh_set_mesh(multimesh, RID());
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
Ref<Mesh> CPUParticles3D::get_mesh() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return mesh;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_fixed_fps(int p_count) {
|
2018-07-07 01:21:13 +02:00
|
|
|
fixed_fps = p_count;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
int CPUParticles3D::get_fixed_fps() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return fixed_fps;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_fractional_delta(bool p_enable) {
|
2018-07-07 01:21:13 +02:00
|
|
|
fractional_delta = p_enable;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
bool CPUParticles3D::get_fractional_delta() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return fractional_delta;
|
|
|
|
}
|
|
|
|
|
2020-10-29 11:01:28 +01:00
|
|
|
TypedArray<String> CPUParticles3D::get_configuration_warnings() const {
|
|
|
|
TypedArray<String> warnings = Node::get_configuration_warnings();
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2018-11-13 18:19:16 +01:00
|
|
|
bool mesh_found = false;
|
|
|
|
bool anim_material_found = false;
|
|
|
|
|
|
|
|
if (get_mesh().is_valid()) {
|
|
|
|
mesh_found = true;
|
|
|
|
for (int j = 0; j < get_mesh()->get_surface_count(); j++) {
|
2020-04-02 01:20:12 +02:00
|
|
|
anim_material_found = Object::cast_to<ShaderMaterial>(get_mesh()->surface_get_material(j).ptr()) != nullptr;
|
2019-09-15 06:01:52 +02:00
|
|
|
StandardMaterial3D *spat = Object::cast_to<StandardMaterial3D>(get_mesh()->surface_get_material(j).ptr());
|
|
|
|
anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES);
|
2018-11-13 18:19:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-02 01:20:12 +02:00
|
|
|
anim_material_found = anim_material_found || Object::cast_to<ShaderMaterial>(get_material_override().ptr()) != nullptr;
|
2019-09-15 06:01:52 +02:00
|
|
|
StandardMaterial3D *spat = Object::cast_to<StandardMaterial3D>(get_material_override().ptr());
|
|
|
|
anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES);
|
2018-11-13 18:19:16 +01:00
|
|
|
|
|
|
|
if (!mesh_found) {
|
2020-10-29 11:01:28 +01:00
|
|
|
warnings.push_back(TTR("Nothing is visible because no mesh has been assigned."));
|
2018-11-13 18:19:16 +01:00
|
|
|
}
|
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
if (!anim_material_found && (get_param_max(PARAM_ANIM_SPEED) != 0.0 || get_param_max(PARAM_ANIM_OFFSET) != 0.0 ||
|
2018-11-13 18:19:16 +01:00
|
|
|
get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid())) {
|
2020-10-29 11:01:28 +01:00
|
|
|
warnings.push_back(TTR("CPUParticles3D animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\"."));
|
2018-11-13 18:19:16 +01:00
|
|
|
}
|
|
|
|
|
2018-07-07 01:21:13 +02:00
|
|
|
return warnings;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::restart() {
|
2018-07-07 01:21:13 +02:00
|
|
|
time = 0;
|
|
|
|
inactive_time = 0;
|
|
|
|
frame_remainder = 0;
|
|
|
|
cycle = 0;
|
2019-10-24 21:38:01 +02:00
|
|
|
emitting = false;
|
2019-06-22 07:33:11 +02:00
|
|
|
|
2018-07-07 01:21:13 +02:00
|
|
|
{
|
|
|
|
int pc = particles.size();
|
2020-02-17 22:06:54 +01:00
|
|
|
Particle *w = particles.ptrw();
|
2018-07-07 01:21:13 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < pc; i++) {
|
|
|
|
w[i].active = false;
|
|
|
|
}
|
|
|
|
}
|
2019-10-24 21:38:01 +02:00
|
|
|
|
|
|
|
set_emitting(true);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_direction(Vector3 p_direction) {
|
2019-03-04 23:45:53 +01:00
|
|
|
direction = p_direction;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
Vector3 CPUParticles3D::get_direction() const {
|
2019-03-04 23:45:53 +01:00
|
|
|
return direction;
|
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
void CPUParticles3D::set_spread(real_t p_spread) {
|
2018-07-07 01:21:13 +02:00
|
|
|
spread = p_spread;
|
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t CPUParticles3D::get_spread() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return spread;
|
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
void CPUParticles3D::set_flatness(real_t p_flatness) {
|
2018-07-07 01:21:13 +02:00
|
|
|
flatness = p_flatness;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t CPUParticles3D::get_flatness() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return flatness;
|
|
|
|
}
|
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
void CPUParticles3D::set_param_min(Parameter p_param, real_t p_value) {
|
2018-07-07 01:21:13 +02:00
|
|
|
ERR_FAIL_INDEX(p_param, PARAM_MAX);
|
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
parameters_min[p_param] = p_value;
|
|
|
|
if (parameters_min[p_param] > parameters_max[p_param]) {
|
|
|
|
set_param_max(p_param, p_value);
|
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
real_t CPUParticles3D::get_param_min(Parameter p_param) const {
|
2018-07-07 01:21:13 +02:00
|
|
|
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
|
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
return parameters_min[p_param];
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
void CPUParticles3D::set_param_max(Parameter p_param, real_t p_value) {
|
2018-07-07 01:21:13 +02:00
|
|
|
ERR_FAIL_INDEX(p_param, PARAM_MAX);
|
2021-07-13 19:46:27 +02:00
|
|
|
parameters_max[p_param] = p_value;
|
|
|
|
if (parameters_min[p_param] > parameters_max[p_param]) {
|
|
|
|
set_param_min(p_param, p_value);
|
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
real_t CPUParticles3D::get_param_max(Parameter p_param) const {
|
2018-07-07 01:21:13 +02:00
|
|
|
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
|
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
return parameters_max[p_param];
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
static void _adjust_curve_range(const Ref<Curve> &p_curve, real_t p_min, real_t p_max) {
|
2018-07-07 01:21:13 +02:00
|
|
|
Ref<Curve> curve = p_curve;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (!curve.is_valid()) {
|
2018-07-07 01:21:13 +02:00
|
|
|
return;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
|
|
|
|
curve->ensure_default_setup(p_min, p_max);
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_param_curve(Parameter p_param, const Ref<Curve> &p_curve) {
|
2018-07-07 01:21:13 +02:00
|
|
|
ERR_FAIL_INDEX(p_param, PARAM_MAX);
|
|
|
|
|
|
|
|
curve_parameters[p_param] = p_curve;
|
|
|
|
|
|
|
|
switch (p_param) {
|
|
|
|
case PARAM_INITIAL_LINEAR_VELOCITY: {
|
|
|
|
//do none for this one
|
|
|
|
} break;
|
|
|
|
case PARAM_ANGULAR_VELOCITY: {
|
|
|
|
_adjust_curve_range(p_curve, -360, 360);
|
|
|
|
} break;
|
2019-06-11 17:47:24 +02:00
|
|
|
case PARAM_ORBIT_VELOCITY: {
|
2018-07-07 01:21:13 +02:00
|
|
|
_adjust_curve_range(p_curve, -500, 500);
|
2019-06-11 17:47:24 +02:00
|
|
|
} break;
|
2018-07-07 01:21:13 +02:00
|
|
|
case PARAM_LINEAR_ACCEL: {
|
|
|
|
_adjust_curve_range(p_curve, -200, 200);
|
|
|
|
} break;
|
|
|
|
case PARAM_RADIAL_ACCEL: {
|
|
|
|
_adjust_curve_range(p_curve, -200, 200);
|
|
|
|
} break;
|
|
|
|
case PARAM_TANGENTIAL_ACCEL: {
|
|
|
|
_adjust_curve_range(p_curve, -200, 200);
|
|
|
|
} break;
|
|
|
|
case PARAM_DAMPING: {
|
|
|
|
_adjust_curve_range(p_curve, 0, 100);
|
|
|
|
} break;
|
|
|
|
case PARAM_ANGLE: {
|
|
|
|
_adjust_curve_range(p_curve, -360, 360);
|
|
|
|
} break;
|
|
|
|
case PARAM_SCALE: {
|
|
|
|
} break;
|
|
|
|
case PARAM_HUE_VARIATION: {
|
|
|
|
_adjust_curve_range(p_curve, -1, 1);
|
|
|
|
} break;
|
|
|
|
case PARAM_ANIM_SPEED: {
|
|
|
|
_adjust_curve_range(p_curve, 0, 200);
|
|
|
|
} break;
|
|
|
|
case PARAM_ANIM_OFFSET: {
|
|
|
|
} break;
|
2019-03-09 02:50:44 +01:00
|
|
|
default: {
|
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
Ref<Curve> CPUParticles3D::get_param_curve(Parameter p_param) const {
|
2018-07-07 01:21:13 +02:00
|
|
|
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref<Curve>());
|
|
|
|
|
|
|
|
return curve_parameters[p_param];
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_color(const Color &p_color) {
|
2018-07-07 01:21:13 +02:00
|
|
|
color = p_color;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
Color CPUParticles3D::get_color() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return color;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_color_ramp(const Ref<Gradient> &p_ramp) {
|
2018-07-07 01:21:13 +02:00
|
|
|
color_ramp = p_ramp;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
Ref<Gradient> CPUParticles3D::get_color_ramp() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return color_ramp;
|
|
|
|
}
|
|
|
|
|
2020-12-05 00:35:57 +01:00
|
|
|
void CPUParticles3D::set_particle_flag(ParticleFlags p_particle_flag, bool p_enable) {
|
|
|
|
ERR_FAIL_INDEX(p_particle_flag, PARTICLE_FLAG_MAX);
|
|
|
|
particle_flags[p_particle_flag] = p_enable;
|
|
|
|
if (p_particle_flag == PARTICLE_FLAG_DISABLE_Z) {
|
2021-02-10 21:18:45 +01:00
|
|
|
notify_property_list_changed();
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-05 00:35:57 +01:00
|
|
|
bool CPUParticles3D::get_particle_flag(ParticleFlags p_particle_flag) const {
|
|
|
|
ERR_FAIL_INDEX_V(p_particle_flag, PARTICLE_FLAG_MAX, false);
|
|
|
|
return particle_flags[p_particle_flag];
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_emission_shape(EmissionShape p_shape) {
|
2020-01-16 10:59:01 +01:00
|
|
|
ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX);
|
2018-07-07 01:21:13 +02:00
|
|
|
emission_shape = p_shape;
|
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
void CPUParticles3D::set_emission_sphere_radius(real_t p_radius) {
|
2018-07-07 01:21:13 +02:00
|
|
|
emission_sphere_radius = p_radius;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_emission_box_extents(Vector3 p_extents) {
|
2018-07-07 01:21:13 +02:00
|
|
|
emission_box_extents = p_extents;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_emission_points(const Vector<Vector3> &p_points) {
|
2018-07-07 01:21:13 +02:00
|
|
|
emission_points = p_points;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_emission_normals(const Vector<Vector3> &p_normals) {
|
2018-07-07 01:21:13 +02:00
|
|
|
emission_normals = p_normals;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_emission_colors(const Vector<Color> &p_colors) {
|
2018-07-07 01:21:13 +02:00
|
|
|
emission_colors = p_colors;
|
|
|
|
}
|
|
|
|
|
2021-07-11 15:45:21 +02:00
|
|
|
void CPUParticles3D::set_emission_ring_axis(Vector3 p_axis) {
|
|
|
|
emission_ring_axis = p_axis;
|
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
void CPUParticles3D::set_emission_ring_height(real_t p_height) {
|
2021-07-11 15:45:21 +02:00
|
|
|
emission_ring_height = p_height;
|
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
void CPUParticles3D::set_emission_ring_radius(real_t p_radius) {
|
2021-07-11 15:45:21 +02:00
|
|
|
emission_ring_radius = p_radius;
|
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
void CPUParticles3D::set_emission_ring_inner_radius(real_t p_radius) {
|
2021-07-11 15:45:21 +02:00
|
|
|
emission_ring_inner_radius = p_radius;
|
|
|
|
}
|
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
void CPUParticles3D::set_scale_curve_x(Ref<Curve> p_scale_curve) {
|
|
|
|
scale_curve_x = p_scale_curve;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPUParticles3D::set_scale_curve_y(Ref<Curve> p_scale_curve) {
|
|
|
|
scale_curve_y = p_scale_curve;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPUParticles3D::set_scale_curve_z(Ref<Curve> p_scale_curve) {
|
|
|
|
scale_curve_z = p_scale_curve;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPUParticles3D::set_split_scale(bool p_split_scale) {
|
|
|
|
split_scale = p_split_scale;
|
|
|
|
notify_property_list_changed();
|
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t CPUParticles3D::get_emission_sphere_radius() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return emission_sphere_radius;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
Vector3 CPUParticles3D::get_emission_box_extents() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return emission_box_extents;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
Vector<Vector3> CPUParticles3D::get_emission_points() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return emission_points;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
Vector<Vector3> CPUParticles3D::get_emission_normals() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return emission_normals;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
Vector<Color> CPUParticles3D::get_emission_colors() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return emission_colors;
|
|
|
|
}
|
|
|
|
|
2021-07-11 15:45:21 +02:00
|
|
|
Vector3 CPUParticles3D::get_emission_ring_axis() const {
|
|
|
|
return emission_ring_axis;
|
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t CPUParticles3D::get_emission_ring_height() const {
|
2021-07-11 15:45:21 +02:00
|
|
|
return emission_ring_height;
|
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t CPUParticles3D::get_emission_ring_radius() const {
|
2021-07-11 15:45:21 +02:00
|
|
|
return emission_ring_radius;
|
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t CPUParticles3D::get_emission_ring_inner_radius() const {
|
2021-07-11 15:45:21 +02:00
|
|
|
return emission_ring_inner_radius;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
CPUParticles3D::EmissionShape CPUParticles3D::get_emission_shape() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return emission_shape;
|
|
|
|
}
|
2020-05-14 14:29:06 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::set_gravity(const Vector3 &p_gravity) {
|
2018-07-07 01:21:13 +02:00
|
|
|
gravity = p_gravity;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
Vector3 CPUParticles3D::get_gravity() const {
|
2018-07-07 01:21:13 +02:00
|
|
|
return gravity;
|
|
|
|
}
|
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
Ref<Curve> CPUParticles3D::get_scale_curve_x() const {
|
|
|
|
return scale_curve_x;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ref<Curve> CPUParticles3D::get_scale_curve_y() const {
|
|
|
|
return scale_curve_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ref<Curve> CPUParticles3D::get_scale_curve_z() const {
|
|
|
|
return scale_curve_z;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CPUParticles3D::get_split_scale() {
|
|
|
|
return split_scale;
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::_validate_property(PropertyInfo &property) const {
|
2018-07-07 01:21:13 +02:00
|
|
|
if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) {
|
2021-07-01 03:24:34 +02:00
|
|
|
property.usage = PROPERTY_USAGE_NONE;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (property.name == "emission_box_extents" && emission_shape != EMISSION_SHAPE_BOX) {
|
2021-07-01 03:24:34 +02:00
|
|
|
property.usage = PROPERTY_USAGE_NONE;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-07-11 15:45:21 +02:00
|
|
|
if ((property.name == "emission_point_texture" || property.name == "emission_color_texture" || property.name == "emission_points") && (emission_shape != EMISSION_SHAPE_POINTS && (emission_shape != EMISSION_SHAPE_DIRECTED_POINTS))) {
|
2021-07-01 03:24:34 +02:00
|
|
|
property.usage = PROPERTY_USAGE_NONE;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (property.name == "emission_normals" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
|
2021-07-01 03:24:34 +02:00
|
|
|
property.usage = PROPERTY_USAGE_NONE;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
2019-06-11 17:47:24 +02:00
|
|
|
|
2021-07-11 15:45:21 +02:00
|
|
|
if (property.name.begins_with("emission_ring_") && emission_shape != EMISSION_SHAPE_RING) {
|
|
|
|
property.usage = PROPERTY_USAGE_NONE;
|
|
|
|
}
|
|
|
|
|
2020-12-05 00:35:57 +01:00
|
|
|
if (property.name.begins_with("orbit_") && !particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
|
2021-07-01 03:24:34 +02:00
|
|
|
property.usage = PROPERTY_USAGE_NONE;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
2021-07-13 19:46:27 +02:00
|
|
|
|
|
|
|
if (property.name.begins_with("scale_curve_") && !split_scale) {
|
|
|
|
property.usage = PROPERTY_USAGE_NONE;
|
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t idhash(uint32_t x) {
|
|
|
|
x = ((x >> uint32_t(16)) ^ x) * uint32_t(0x45d9f3b);
|
|
|
|
x = ((x >> uint32_t(16)) ^ x) * uint32_t(0x45d9f3b);
|
|
|
|
x = (x >> uint32_t(16)) ^ x;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
static real_t rand_from_seed(uint32_t &seed) {
|
2018-07-07 01:21:13 +02:00
|
|
|
int k;
|
|
|
|
int s = int(seed);
|
2020-05-14 16:41:43 +02:00
|
|
|
if (s == 0) {
|
2018-07-07 01:21:13 +02:00
|
|
|
s = 305420679;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
k = s / 127773;
|
|
|
|
s = 16807 * (s - k * 127773) - 2836 * k;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (s < 0) {
|
2018-07-07 01:21:13 +02:00
|
|
|
s += 2147483647;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
seed = uint32_t(s);
|
2021-01-30 01:55:54 +01:00
|
|
|
return (seed % uint32_t(65536)) / 65535.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::_update_internal() {
|
2019-10-19 17:30:13 +02:00
|
|
|
if (particles.size() == 0 || !is_visible_in_tree()) {
|
|
|
|
_set_redraw(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
double delta = get_process_delta_time();
|
2019-10-19 17:30:13 +02:00
|
|
|
if (emitting) {
|
|
|
|
inactive_time = 0;
|
|
|
|
} else {
|
|
|
|
inactive_time += delta;
|
|
|
|
if (inactive_time > lifetime * 1.2) {
|
|
|
|
set_process_internal(false);
|
|
|
|
_set_redraw(false);
|
|
|
|
|
|
|
|
//reset variables
|
|
|
|
time = 0;
|
|
|
|
inactive_time = 0;
|
|
|
|
frame_remainder = 0;
|
|
|
|
cycle = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_set_redraw(true);
|
|
|
|
|
|
|
|
bool processed = false;
|
|
|
|
|
|
|
|
if (time == 0 && pre_process_time > 0.0) {
|
2021-02-02 03:16:37 +01:00
|
|
|
double frame_time;
|
2020-05-14 16:41:43 +02:00
|
|
|
if (fixed_fps > 0) {
|
2019-10-19 17:30:13 +02:00
|
|
|
frame_time = 1.0 / fixed_fps;
|
2020-05-14 16:41:43 +02:00
|
|
|
} else {
|
2019-10-19 17:30:13 +02:00
|
|
|
frame_time = 1.0 / 30.0;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2019-10-19 17:30:13 +02:00
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
double todo = pre_process_time;
|
2019-10-19 17:30:13 +02:00
|
|
|
|
|
|
|
while (todo >= 0) {
|
|
|
|
_particles_process(frame_time);
|
|
|
|
processed = true;
|
|
|
|
todo -= frame_time;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fixed_fps > 0) {
|
2021-02-02 03:16:37 +01:00
|
|
|
double frame_time = 1.0 / fixed_fps;
|
|
|
|
double decr = frame_time;
|
2019-10-19 17:30:13 +02:00
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
double ldelta = delta;
|
2019-10-19 17:30:13 +02:00
|
|
|
if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10
|
|
|
|
ldelta = 0.1;
|
|
|
|
} else if (ldelta <= 0.0) { //unlikely but..
|
|
|
|
ldelta = 0.001;
|
|
|
|
}
|
2021-02-02 03:16:37 +01:00
|
|
|
double todo = frame_remainder + ldelta;
|
2019-10-19 17:30:13 +02:00
|
|
|
|
|
|
|
while (todo >= frame_time) {
|
|
|
|
_particles_process(frame_time);
|
|
|
|
processed = true;
|
|
|
|
todo -= decr;
|
|
|
|
}
|
|
|
|
|
|
|
|
frame_remainder = todo;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
_particles_process(delta);
|
|
|
|
processed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (processed) {
|
|
|
|
_update_particle_data_buffer();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
void CPUParticles3D::_particles_process(double p_delta) {
|
2018-07-23 17:28:15 +02:00
|
|
|
p_delta *= speed_scale;
|
|
|
|
|
2018-07-07 01:21:13 +02:00
|
|
|
int pcount = particles.size();
|
2020-02-17 22:06:54 +01:00
|
|
|
Particle *w = particles.ptrw();
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
Particle *parray = w;
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
double prev_time = time;
|
2018-07-07 01:21:13 +02:00
|
|
|
time += p_delta;
|
|
|
|
if (time > lifetime) {
|
|
|
|
time = Math::fmod(time, lifetime);
|
|
|
|
cycle++;
|
|
|
|
if (one_shot && cycle > 0) {
|
2019-06-20 20:20:27 +02:00
|
|
|
set_emitting(false);
|
2021-02-10 21:18:45 +01:00
|
|
|
notify_property_list_changed();
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-17 07:08:21 +02:00
|
|
|
Transform3D emission_xform;
|
2018-07-07 01:21:13 +02:00
|
|
|
Basis velocity_xform;
|
|
|
|
if (!local_coords) {
|
|
|
|
emission_xform = get_global_transform();
|
2018-11-27 11:07:58 +01:00
|
|
|
velocity_xform = emission_xform.basis;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
double system_phase = time / lifetime;
|
2019-06-11 23:38:10 +02:00
|
|
|
|
2018-07-07 01:21:13 +02:00
|
|
|
for (int i = 0; i < pcount; i++) {
|
|
|
|
Particle &p = parray[i];
|
|
|
|
|
2020-05-14 16:41:43 +02:00
|
|
|
if (!emitting && !p.active) {
|
2018-07-07 01:21:13 +02:00
|
|
|
continue;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2021-02-02 03:16:37 +01:00
|
|
|
double local_delta = p_delta;
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2019-06-11 23:38:10 +02:00
|
|
|
// The phase is a ratio between 0 (birth) and 1 (end of life) for each particle.
|
|
|
|
// While we use time in tests later on, for randomness we use the phase as done in the
|
|
|
|
// original shader code, and we later multiply by lifetime to get the time.
|
2021-02-02 03:16:37 +01:00
|
|
|
double restart_phase = double(i) / double(pcount);
|
2019-06-11 23:38:10 +02:00
|
|
|
|
2018-07-07 01:21:13 +02:00
|
|
|
if (randomness_ratio > 0.0) {
|
|
|
|
uint32_t seed = cycle;
|
2019-06-11 23:38:10 +02:00
|
|
|
if (restart_phase >= system_phase) {
|
2018-07-07 01:21:13 +02:00
|
|
|
seed -= uint32_t(1);
|
|
|
|
}
|
|
|
|
seed *= uint32_t(pcount);
|
|
|
|
seed += uint32_t(i);
|
2021-02-02 03:16:37 +01:00
|
|
|
double random = double(idhash(seed) % uint32_t(65536)) / 65536.0;
|
|
|
|
restart_phase += randomness_ratio * random * 1.0 / double(pcount);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2019-06-11 23:38:10 +02:00
|
|
|
restart_phase *= (1.0 - explosiveness_ratio);
|
2021-02-02 03:16:37 +01:00
|
|
|
double restart_time = restart_phase * lifetime;
|
2018-07-07 01:21:13 +02:00
|
|
|
bool restart = false;
|
|
|
|
|
|
|
|
if (time > prev_time) {
|
|
|
|
// restart_time >= prev_time is used so particles emit in the first frame they are processed
|
|
|
|
|
|
|
|
if (restart_time >= prev_time && restart_time < time) {
|
|
|
|
restart = true;
|
|
|
|
if (fractional_delta) {
|
2019-03-10 00:33:08 +01:00
|
|
|
local_delta = time - restart_time;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (local_delta > 0.0) {
|
|
|
|
if (restart_time >= prev_time) {
|
|
|
|
restart = true;
|
|
|
|
if (fractional_delta) {
|
2019-03-10 00:33:08 +01:00
|
|
|
local_delta = lifetime - restart_time + time;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
} else if (restart_time < time) {
|
|
|
|
restart = true;
|
|
|
|
if (fractional_delta) {
|
2019-03-10 00:33:08 +01:00
|
|
|
local_delta = time - restart_time;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-15 06:48:20 +02:00
|
|
|
if (p.time * (1.0 - explosiveness_ratio) > p.lifetime) {
|
|
|
|
restart = true;
|
|
|
|
}
|
|
|
|
|
2021-01-27 12:18:07 +01:00
|
|
|
float tv = 0.0;
|
|
|
|
|
2018-07-07 01:21:13 +02:00
|
|
|
if (restart) {
|
|
|
|
if (!emitting) {
|
|
|
|
p.active = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
p.active = true;
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
/*real_t tex_linear_velocity = 0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
|
|
|
|
tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(0);
|
|
|
|
}*/
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_angle = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_ANGLE].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_anim_offset = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_ANGLE].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_anim_offset = curve_parameters[PARAM_ANGLE]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
p.seed = Math::rand();
|
|
|
|
|
|
|
|
p.angle_rand = Math::randf();
|
|
|
|
p.scale_rand = Math::randf();
|
|
|
|
p.hue_rot_rand = Math::randf();
|
|
|
|
p.anim_offset_rand = Math::randf();
|
|
|
|
|
2020-12-05 00:35:57 +01:00
|
|
|
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread);
|
2018-07-07 01:21:13 +02:00
|
|
|
Vector3 rot = Vector3(Math::cos(angle1_rad), Math::sin(angle1_rad), 0.0);
|
2021-07-13 19:46:27 +02:00
|
|
|
p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], Math::randf());
|
2018-07-07 01:21:13 +02:00
|
|
|
} else {
|
|
|
|
//initiate velocity spread in 3D
|
2021-08-12 14:36:30 +02:00
|
|
|
real_t angle1_rad = Math::deg2rad((Math::randf() * (real_t)2.0 - (real_t)1.0) * spread);
|
|
|
|
real_t angle2_rad = Math::deg2rad((Math::randf() * (real_t)2.0 - (real_t)1.0) * ((real_t)1.0 - flatness) * spread);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
|
|
|
Vector3 direction_xz = Vector3(Math::sin(angle1_rad), 0, Math::cos(angle1_rad));
|
|
|
|
Vector3 direction_yz = Vector3(0, Math::sin(angle2_rad), Math::cos(angle2_rad));
|
2021-08-12 14:36:30 +02:00
|
|
|
Vector3 spread_direction = Vector3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);
|
|
|
|
Vector3 direction_nrm = direction;
|
|
|
|
if (direction_nrm.length_squared() > 0) {
|
|
|
|
direction_nrm.normalize();
|
|
|
|
} else {
|
|
|
|
direction_nrm = Vector3(0, 0, 1);
|
|
|
|
}
|
|
|
|
// rotate spread to direction
|
|
|
|
Vector3 binormal = Vector3(0.0, 1.0, 0.0).cross(direction_nrm);
|
|
|
|
if (binormal.length_squared() < 0.00000001) {
|
|
|
|
// direction is parallel to Y. Choose Z as the binormal.
|
|
|
|
binormal = Vector3(0.0, 0.0, 1.0);
|
|
|
|
}
|
|
|
|
binormal.normalize();
|
|
|
|
Vector3 normal = binormal.cross(direction_nrm);
|
|
|
|
spread_direction = binormal * spread_direction.x + normal * spread_direction.y + direction_nrm * spread_direction.z;
|
2021-07-13 19:46:27 +02:00
|
|
|
p.velocity = spread_direction * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], float(Math::randf()));
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
real_t base_angle = tex_angle * Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand);
|
2018-07-07 01:21:13 +02:00
|
|
|
p.custom[0] = Math::deg2rad(base_angle); //angle
|
|
|
|
p.custom[1] = 0.0; //phase
|
2021-07-13 19:46:27 +02:00
|
|
|
p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand); //animation offset (0-1)
|
2020-10-17 07:08:21 +02:00
|
|
|
p.transform = Transform3D();
|
2018-07-07 01:21:13 +02:00
|
|
|
p.time = 0;
|
2019-07-15 06:48:20 +02:00
|
|
|
p.lifetime = lifetime * (1.0 - Math::randf() * lifetime_randomness);
|
2018-07-07 01:21:13 +02:00
|
|
|
p.base_color = Color(1, 1, 1, 1);
|
|
|
|
|
|
|
|
switch (emission_shape) {
|
|
|
|
case EMISSION_SHAPE_POINT: {
|
|
|
|
//do none
|
|
|
|
} break;
|
|
|
|
case EMISSION_SHAPE_SPHERE: {
|
2020-04-03 11:50:40 +02:00
|
|
|
real_t s = 2.0 * Math::randf() - 1.0;
|
|
|
|
real_t t = Math_TAU * Math::randf();
|
|
|
|
real_t radius = emission_sphere_radius * Math::sqrt(1.0 - s * s);
|
2019-07-06 00:13:03 +02:00
|
|
|
p.transform.origin = Vector3(radius * Math::cos(t), radius * Math::sin(t), emission_sphere_radius * s);
|
2018-07-07 01:21:13 +02:00
|
|
|
} break;
|
|
|
|
case EMISSION_SHAPE_BOX: {
|
|
|
|
p.transform.origin = Vector3(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0) * emission_box_extents;
|
|
|
|
} break;
|
|
|
|
case EMISSION_SHAPE_POINTS:
|
|
|
|
case EMISSION_SHAPE_DIRECTED_POINTS: {
|
|
|
|
int pc = emission_points.size();
|
2020-05-14 16:41:43 +02:00
|
|
|
if (pc == 0) {
|
2018-07-07 01:21:13 +02:00
|
|
|
break;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
|
|
|
|
int random_idx = Math::rand() % pc;
|
|
|
|
|
|
|
|
p.transform.origin = emission_points.get(random_idx);
|
|
|
|
|
|
|
|
if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS && emission_normals.size() == pc) {
|
2020-12-05 00:35:57 +01:00
|
|
|
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
|
2020-08-09 18:16:53 +02:00
|
|
|
Vector3 normal = emission_normals.get(random_idx);
|
|
|
|
Vector2 normal_2d(normal.x, normal.y);
|
|
|
|
Transform2D m2;
|
|
|
|
m2.set_axis(0, normal_2d);
|
2020-12-06 19:16:06 +01:00
|
|
|
m2.set_axis(1, normal_2d.orthogonal());
|
2020-08-09 18:16:53 +02:00
|
|
|
Vector2 velocity_2d(p.velocity.x, p.velocity.y);
|
|
|
|
velocity_2d = m2.basis_xform(velocity_2d);
|
|
|
|
p.velocity.x = velocity_2d.x;
|
|
|
|
p.velocity.y = velocity_2d.y;
|
2018-07-07 01:21:13 +02:00
|
|
|
} else {
|
|
|
|
Vector3 normal = emission_normals.get(random_idx);
|
|
|
|
Vector3 v0 = Math::abs(normal.z) < 0.999 ? Vector3(0.0, 0.0, 1.0) : Vector3(0, 1.0, 0.0);
|
|
|
|
Vector3 tangent = v0.cross(normal).normalized();
|
|
|
|
Vector3 bitangent = tangent.cross(normal).normalized();
|
|
|
|
Basis m3;
|
|
|
|
m3.set_axis(0, tangent);
|
|
|
|
m3.set_axis(1, bitangent);
|
|
|
|
m3.set_axis(2, normal);
|
|
|
|
p.velocity = m3.xform(p.velocity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (emission_colors.size() == pc) {
|
|
|
|
p.base_color = emission_colors.get(random_idx);
|
|
|
|
}
|
|
|
|
} break;
|
2021-07-11 15:45:21 +02:00
|
|
|
case EMISSION_SHAPE_RING: {
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t ring_random_angle = Math::randf() * Math_TAU;
|
|
|
|
real_t ring_random_radius = Math::randf() * (emission_ring_radius - emission_ring_inner_radius) + emission_ring_inner_radius;
|
2021-07-11 15:45:21 +02:00
|
|
|
Vector3 axis = emission_ring_axis.normalized();
|
|
|
|
Vector3 ortho_axis = Vector3();
|
|
|
|
if (axis == Vector3(1.0, 0.0, 0.0)) {
|
|
|
|
ortho_axis = Vector3(0.0, 1.0, 0.0).cross(axis);
|
|
|
|
} else {
|
|
|
|
ortho_axis = Vector3(1.0, 0.0, 0.0).cross(axis);
|
|
|
|
}
|
|
|
|
ortho_axis = ortho_axis.normalized();
|
|
|
|
ortho_axis.rotate(axis, ring_random_angle);
|
|
|
|
ortho_axis = ortho_axis.normalized();
|
|
|
|
p.transform.origin = ortho_axis * ring_random_radius + (Math::randf() * emission_ring_height - emission_ring_height / 2.0) * axis;
|
|
|
|
} break;
|
2020-01-16 10:59:01 +01:00
|
|
|
case EMISSION_SHAPE_MAX: { // Max value for validity check.
|
|
|
|
break;
|
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!local_coords) {
|
|
|
|
p.velocity = velocity_xform.xform(p.velocity);
|
|
|
|
p.transform = emission_xform * p.transform;
|
|
|
|
}
|
|
|
|
|
2020-12-05 00:35:57 +01:00
|
|
|
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
|
2018-07-07 01:21:13 +02:00
|
|
|
p.velocity.z = 0.0;
|
Fix many errors found by PVS-Studio
Fix errors 2, 3, 4, 6, 8, 9, 11, 12, 13, 14, and 15.
2018-11-28 03:58:00 +01:00
|
|
|
p.transform.origin.z = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
} else if (!p.active) {
|
|
|
|
continue;
|
2019-07-15 06:48:20 +02:00
|
|
|
} else if (p.time > p.lifetime) {
|
|
|
|
p.active = false;
|
2021-01-27 12:18:07 +01:00
|
|
|
tv = 1.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
} else {
|
|
|
|
uint32_t alt_seed = p.seed;
|
|
|
|
|
|
|
|
p.time += local_delta;
|
2018-07-23 17:28:15 +02:00
|
|
|
p.custom[1] = p.time / lifetime;
|
2021-01-27 12:18:07 +01:00
|
|
|
tv = p.time / p.lifetime;
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_linear_velocity = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_orbit_velocity = 0.0;
|
2020-12-05 00:35:57 +01:00
|
|
|
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
|
2019-06-11 17:47:24 +02:00
|
|
|
if (curve_parameters[PARAM_ORBIT_VELOCITY].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
}
|
2019-06-11 17:47:24 +02:00
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_angular_velocity = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_linear_accel = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_LINEAR_ACCEL].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_tangential_accel = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_radial_accel = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_RADIAL_ACCEL].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_damping = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_DAMPING].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_damping = curve_parameters[PARAM_DAMPING]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_angle = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_ANGLE].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_anim_speed = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_ANIM_SPEED].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_anim_offset = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_ANIM_OFFSET].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Vector3 force = gravity;
|
Fix many errors found by PVS-Studio
Fix errors 2, 3, 4, 6, 8, 9, 11, 12, 13, 14, and 15.
2018-11-28 03:58:00 +01:00
|
|
|
Vector3 position = p.transform.origin;
|
2020-12-05 00:35:57 +01:00
|
|
|
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
|
Fix many errors found by PVS-Studio
Fix errors 2, 3, 4, 6, 8, 9, 11, 12, 13, 14, and 15.
2018-11-28 03:58:00 +01:00
|
|
|
position.z = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
//apply linear acceleration
|
2021-07-13 19:46:27 +02:00
|
|
|
force += p.velocity.length() > 0.0 ? p.velocity.normalized() * tex_linear_accel * Math::lerp(parameters_min[PARAM_LINEAR_ACCEL], parameters_max[PARAM_LINEAR_ACCEL], rand_from_seed(alt_seed)) : Vector3();
|
2018-07-07 01:21:13 +02:00
|
|
|
//apply radial acceleration
|
|
|
|
Vector3 org = emission_xform.origin;
|
Fix many errors found by PVS-Studio
Fix errors 2, 3, 4, 6, 8, 9, 11, 12, 13, 14, and 15.
2018-11-28 03:58:00 +01:00
|
|
|
Vector3 diff = position - org;
|
2021-07-13 19:46:27 +02:00
|
|
|
force += diff.length() > 0.0 ? diff.normalized() * (tex_radial_accel)*Math::lerp(parameters_min[PARAM_RADIAL_ACCEL], parameters_max[PARAM_RADIAL_ACCEL], rand_from_seed(alt_seed)) : Vector3();
|
2020-12-05 00:35:57 +01:00
|
|
|
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
|
2019-06-11 18:56:07 +02:00
|
|
|
Vector2 yx = Vector2(diff.y, diff.x);
|
|
|
|
Vector2 yx2 = (yx * Vector2(-1.0, 1.0)).normalized();
|
2021-07-13 19:46:27 +02:00
|
|
|
force += yx.length() > 0.0 ? Vector3(yx2.x, yx2.y, 0.0) * (tex_tangential_accel * Math::lerp(parameters_min[PARAM_TANGENTIAL_ACCEL], parameters_max[PARAM_TANGENTIAL_ACCEL], rand_from_seed(alt_seed))) : Vector3();
|
2018-07-07 01:21:13 +02:00
|
|
|
|
|
|
|
} else {
|
|
|
|
Vector3 crossDiff = diff.normalized().cross(gravity.normalized());
|
2021-07-13 19:46:27 +02:00
|
|
|
force += crossDiff.length() > 0.0 ? crossDiff.normalized() * (tex_tangential_accel * Math::lerp(parameters_min[PARAM_TANGENTIAL_ACCEL], parameters_max[PARAM_TANGENTIAL_ACCEL], rand_from_seed(alt_seed))) : Vector3();
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
//apply attractor forces
|
|
|
|
p.velocity += force * local_delta;
|
|
|
|
//orbit velocity
|
2020-12-05 00:35:57 +01:00
|
|
|
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
|
2021-07-13 19:46:27 +02:00
|
|
|
real_t orbit_amount = tex_orbit_velocity * Math::lerp(parameters_min[PARAM_ORBIT_VELOCITY], parameters_max[PARAM_ORBIT_VELOCITY], rand_from_seed(alt_seed));
|
2018-07-07 01:21:13 +02:00
|
|
|
if (orbit_amount != 0.0) {
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t ang = orbit_amount * local_delta * Math_TAU;
|
2019-06-11 17:47:24 +02:00
|
|
|
// Not sure why the ParticlesMaterial code uses a clockwise rotation matrix,
|
|
|
|
// but we use -ang here to reproduce its behavior.
|
|
|
|
Transform2D rot = Transform2D(-ang, Vector2());
|
|
|
|
Vector2 rotv = rot.basis_xform(Vector2(diff.x, diff.y));
|
|
|
|
p.transform.origin -= Vector3(diff.x, diff.y, 0);
|
|
|
|
p.transform.origin += Vector3(rotv.x, rotv.y, 0);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
|
|
|
|
p.velocity = p.velocity.normalized() * tex_linear_velocity;
|
|
|
|
}
|
2021-07-13 19:46:27 +02:00
|
|
|
|
|
|
|
if (parameters_max[PARAM_DAMPING] + tex_damping > 0.0) {
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t v = p.velocity.length();
|
2021-07-13 19:46:27 +02:00
|
|
|
real_t damp = tex_damping * Math::lerp(parameters_min[PARAM_DAMPING], parameters_max[PARAM_DAMPING], rand_from_seed(alt_seed));
|
2018-07-07 01:21:13 +02:00
|
|
|
v -= damp * local_delta;
|
|
|
|
if (v < 0.0) {
|
|
|
|
p.velocity = Vector3();
|
|
|
|
} else {
|
|
|
|
p.velocity = p.velocity.normalized() * v;
|
|
|
|
}
|
|
|
|
}
|
2021-07-13 19:46:27 +02:00
|
|
|
real_t base_angle = (tex_angle)*Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand);
|
|
|
|
base_angle += p.custom[1] * lifetime * tex_angular_velocity * Math::lerp(parameters_min[PARAM_ANGULAR_VELOCITY], parameters_max[PARAM_ANGULAR_VELOCITY], rand_from_seed(alt_seed));
|
2018-07-07 01:21:13 +02:00
|
|
|
p.custom[0] = Math::deg2rad(base_angle); //angle
|
2021-07-13 19:46:27 +02:00
|
|
|
p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand) + p.custom[1] * tex_anim_speed * Math::lerp(parameters_min[PARAM_ANIM_SPEED], parameters_max[PARAM_ANIM_SPEED], rand_from_seed(alt_seed)); //angle
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
//apply color
|
|
|
|
//apply hue rotation
|
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
Vector3 tex_scale = Vector3(1.0, 1.0, 1.0);
|
|
|
|
if (split_scale) {
|
|
|
|
if (scale_curve_x.is_valid()) {
|
|
|
|
tex_scale.x = scale_curve_x->interpolate(tv);
|
|
|
|
} else {
|
|
|
|
tex_scale.x = 1.0;
|
|
|
|
}
|
|
|
|
if (scale_curve_y.is_valid()) {
|
|
|
|
tex_scale.y = scale_curve_y->interpolate(tv);
|
|
|
|
} else {
|
|
|
|
tex_scale.y = 1.0;
|
|
|
|
}
|
|
|
|
if (scale_curve_z.is_valid()) {
|
|
|
|
tex_scale.z = scale_curve_z->interpolate(tv);
|
|
|
|
} else {
|
|
|
|
tex_scale.z = 1.0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (curve_parameters[PARAM_SCALE].is_valid()) {
|
|
|
|
float tmp_scale = curve_parameters[PARAM_SCALE]->interpolate(tv);
|
|
|
|
tex_scale.x = tmp_scale;
|
|
|
|
tex_scale.y = tmp_scale;
|
|
|
|
tex_scale.z = tmp_scale;
|
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t tex_hue_variation = 0.0;
|
2018-07-07 01:21:13 +02:00
|
|
|
if (curve_parameters[PARAM_HUE_VARIATION].is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->interpolate(tv);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
real_t hue_rot_angle = (tex_hue_variation)*Math_TAU * Math::lerp(parameters_min[PARAM_HUE_VARIATION], parameters_max[PARAM_HUE_VARIATION], p.hue_rot_rand);
|
2021-01-30 01:55:54 +01:00
|
|
|
real_t hue_rot_c = Math::cos(hue_rot_angle);
|
|
|
|
real_t hue_rot_s = Math::sin(hue_rot_angle);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
|
|
|
Basis hue_rot_mat;
|
|
|
|
{
|
|
|
|
Basis mat1(0.299, 0.587, 0.114, 0.299, 0.587, 0.114, 0.299, 0.587, 0.114);
|
|
|
|
Basis mat2(0.701, -0.587, -0.114, -0.299, 0.413, -0.114, -0.300, -0.588, 0.886);
|
|
|
|
Basis mat3(0.168, 0.330, -0.497, -0.328, 0.035, 0.292, 1.250, -1.050, -0.203);
|
|
|
|
|
|
|
|
for (int j = 0; j < 3; j++) {
|
|
|
|
hue_rot_mat[j] = mat1[j] + mat2[j] * hue_rot_c + mat3[j] * hue_rot_s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (color_ramp.is_valid()) {
|
2021-01-27 12:18:07 +01:00
|
|
|
p.color = color_ramp->get_color_at_offset(tv) * color;
|
2018-07-07 01:21:13 +02:00
|
|
|
} else {
|
|
|
|
p.color = color;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector3 color_rgb = hue_rot_mat.xform_inv(Vector3(p.color.r, p.color.g, p.color.b));
|
|
|
|
p.color.r = color_rgb.x;
|
|
|
|
p.color.g = color_rgb.y;
|
|
|
|
p.color.b = color_rgb.z;
|
|
|
|
|
|
|
|
p.color *= p.base_color;
|
|
|
|
|
2020-12-05 00:35:57 +01:00
|
|
|
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
|
|
|
|
if (particle_flags[PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY]) {
|
2018-07-07 01:21:13 +02:00
|
|
|
if (p.velocity.length() > 0.0) {
|
|
|
|
p.transform.basis.set_axis(1, p.velocity.normalized());
|
|
|
|
} else {
|
|
|
|
p.transform.basis.set_axis(1, p.transform.basis.get_axis(1));
|
|
|
|
}
|
|
|
|
p.transform.basis.set_axis(0, p.transform.basis.get_axis(1).cross(p.transform.basis.get_axis(2)).normalized());
|
|
|
|
p.transform.basis.set_axis(2, Vector3(0, 0, 1));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
p.transform.basis.set_axis(0, Vector3(Math::cos(p.custom[0]), -Math::sin(p.custom[0]), 0.0));
|
|
|
|
p.transform.basis.set_axis(1, Vector3(Math::sin(p.custom[0]), Math::cos(p.custom[0]), 0.0));
|
|
|
|
p.transform.basis.set_axis(2, Vector3(0, 0, 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
//orient particle Y towards velocity
|
2020-12-05 00:35:57 +01:00
|
|
|
if (particle_flags[PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY]) {
|
2018-07-07 01:21:13 +02:00
|
|
|
if (p.velocity.length() > 0.0) {
|
|
|
|
p.transform.basis.set_axis(1, p.velocity.normalized());
|
|
|
|
} else {
|
|
|
|
p.transform.basis.set_axis(1, p.transform.basis.get_axis(1).normalized());
|
|
|
|
}
|
|
|
|
if (p.transform.basis.get_axis(1) == p.transform.basis.get_axis(0)) {
|
|
|
|
p.transform.basis.set_axis(0, p.transform.basis.get_axis(1).cross(p.transform.basis.get_axis(2)).normalized());
|
|
|
|
p.transform.basis.set_axis(2, p.transform.basis.get_axis(0).cross(p.transform.basis.get_axis(1)).normalized());
|
|
|
|
} else {
|
|
|
|
p.transform.basis.set_axis(2, p.transform.basis.get_axis(0).cross(p.transform.basis.get_axis(1)).normalized());
|
|
|
|
p.transform.basis.set_axis(0, p.transform.basis.get_axis(1).cross(p.transform.basis.get_axis(2)).normalized());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
p.transform.basis.orthonormalize();
|
|
|
|
}
|
|
|
|
|
|
|
|
//turn particle by rotation in Y
|
2020-12-05 00:35:57 +01:00
|
|
|
if (particle_flags[PARTICLE_FLAG_ROTATE_Y]) {
|
2018-07-07 01:21:13 +02:00
|
|
|
Basis rot_y(Vector3(0, 1, 0), p.custom[0]);
|
|
|
|
p.transform.basis = p.transform.basis * rot_y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
p.transform.basis = p.transform.basis.orthonormalized();
|
2018-07-07 01:21:13 +02:00
|
|
|
//scale by scale
|
2021-07-13 19:46:27 +02:00
|
|
|
|
|
|
|
Vector3 base_scale = tex_scale * Math::lerp(parameters_min[PARAM_SCALE], parameters_max[PARAM_SCALE], p.scale_rand);
|
|
|
|
if (base_scale.x < CMP_EPSILON) {
|
|
|
|
base_scale.x = CMP_EPSILON;
|
|
|
|
}
|
|
|
|
if (base_scale.y < CMP_EPSILON) {
|
|
|
|
base_scale.y = CMP_EPSILON;
|
|
|
|
}
|
|
|
|
if (base_scale.z < CMP_EPSILON) {
|
|
|
|
base_scale.z = CMP_EPSILON;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
p.transform.basis.scale(base_scale);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-12-05 00:35:57 +01:00
|
|
|
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
|
2018-07-07 01:21:13 +02:00
|
|
|
p.velocity.z = 0.0;
|
|
|
|
p.transform.origin.z = 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
p.transform.origin += p.velocity * local_delta;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::_update_particle_data_buffer() {
|
2020-02-26 11:28:13 +01:00
|
|
|
MutexLock lock(update_mutex);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
int pc = particles.size();
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
int *ow;
|
2020-04-02 01:20:12 +02:00
|
|
|
int *order = nullptr;
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
float *w = particle_data.ptrw();
|
|
|
|
const Particle *r = particles.ptr();
|
|
|
|
float *ptr = w;
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
if (draw_order != DRAW_ORDER_INDEX) {
|
|
|
|
ow = particle_order.ptrw();
|
|
|
|
order = ow;
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
for (int i = 0; i < pc; i++) {
|
|
|
|
order[i] = i;
|
|
|
|
}
|
|
|
|
if (draw_order == DRAW_ORDER_LIFETIME) {
|
|
|
|
SortArray<int, SortLifetime> sorter;
|
|
|
|
sorter.compare.particles = r;
|
|
|
|
sorter.sort(order, pc);
|
|
|
|
} else if (draw_order == DRAW_ORDER_VIEW_DEPTH) {
|
2021-02-17 15:30:03 +01:00
|
|
|
ERR_FAIL_NULL(get_viewport());
|
2020-04-28 17:04:07 +02:00
|
|
|
Camera3D *c = get_viewport()->get_camera_3d();
|
2020-02-26 11:28:13 +01:00
|
|
|
if (c) {
|
|
|
|
Vector3 dir = c->get_global_transform().basis.get_axis(2); //far away to close
|
|
|
|
|
|
|
|
if (local_coords) {
|
|
|
|
// will look different from Particles in editor as this is based on the camera in the scenetree
|
|
|
|
// and not the editor camera
|
|
|
|
dir = inv_emission_transform.xform(dir).normalized();
|
|
|
|
} else {
|
|
|
|
dir = dir.normalized();
|
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
SortArray<int, SortAxis> sorter;
|
2020-02-17 22:06:54 +01:00
|
|
|
sorter.compare.particles = r;
|
2020-02-26 11:28:13 +01:00
|
|
|
sorter.compare.axis = dir;
|
2018-07-07 01:21:13 +02:00
|
|
|
sorter.sort(order, pc);
|
|
|
|
}
|
|
|
|
}
|
2020-02-26 11:28:13 +01:00
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
for (int i = 0; i < pc; i++) {
|
|
|
|
int idx = order ? order[i] : i;
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-10-17 07:08:21 +02:00
|
|
|
Transform3D t = r[idx].transform;
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
if (!local_coords) {
|
|
|
|
t = inv_emission_transform * t;
|
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
if (r[idx].active) {
|
|
|
|
ptr[0] = t.basis.elements[0][0];
|
|
|
|
ptr[1] = t.basis.elements[0][1];
|
|
|
|
ptr[2] = t.basis.elements[0][2];
|
|
|
|
ptr[3] = t.origin.x;
|
|
|
|
ptr[4] = t.basis.elements[1][0];
|
|
|
|
ptr[5] = t.basis.elements[1][1];
|
|
|
|
ptr[6] = t.basis.elements[1][2];
|
|
|
|
ptr[7] = t.origin.y;
|
|
|
|
ptr[8] = t.basis.elements[2][0];
|
|
|
|
ptr[9] = t.basis.elements[2][1];
|
|
|
|
ptr[10] = t.basis.elements[2][2];
|
|
|
|
ptr[11] = t.origin.z;
|
|
|
|
} else {
|
2021-08-10 00:15:17 +02:00
|
|
|
memset(ptr, 0, sizeof(Transform3D));
|
2020-02-26 11:28:13 +01:00
|
|
|
}
|
2019-10-05 16:35:10 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
Color c = r[idx].color;
|
2019-10-05 16:35:10 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
ptr[12] = c.r;
|
|
|
|
ptr[13] = c.g;
|
|
|
|
ptr[14] = c.b;
|
|
|
|
ptr[15] = c.a;
|
2019-10-05 16:35:10 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
ptr[16] = r[idx].custom[0];
|
|
|
|
ptr[17] = r[idx].custom[1];
|
|
|
|
ptr[18] = r[idx].custom[2];
|
|
|
|
ptr[19] = r[idx].custom[3];
|
2018-10-08 05:51:48 +02:00
|
|
|
|
2020-02-26 11:28:13 +01:00
|
|
|
ptr += 20;
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2021-02-10 19:22:13 +01:00
|
|
|
can_update.set();
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::_set_redraw(bool p_redraw) {
|
2020-05-14 16:41:43 +02:00
|
|
|
if (redraw == p_redraw) {
|
2019-03-09 02:50:44 +01:00
|
|
|
return;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2019-03-09 02:50:44 +01:00
|
|
|
redraw = p_redraw;
|
2020-02-26 11:28:13 +01:00
|
|
|
|
|
|
|
{
|
|
|
|
MutexLock lock(update_mutex);
|
|
|
|
|
|
|
|
if (redraw) {
|
2020-03-27 19:21:27 +01:00
|
|
|
RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &CPUParticles3D::_update_render_thread));
|
|
|
|
RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true);
|
|
|
|
RS::get_singleton()->multimesh_set_visible_instances(multimesh, -1);
|
2020-02-26 11:28:13 +01:00
|
|
|
} else {
|
2020-03-27 19:21:27 +01:00
|
|
|
if (RS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &CPUParticles3D::_update_render_thread))) {
|
|
|
|
RS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &CPUParticles3D::_update_render_thread));
|
2020-02-26 11:28:13 +01:00
|
|
|
}
|
2020-03-27 19:21:27 +01:00
|
|
|
RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, false);
|
|
|
|
RS::get_singleton()->multimesh_set_visible_instances(multimesh, 0);
|
2019-10-29 00:40:36 +01:00
|
|
|
}
|
2019-03-09 02:50:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::_update_render_thread() {
|
2020-02-26 11:28:13 +01:00
|
|
|
MutexLock lock(update_mutex);
|
|
|
|
|
2021-02-10 19:22:13 +01:00
|
|
|
if (can_update.is_set()) {
|
2020-03-27 19:21:27 +01:00
|
|
|
RS::get_singleton()->multimesh_set_buffer(multimesh, particle_data);
|
2021-02-10 19:22:13 +01:00
|
|
|
can_update.clear(); //wait for next time
|
2018-10-08 05:51:48 +02:00
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::_notification(int p_what) {
|
2018-07-07 01:21:13 +02:00
|
|
|
if (p_what == NOTIFICATION_ENTER_TREE) {
|
2019-03-20 10:50:56 +01:00
|
|
|
set_process_internal(emitting);
|
2019-10-19 17:30:13 +02:00
|
|
|
|
|
|
|
// first update before rendering to avoid one frame delay after emitting starts
|
2020-05-14 16:41:43 +02:00
|
|
|
if (emitting && (time == 0)) {
|
2019-10-19 17:30:13 +02:00
|
|
|
_update_internal();
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (p_what == NOTIFICATION_EXIT_TREE) {
|
2019-03-09 02:50:44 +01:00
|
|
|
_set_redraw(false);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2019-10-19 17:30:13 +02:00
|
|
|
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
|
|
|
|
// first update before rendering to avoid one frame delay after emitting starts
|
2020-05-14 16:41:43 +02:00
|
|
|
if (emitting && (time == 0)) {
|
2019-10-19 17:30:13 +02:00
|
|
|
_update_internal();
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2019-10-19 17:30:13 +02:00
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2019-10-19 17:30:13 +02:00
|
|
|
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
|
|
|
|
_update_internal();
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
2019-06-14 22:22:19 +02:00
|
|
|
|
|
|
|
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
|
|
|
|
inv_emission_transform = get_global_transform().affine_inverse();
|
|
|
|
|
|
|
|
if (!local_coords) {
|
|
|
|
int pc = particles.size();
|
|
|
|
|
2020-02-17 22:06:54 +01:00
|
|
|
float *w = particle_data.ptrw();
|
|
|
|
const Particle *r = particles.ptr();
|
|
|
|
float *ptr = w;
|
2019-06-14 22:22:19 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < pc; i++) {
|
2020-10-17 07:08:21 +02:00
|
|
|
Transform3D t = inv_emission_transform * r[i].transform;
|
2019-06-14 22:22:19 +02:00
|
|
|
|
|
|
|
if (r[i].active) {
|
|
|
|
ptr[0] = t.basis.elements[0][0];
|
|
|
|
ptr[1] = t.basis.elements[0][1];
|
|
|
|
ptr[2] = t.basis.elements[0][2];
|
|
|
|
ptr[3] = t.origin.x;
|
|
|
|
ptr[4] = t.basis.elements[1][0];
|
|
|
|
ptr[5] = t.basis.elements[1][1];
|
|
|
|
ptr[6] = t.basis.elements[1][2];
|
|
|
|
ptr[7] = t.origin.y;
|
|
|
|
ptr[8] = t.basis.elements[2][0];
|
|
|
|
ptr[9] = t.basis.elements[2][1];
|
|
|
|
ptr[10] = t.basis.elements[2][2];
|
|
|
|
ptr[11] = t.origin.z;
|
|
|
|
} else {
|
2021-04-27 16:19:21 +02:00
|
|
|
memset(ptr, 0, sizeof(float) * 12);
|
2019-06-14 22:22:19 +02:00
|
|
|
}
|
|
|
|
|
2019-10-05 16:35:10 +02:00
|
|
|
ptr += 20;
|
2019-06-14 22:22:19 +02:00
|
|
|
}
|
|
|
|
|
2021-02-10 19:22:13 +01:00
|
|
|
can_update.set();
|
2019-06-14 22:22:19 +02:00
|
|
|
}
|
|
|
|
}
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::convert_from_particles(Node *p_particles) {
|
|
|
|
GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_particles);
|
2020-03-30 18:22:57 +02:00
|
|
|
ERR_FAIL_COND_MSG(!particles, "Only GPUParticles3D nodes can be converted to CPUParticles3D.");
|
2018-07-07 14:04:22 +02:00
|
|
|
|
|
|
|
set_emitting(particles->is_emitting());
|
|
|
|
set_amount(particles->get_amount());
|
|
|
|
set_lifetime(particles->get_lifetime());
|
|
|
|
set_one_shot(particles->get_one_shot());
|
|
|
|
set_pre_process_time(particles->get_pre_process_time());
|
|
|
|
set_explosiveness_ratio(particles->get_explosiveness_ratio());
|
|
|
|
set_randomness_ratio(particles->get_randomness_ratio());
|
|
|
|
set_use_local_coordinates(particles->get_use_local_coordinates());
|
|
|
|
set_fixed_fps(particles->get_fixed_fps());
|
|
|
|
set_fractional_delta(particles->get_fractional_delta());
|
|
|
|
set_speed_scale(particles->get_speed_scale());
|
|
|
|
set_draw_order(DrawOrder(particles->get_draw_order()));
|
|
|
|
set_mesh(particles->get_draw_pass_mesh(0));
|
|
|
|
|
|
|
|
Ref<ParticlesMaterial> material = particles->get_process_material();
|
2020-05-14 16:41:43 +02:00
|
|
|
if (material.is_null()) {
|
2018-07-07 14:04:22 +02:00
|
|
|
return;
|
2020-05-14 16:41:43 +02:00
|
|
|
}
|
2018-07-07 14:04:22 +02:00
|
|
|
|
2019-03-04 23:45:53 +01:00
|
|
|
set_direction(material->get_direction());
|
2018-07-07 14:04:22 +02:00
|
|
|
set_spread(material->get_spread());
|
|
|
|
set_flatness(material->get_flatness());
|
|
|
|
|
|
|
|
set_color(material->get_color());
|
|
|
|
|
|
|
|
Ref<GradientTexture> gt = material->get_color_ramp();
|
|
|
|
if (gt.is_valid()) {
|
|
|
|
set_color_ramp(gt->get_gradient());
|
|
|
|
}
|
|
|
|
|
2020-12-05 00:35:57 +01:00
|
|
|
set_particle_flag(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY));
|
|
|
|
set_particle_flag(PARTICLE_FLAG_ROTATE_Y, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_ROTATE_Y));
|
|
|
|
set_particle_flag(PARTICLE_FLAG_DISABLE_Z, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_DISABLE_Z));
|
2018-07-07 14:04:22 +02:00
|
|
|
|
|
|
|
set_emission_shape(EmissionShape(material->get_emission_shape()));
|
|
|
|
set_emission_sphere_radius(material->get_emission_sphere_radius());
|
|
|
|
set_emission_box_extents(material->get_emission_box_extents());
|
2021-07-13 19:46:27 +02:00
|
|
|
Ref<CurveXYZTexture> scale3D = material->get_param_texture(ParticlesMaterial::PARAM_SCALE);
|
|
|
|
if (scale3D.is_valid()) {
|
|
|
|
split_scale = true;
|
|
|
|
scale_curve_x = scale3D->get_curve_x();
|
|
|
|
scale_curve_y = scale3D->get_curve_y();
|
|
|
|
scale_curve_z = scale3D->get_curve_z();
|
|
|
|
}
|
2018-07-07 14:04:22 +02:00
|
|
|
|
|
|
|
set_gravity(material->get_gravity());
|
2019-07-15 06:48:20 +02:00
|
|
|
set_lifetime_randomness(material->get_lifetime_randomness());
|
2018-07-07 14:04:22 +02:00
|
|
|
|
|
|
|
#define CONVERT_PARAM(m_param) \
|
2021-07-13 19:46:27 +02:00
|
|
|
set_param_min(m_param, material->get_param_min(ParticlesMaterial::m_param)); \
|
2018-07-07 14:04:22 +02:00
|
|
|
{ \
|
|
|
|
Ref<CurveTexture> ctex = material->get_param_texture(ParticlesMaterial::m_param); \
|
2020-05-10 12:56:01 +02:00
|
|
|
if (ctex.is_valid()) \
|
|
|
|
set_param_curve(m_param, ctex->get_curve()); \
|
2018-07-07 14:04:22 +02:00
|
|
|
} \
|
2021-07-13 19:46:27 +02:00
|
|
|
set_param_max(m_param, material->get_param_max(ParticlesMaterial::m_param));
|
2018-07-07 14:04:22 +02:00
|
|
|
|
|
|
|
CONVERT_PARAM(PARAM_INITIAL_LINEAR_VELOCITY);
|
|
|
|
CONVERT_PARAM(PARAM_ANGULAR_VELOCITY);
|
2019-06-11 17:47:24 +02:00
|
|
|
CONVERT_PARAM(PARAM_ORBIT_VELOCITY);
|
2018-07-07 14:04:22 +02:00
|
|
|
CONVERT_PARAM(PARAM_LINEAR_ACCEL);
|
|
|
|
CONVERT_PARAM(PARAM_RADIAL_ACCEL);
|
|
|
|
CONVERT_PARAM(PARAM_TANGENTIAL_ACCEL);
|
|
|
|
CONVERT_PARAM(PARAM_DAMPING);
|
|
|
|
CONVERT_PARAM(PARAM_ANGLE);
|
|
|
|
CONVERT_PARAM(PARAM_SCALE);
|
|
|
|
CONVERT_PARAM(PARAM_HUE_VARIATION);
|
|
|
|
CONVERT_PARAM(PARAM_ANIM_SPEED);
|
|
|
|
CONVERT_PARAM(PARAM_ANIM_OFFSET);
|
|
|
|
|
|
|
|
#undef CONVERT_PARAM
|
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
void CPUParticles3D::_bind_methods() {
|
|
|
|
ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &CPUParticles3D::set_emitting);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_amount", "amount"), &CPUParticles3D::set_amount);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &CPUParticles3D::set_lifetime);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_one_shot", "enable"), &CPUParticles3D::set_one_shot);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &CPUParticles3D::set_pre_process_time);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_explosiveness_ratio", "ratio"), &CPUParticles3D::set_explosiveness_ratio);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_randomness_ratio", "ratio"), &CPUParticles3D::set_randomness_ratio);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_lifetime_randomness", "random"), &CPUParticles3D::set_lifetime_randomness);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_use_local_coordinates", "enable"), &CPUParticles3D::set_use_local_coordinates);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &CPUParticles3D::set_fixed_fps);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &CPUParticles3D::set_fractional_delta);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &CPUParticles3D::set_speed_scale);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("is_emitting"), &CPUParticles3D::is_emitting);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_amount"), &CPUParticles3D::get_amount);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_lifetime"), &CPUParticles3D::get_lifetime);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_one_shot"), &CPUParticles3D::get_one_shot);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_pre_process_time"), &CPUParticles3D::get_pre_process_time);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_explosiveness_ratio"), &CPUParticles3D::get_explosiveness_ratio);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_randomness_ratio"), &CPUParticles3D::get_randomness_ratio);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_lifetime_randomness"), &CPUParticles3D::get_lifetime_randomness);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_use_local_coordinates"), &CPUParticles3D::get_use_local_coordinates);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_fixed_fps"), &CPUParticles3D::get_fixed_fps);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_fractional_delta"), &CPUParticles3D::get_fractional_delta);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_speed_scale"), &CPUParticles3D::get_speed_scale);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &CPUParticles3D::set_draw_order);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("get_draw_order"), &CPUParticles3D::get_draw_order);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &CPUParticles3D::set_mesh);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_mesh"), &CPUParticles3D::get_mesh);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("restart"), &CPUParticles3D::restart);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
|
Fix editor suffixes and degrees conversion
* Functions to convert to/from degrees are all gone. Conversion is done by the editor.
* Use PROPERTY_HINT_ANGLE instead of PROPERTY_HINT_RANGE to edit radian angles in degrees.
* Added possibility to add suffixes to range properties, use "min,max[,step][,suffix:<something>]" example "0,100,1,suffix:m"
* In general, can add suffixes for EditorSpinSlider
Not covered by this PR, will have to be addressed by future ones:
* Ability to switch radians/degrees in the inspector for angle properties (if actually wanted).
* Animations previously made will most likely break, need to add a way to make old ones compatible.
* Only added a "px" suffix to 2D position and a "m" one to 3D position, someone needs to go through the rest of the engine and add all remaining suffixes.
* Likely also need to track down usage of EditorSpinSlider outside properties to add suffixes to it too.
2021-06-29 21:42:12 +02:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount");
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_GROUP("Time", "");
|
Fix editor suffixes and degrees conversion
* Functions to convert to/from degrees are all gone. Conversion is done by the editor.
* Use PROPERTY_HINT_ANGLE instead of PROPERTY_HINT_RANGE to edit radian angles in degrees.
* Added possibility to add suffixes to range properties, use "min,max[,step][,suffix:<something>]" example "0,100,1,suffix:m"
* In general, can add suffixes for EditorSpinSlider
Not covered by this PR, will have to be addressed by future ones:
* Ability to switch radians/degrees in the inspector for angle properties (if actually wanted).
* Animations previously made will most likely break, need to add a way to make old ones compatible.
* Only added a "px" suffix to 2D position and a "m" one to 3D position, someone needs to go through the rest of the engine and add all remaining suffixes.
* Likely also need to track down usage of EditorSpinSlider outside properties to add suffixes to it too.
2021-06-29 21:42:12 +02:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,exp"), "set_lifetime", "get_lifetime");
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
|
Fix editor suffixes and degrees conversion
* Functions to convert to/from degrees are all gone. Conversion is done by the editor.
* Use PROPERTY_HINT_ANGLE instead of PROPERTY_HINT_RANGE to edit radian angles in degrees.
* Added possibility to add suffixes to range properties, use "min,max[,step][,suffix:<something>]" example "0,100,1,suffix:m"
* In general, can add suffixes for EditorSpinSlider
Not covered by this PR, will have to be addressed by future ones:
* Ability to switch radians/degrees in the inspector for angle properties (if actually wanted).
* Animations previously made will most likely break, need to add a way to make old ones compatible.
* Only added a "px" suffix to 2D position and a "m" one to 3D position, someone needs to go through the rest of the engine and add all remaining suffixes.
* Likely also need to track down usage of EditorSpinSlider outside properties to add suffixes to it too.
2021-06-29 21:42:12 +02:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01,exp"), "set_pre_process_time", "get_pre_process_time");
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness");
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
|
|
|
|
ADD_GROUP("Drawing", "");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,View Depth"), "set_draw_order", "get_draw_order");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
|
|
|
|
|
|
|
|
BIND_ENUM_CONSTANT(DRAW_ORDER_INDEX);
|
|
|
|
BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME);
|
|
|
|
BIND_ENUM_CONSTANT(DRAW_ORDER_VIEW_DEPTH);
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_direction", "direction"), &CPUParticles3D::set_direction);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_direction"), &CPUParticles3D::get_direction);
|
2019-03-04 23:45:53 +01:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &CPUParticles3D::set_spread);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_spread"), &CPUParticles3D::get_spread);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &CPUParticles3D::set_flatness);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_flatness"), &CPUParticles3D::get_flatness);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
ClassDB::bind_method(D_METHOD("set_param_min", "param", "value"), &CPUParticles3D::set_param_min);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_param_min", "param"), &CPUParticles3D::get_param_min);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
ClassDB::bind_method(D_METHOD("set_param_max", "param", "value"), &CPUParticles3D::set_param_max);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_param_max", "param"), &CPUParticles3D::get_param_max);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_param_curve", "param", "curve"), &CPUParticles3D::set_param_curve);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_param_curve", "param"), &CPUParticles3D::get_param_curve);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_color", "color"), &CPUParticles3D::set_color);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_color"), &CPUParticles3D::get_color);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp"), &CPUParticles3D::set_color_ramp);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_color_ramp"), &CPUParticles3D::get_color_ramp);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-12-05 00:35:57 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_particle_flag", "particle_flag", "enable"), &CPUParticles3D::set_particle_flag);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_particle_flag", "particle_flag"), &CPUParticles3D::get_particle_flag);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &CPUParticles3D::set_emission_shape);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_emission_shape"), &CPUParticles3D::get_emission_shape);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &CPUParticles3D::set_emission_sphere_radius);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &CPUParticles3D::get_emission_sphere_radius);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_emission_box_extents", "extents"), &CPUParticles3D::set_emission_box_extents);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_emission_box_extents"), &CPUParticles3D::get_emission_box_extents);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_emission_points", "array"), &CPUParticles3D::set_emission_points);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_emission_points"), &CPUParticles3D::get_emission_points);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_emission_normals", "array"), &CPUParticles3D::set_emission_normals);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_emission_normals"), &CPUParticles3D::get_emission_normals);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("set_emission_colors", "array"), &CPUParticles3D::set_emission_colors);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_emission_colors"), &CPUParticles3D::get_emission_colors);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2021-07-11 15:45:21 +02:00
|
|
|
ClassDB::bind_method(D_METHOD("set_emission_ring_axis", "axis"), &CPUParticles3D::set_emission_ring_axis);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_emission_ring_axis"), &CPUParticles3D::get_emission_ring_axis);
|
|
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("set_emission_ring_height", "height"), &CPUParticles3D::set_emission_ring_height);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_emission_ring_height"), &CPUParticles3D::get_emission_ring_height);
|
|
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("set_emission_ring_radius", "radius"), &CPUParticles3D::set_emission_ring_radius);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_emission_ring_radius"), &CPUParticles3D::get_emission_ring_radius);
|
|
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "inner_radius"), &CPUParticles3D::set_emission_ring_inner_radius);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &CPUParticles3D::get_emission_ring_inner_radius);
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("get_gravity"), &CPUParticles3D::get_gravity);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &CPUParticles3D::set_gravity);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
ClassDB::bind_method(D_METHOD("get_split_scale"), &CPUParticles3D::get_split_scale);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_split_scale", "split_scale"), &CPUParticles3D::set_split_scale);
|
|
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("get_scale_curve_x"), &CPUParticles3D::get_scale_curve_x);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_scale_curve_x", "scale_curve"), &CPUParticles3D::set_scale_curve_x);
|
|
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("get_scale_curve_y"), &CPUParticles3D::get_scale_curve_y);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_scale_curve_y", "scale_curve"), &CPUParticles3D::set_scale_curve_y);
|
|
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("get_scale_curve_z"), &CPUParticles3D::get_scale_curve_z);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_scale_curve_z", "scale_curve"), &CPUParticles3D::set_scale_curve_z);
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles3D::convert_from_particles);
|
2018-07-07 14:04:22 +02:00
|
|
|
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_GROUP("Emission Shape", "emission_");
|
2021-07-11 15:45:21 +02:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points,Ring", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape");
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius");
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents");
|
2020-02-17 22:06:54 +01:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_points"), "set_emission_points", "get_emission_points");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "emission_colors"), "set_emission_colors", "get_emission_colors");
|
2021-07-11 15:45:21 +02:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_ring_axis"), "set_emission_ring_axis", "get_emission_ring_axis");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_height"), "set_emission_ring_height", "get_emission_ring_height");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_radius"), "set_emission_ring_radius", "get_emission_ring_radius");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_inner_radius"), "set_emission_ring_inner_radius", "get_emission_ring_inner_radius");
|
2020-12-05 00:35:57 +01:00
|
|
|
ADD_GROUP("Particle Flags", "particle_flag_");
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_align_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_rotate_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ROTATE_Y);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_disable_z"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_DISABLE_Z);
|
2019-03-04 23:45:53 +01:00
|
|
|
ADD_GROUP("Direction", "");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "direction"), "set_direction", "get_direction");
|
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness");
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_GROUP("Gravity", "");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity");
|
|
|
|
ADD_GROUP("Initial Velocity", "initial_");
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "initial_velocity_min", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param_min", "get_param_min", PARAM_INITIAL_LINEAR_VELOCITY);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "initial_velocity_max", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param_max", "get_param_max", PARAM_INITIAL_LINEAR_VELOCITY);
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_GROUP("Angular Velocity", "angular_");
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_velocity_min", PROPERTY_HINT_RANGE, "-720,720,0.01,or_lesser,or_greater"), "set_param_min", "get_param_min", PARAM_ANGULAR_VELOCITY);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_velocity_max", PROPERTY_HINT_RANGE, "-720,720,0.01,or_lesser,or_greater"), "set_param_max", "get_param_max", PARAM_ANGULAR_VELOCITY);
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angular_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGULAR_VELOCITY);
|
|
|
|
ADD_GROUP("Orbit Velocity", "orbit_");
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity_min", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_lesser,or_greater"), "set_param_min", "get_param_min", PARAM_ORBIT_VELOCITY);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity_max", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_lesser,or_greater"), "set_param_max", "get_param_max", PARAM_ORBIT_VELOCITY);
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orbit_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ORBIT_VELOCITY);
|
|
|
|
ADD_GROUP("Linear Accel", "linear_");
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_accel_min", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param_min", "get_param_min", PARAM_LINEAR_ACCEL);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_accel_max", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param_max", "get_param_max", PARAM_LINEAR_ACCEL);
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "linear_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_LINEAR_ACCEL);
|
|
|
|
ADD_GROUP("Radial Accel", "radial_");
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "radial_accel_min", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param_min", "get_param_min", PARAM_RADIAL_ACCEL);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "radial_accel_max", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param_max", "get_param_max", PARAM_RADIAL_ACCEL);
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "radial_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_RADIAL_ACCEL);
|
|
|
|
ADD_GROUP("Tangential Accel", "tangential_");
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "tangential_accel_min", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param_min", "get_param_min", PARAM_TANGENTIAL_ACCEL);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "tangential_accel_max", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param_max", "get_param_max", PARAM_TANGENTIAL_ACCEL);
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_TANGENTIAL_ACCEL);
|
|
|
|
ADD_GROUP("Damping", "");
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_min", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param_min", "get_param_min", PARAM_DAMPING);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_max", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param_max", "get_param_max", PARAM_DAMPING);
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_DAMPING);
|
|
|
|
ADD_GROUP("Angle", "");
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle_min", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater,degrees"), "set_param_min", "get_param_min", PARAM_ANGLE);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle_max", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater,degrees"), "set_param_max", "get_param_max", PARAM_ANGLE);
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGLE);
|
|
|
|
ADD_GROUP("Scale", "");
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "scale_amount_min", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param_min", "get_param_min", PARAM_SCALE);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "scale_amount_max", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param_max", "get_param_max", PARAM_SCALE);
|
2018-11-27 11:07:58 +01:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "scale_amount_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_SCALE);
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "split_scale"), "set_split_scale", "get_split_scale");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "scale_curve_x", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_scale_curve_x", "get_scale_curve_x");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "scale_curve_y", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_scale_curve_y", "get_scale_curve_y");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "scale_curve_z", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_scale_curve_z", "get_scale_curve_z");
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_GROUP("Color", "");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
|
2018-11-11 00:07:22 +01:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_color_ramp", "get_color_ramp");
|
2018-07-07 01:21:13 +02:00
|
|
|
|
|
|
|
ADD_GROUP("Hue Variation", "hue_");
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_min", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param_min", "get_param_min", PARAM_HUE_VARIATION);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_max", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param_max", "get_param_max", PARAM_HUE_VARIATION);
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_HUE_VARIATION);
|
|
|
|
ADD_GROUP("Animation", "anim_");
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed_min", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater,or_lesser"), "set_param_min", "get_param_min", PARAM_ANIM_SPEED);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed_max", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater,or_lesser"), "set_param_max", "get_param_max", PARAM_ANIM_SPEED);
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_speed_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANIM_SPEED);
|
2021-07-13 19:46:27 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_offset_min", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_min", "get_param_min", PARAM_ANIM_OFFSET);
|
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_offset_max", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_max", "get_param_max", PARAM_ANIM_OFFSET);
|
2018-07-07 01:21:13 +02:00
|
|
|
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANIM_OFFSET);
|
|
|
|
|
|
|
|
BIND_ENUM_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY);
|
|
|
|
BIND_ENUM_CONSTANT(PARAM_ANGULAR_VELOCITY);
|
2019-06-11 17:47:24 +02:00
|
|
|
BIND_ENUM_CONSTANT(PARAM_ORBIT_VELOCITY);
|
2018-07-07 01:21:13 +02:00
|
|
|
BIND_ENUM_CONSTANT(PARAM_LINEAR_ACCEL);
|
|
|
|
BIND_ENUM_CONSTANT(PARAM_RADIAL_ACCEL);
|
|
|
|
BIND_ENUM_CONSTANT(PARAM_TANGENTIAL_ACCEL);
|
|
|
|
BIND_ENUM_CONSTANT(PARAM_DAMPING);
|
|
|
|
BIND_ENUM_CONSTANT(PARAM_ANGLE);
|
|
|
|
BIND_ENUM_CONSTANT(PARAM_SCALE);
|
|
|
|
BIND_ENUM_CONSTANT(PARAM_HUE_VARIATION);
|
|
|
|
BIND_ENUM_CONSTANT(PARAM_ANIM_SPEED);
|
|
|
|
BIND_ENUM_CONSTANT(PARAM_ANIM_OFFSET);
|
|
|
|
BIND_ENUM_CONSTANT(PARAM_MAX);
|
|
|
|
|
2020-12-05 00:35:57 +01:00
|
|
|
BIND_ENUM_CONSTANT(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY);
|
|
|
|
BIND_ENUM_CONSTANT(PARTICLE_FLAG_ROTATE_Y);
|
|
|
|
BIND_ENUM_CONSTANT(PARTICLE_FLAG_DISABLE_Z);
|
|
|
|
BIND_ENUM_CONSTANT(PARTICLE_FLAG_MAX);
|
2018-07-07 01:21:13 +02:00
|
|
|
|
|
|
|
BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINT);
|
|
|
|
BIND_ENUM_CONSTANT(EMISSION_SHAPE_SPHERE);
|
|
|
|
BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX);
|
|
|
|
BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS);
|
|
|
|
BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS);
|
2021-07-11 15:45:21 +02:00
|
|
|
BIND_ENUM_CONSTANT(EMISSION_SHAPE_RING);
|
2020-01-16 10:59:01 +01:00
|
|
|
BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
CPUParticles3D::CPUParticles3D() {
|
2019-06-14 22:22:19 +02:00
|
|
|
set_notify_transform(true);
|
|
|
|
|
2020-03-27 19:21:27 +01:00
|
|
|
multimesh = RenderingServer::get_singleton()->multimesh_create();
|
|
|
|
RenderingServer::get_singleton()->multimesh_set_visible_instances(multimesh, 0);
|
2018-07-07 01:21:13 +02:00
|
|
|
set_base(multimesh);
|
|
|
|
|
|
|
|
set_emitting(true);
|
|
|
|
set_amount(8);
|
2021-02-07 22:29:31 +01:00
|
|
|
|
2021-07-13 19:46:27 +02:00
|
|
|
set_param_min(PARAM_INITIAL_LINEAR_VELOCITY, 0);
|
|
|
|
set_param_min(PARAM_ANGULAR_VELOCITY, 0);
|
|
|
|
set_param_min(PARAM_ORBIT_VELOCITY, 0);
|
|
|
|
set_param_min(PARAM_LINEAR_ACCEL, 0);
|
|
|
|
set_param_min(PARAM_RADIAL_ACCEL, 0);
|
|
|
|
set_param_min(PARAM_TANGENTIAL_ACCEL, 0);
|
|
|
|
set_param_min(PARAM_DAMPING, 0);
|
|
|
|
set_param_min(PARAM_ANGLE, 0);
|
|
|
|
set_param_min(PARAM_SCALE, 1);
|
|
|
|
set_param_min(PARAM_HUE_VARIATION, 0);
|
|
|
|
set_param_min(PARAM_ANIM_SPEED, 0);
|
|
|
|
set_param_min(PARAM_ANIM_OFFSET, 0);
|
|
|
|
set_param_max(PARAM_INITIAL_LINEAR_VELOCITY, 0);
|
|
|
|
set_param_max(PARAM_ANGULAR_VELOCITY, 0);
|
|
|
|
set_param_max(PARAM_ORBIT_VELOCITY, 0);
|
|
|
|
set_param_max(PARAM_LINEAR_ACCEL, 0);
|
|
|
|
set_param_max(PARAM_RADIAL_ACCEL, 0);
|
|
|
|
set_param_max(PARAM_TANGENTIAL_ACCEL, 0);
|
|
|
|
set_param_max(PARAM_DAMPING, 0);
|
|
|
|
set_param_max(PARAM_ANGLE, 0);
|
|
|
|
set_param_max(PARAM_SCALE, 1);
|
|
|
|
set_param_max(PARAM_HUE_VARIATION, 0);
|
|
|
|
set_param_max(PARAM_ANIM_SPEED, 0);
|
|
|
|
set_param_max(PARAM_ANIM_OFFSET, 0);
|
2021-02-10 19:22:13 +01:00
|
|
|
set_emission_shape(EMISSION_SHAPE_POINT);
|
|
|
|
set_emission_sphere_radius(1);
|
|
|
|
set_emission_box_extents(Vector3(1, 1, 1));
|
2021-07-11 15:45:21 +02:00
|
|
|
set_emission_ring_axis(Vector3(0, 0, 1.0));
|
|
|
|
set_emission_ring_height(1);
|
|
|
|
set_emission_ring_radius(1);
|
|
|
|
set_emission_ring_inner_radius(0);
|
2021-02-10 19:22:13 +01:00
|
|
|
|
|
|
|
set_gravity(Vector3(0, -9.8, 0));
|
|
|
|
|
|
|
|
for (int i = 0; i < PARTICLE_FLAG_MAX; i++) {
|
|
|
|
particle_flags[i] = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_color(Color(1, 1, 1, 1));
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|
|
|
|
|
2020-03-26 22:49:16 +01:00
|
|
|
CPUParticles3D::~CPUParticles3D() {
|
2020-03-27 19:21:27 +01:00
|
|
|
RS::get_singleton()->free(multimesh);
|
2018-07-07 01:21:13 +02:00
|
|
|
}
|