Support for CPU based particles, which aids compatibility with OpenGL ES 2.0
This commit is contained in:
parent
e19388df97
commit
7dcaabaf19
22 changed files with 2287 additions and 216 deletions
|
@ -1182,7 +1182,7 @@ RID RasterizerStorageGLES2::multimesh_create() {
|
||||||
return RID();
|
return RID();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format) {
|
void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format,VS::MultimeshCustomDataFormat p_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int RasterizerStorageGLES2::multimesh_get_instance_count(RID p_multimesh) const {
|
int RasterizerStorageGLES2::multimesh_get_instance_count(RID p_multimesh) const {
|
||||||
|
@ -1201,6 +1201,9 @@ void RasterizerStorageGLES2::multimesh_instance_set_transform_2d(RID p_multimesh
|
||||||
void RasterizerStorageGLES2::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
|
void RasterizerStorageGLES2::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageGLES2::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
|
||||||
|
}
|
||||||
|
|
||||||
RID RasterizerStorageGLES2::multimesh_get_mesh(RID p_multimesh) const {
|
RID RasterizerStorageGLES2::multimesh_get_mesh(RID p_multimesh) const {
|
||||||
return RID();
|
return RID();
|
||||||
}
|
}
|
||||||
|
@ -1217,6 +1220,15 @@ Color RasterizerStorageGLES2::multimesh_instance_get_color(RID p_multimesh, int
|
||||||
return Color();
|
return Color();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color RasterizerStorageGLES2::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
|
||||||
|
return Color();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageGLES2::multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerStorageGLES2::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
|
void RasterizerStorageGLES2::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -508,19 +508,23 @@ public:
|
||||||
|
|
||||||
virtual RID multimesh_create();
|
virtual RID multimesh_create();
|
||||||
|
|
||||||
virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format);
|
virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format,VS::MultimeshCustomDataFormat p_data=VS::MULTIMESH_CUSTOM_DATA_NONE);
|
||||||
virtual int multimesh_get_instance_count(RID p_multimesh) const;
|
virtual int multimesh_get_instance_count(RID p_multimesh) const;
|
||||||
|
|
||||||
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
|
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
|
||||||
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform);
|
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform);
|
||||||
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
|
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
|
||||||
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
|
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
|
||||||
|
virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color);
|
||||||
|
|
||||||
virtual RID multimesh_get_mesh(RID p_multimesh) const;
|
virtual RID multimesh_get_mesh(RID p_multimesh) const;
|
||||||
|
|
||||||
virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
|
virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
|
||||||
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const;
|
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const;
|
||||||
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const;
|
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const;
|
||||||
|
virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const;
|
||||||
|
|
||||||
|
virtual void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array);
|
||||||
|
|
||||||
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
|
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
|
||||||
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
|
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
|
||||||
|
|
|
@ -1336,7 +1336,7 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer
|
glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer
|
||||||
|
|
||||||
int stride = (multi_mesh->xform_floats + multi_mesh->color_floats) * 4;
|
int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4;
|
||||||
glEnableVertexAttribArray(8);
|
glEnableVertexAttribArray(8);
|
||||||
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0);
|
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0);
|
||||||
glVertexAttribDivisor(8, 1);
|
glVertexAttribDivisor(8, 1);
|
||||||
|
@ -1357,6 +1357,8 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
|
||||||
color_ofs = 8 * 4;
|
color_ofs = 8 * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int custom_data_ofs = color_ofs;
|
||||||
|
|
||||||
switch (multi_mesh->color_format) {
|
switch (multi_mesh->color_format) {
|
||||||
|
|
||||||
case VS::MULTIMESH_COLOR_NONE: {
|
case VS::MULTIMESH_COLOR_NONE: {
|
||||||
|
@ -1367,12 +1369,33 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
|
||||||
glEnableVertexAttribArray(11);
|
glEnableVertexAttribArray(11);
|
||||||
glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, ((uint8_t *)NULL) + color_ofs);
|
glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, ((uint8_t *)NULL) + color_ofs);
|
||||||
glVertexAttribDivisor(11, 1);
|
glVertexAttribDivisor(11, 1);
|
||||||
|
custom_data_ofs += 4;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case VS::MULTIMESH_COLOR_FLOAT: {
|
case VS::MULTIMESH_COLOR_FLOAT: {
|
||||||
glEnableVertexAttribArray(11);
|
glEnableVertexAttribArray(11);
|
||||||
glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + color_ofs);
|
glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + color_ofs);
|
||||||
glVertexAttribDivisor(11, 1);
|
glVertexAttribDivisor(11, 1);
|
||||||
|
custom_data_ofs += 4 * 4;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (multi_mesh->custom_data_format) {
|
||||||
|
|
||||||
|
case VS::MULTIMESH_CUSTOM_DATA_NONE: {
|
||||||
|
glDisableVertexAttribArray(12);
|
||||||
|
glVertexAttrib4f(12, 1, 1, 1, 1);
|
||||||
|
} break;
|
||||||
|
case VS::MULTIMESH_CUSTOM_DATA_8BIT: {
|
||||||
|
glEnableVertexAttribArray(12);
|
||||||
|
glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, ((uint8_t *)NULL) + custom_data_ofs);
|
||||||
|
glVertexAttribDivisor(12, 1);
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case VS::MULTIMESH_CUSTOM_DATA_FLOAT: {
|
||||||
|
glEnableVertexAttribArray(12);
|
||||||
|
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + custom_data_ofs);
|
||||||
|
glVertexAttribDivisor(12, 1);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3816,12 +3816,12 @@ RID RasterizerStorageGLES3::multimesh_create() {
|
||||||
return multimesh_owner.make_rid(multimesh);
|
return multimesh_owner.make_rid(multimesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format) {
|
void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data_format) {
|
||||||
|
|
||||||
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
|
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
|
||||||
ERR_FAIL_COND(!multimesh);
|
ERR_FAIL_COND(!multimesh);
|
||||||
|
|
||||||
if (multimesh->size == p_instances && multimesh->transform_format == p_transform_format && multimesh->color_format == p_color_format)
|
if (multimesh->size == p_instances && multimesh->transform_format == p_transform_format && multimesh->color_format == p_color_format && multimesh->custom_data_format == p_data_format)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (multimesh->buffer) {
|
if (multimesh->buffer) {
|
||||||
|
@ -3832,6 +3832,7 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
|
||||||
multimesh->size = p_instances;
|
multimesh->size = p_instances;
|
||||||
multimesh->transform_format = p_transform_format;
|
multimesh->transform_format = p_transform_format;
|
||||||
multimesh->color_format = p_color_format;
|
multimesh->color_format = p_color_format;
|
||||||
|
multimesh->custom_data_format = p_data_format;
|
||||||
|
|
||||||
if (multimesh->size) {
|
if (multimesh->size) {
|
||||||
|
|
||||||
|
@ -3849,11 +3850,22 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
|
||||||
multimesh->color_floats = 4;
|
multimesh->color_floats = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
int format_floats = multimesh->color_floats + multimesh->xform_floats;
|
if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE) {
|
||||||
|
multimesh->custom_data_floats = 0;
|
||||||
|
} else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
|
||||||
|
multimesh->custom_data_floats = 1;
|
||||||
|
} else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
|
||||||
|
multimesh->custom_data_floats = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int format_floats = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
|
||||||
|
|
||||||
multimesh->data.resize(format_floats * p_instances);
|
multimesh->data.resize(format_floats * p_instances);
|
||||||
|
|
||||||
for (int i = 0; i < p_instances; i += format_floats) {
|
for (int i = 0; i < p_instances; i += format_floats) {
|
||||||
|
|
||||||
int color_from = 0;
|
int color_from = 0;
|
||||||
|
int custom_data_from = 0;
|
||||||
|
|
||||||
if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) {
|
if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) {
|
||||||
multimesh->data[i + 0] = 1.0;
|
multimesh->data[i + 0] = 1.0;
|
||||||
|
@ -3865,6 +3877,7 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
|
||||||
multimesh->data[i + 6] = 0.0;
|
multimesh->data[i + 6] = 0.0;
|
||||||
multimesh->data[i + 7] = 0.0;
|
multimesh->data[i + 7] = 0.0;
|
||||||
color_from = 8;
|
color_from = 8;
|
||||||
|
custom_data_from = 8;
|
||||||
} else {
|
} else {
|
||||||
multimesh->data[i + 0] = 1.0;
|
multimesh->data[i + 0] = 1.0;
|
||||||
multimesh->data[i + 1] = 0.0;
|
multimesh->data[i + 1] = 0.0;
|
||||||
|
@ -3879,6 +3892,7 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
|
||||||
multimesh->data[i + 10] = 1.0;
|
multimesh->data[i + 10] = 1.0;
|
||||||
multimesh->data[i + 11] = 0.0;
|
multimesh->data[i + 11] = 0.0;
|
||||||
color_from = 12;
|
color_from = 12;
|
||||||
|
custom_data_from = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (multimesh->color_format == VS::MULTIMESH_COLOR_NONE) {
|
if (multimesh->color_format == VS::MULTIMESH_COLOR_NONE) {
|
||||||
|
@ -3892,12 +3906,33 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
|
||||||
|
|
||||||
cu.colu = 0xFFFFFFFF;
|
cu.colu = 0xFFFFFFFF;
|
||||||
multimesh->data[i + color_from + 0] = cu.colf;
|
multimesh->data[i + color_from + 0] = cu.colf;
|
||||||
|
custom_data_from = color_from + 1;
|
||||||
|
|
||||||
} else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) {
|
} else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) {
|
||||||
multimesh->data[i + color_from + 0] = 1.0;
|
multimesh->data[i + color_from + 0] = 1.0;
|
||||||
multimesh->data[i + color_from + 1] = 1.0;
|
multimesh->data[i + color_from + 1] = 1.0;
|
||||||
multimesh->data[i + color_from + 2] = 1.0;
|
multimesh->data[i + color_from + 2] = 1.0;
|
||||||
multimesh->data[i + color_from + 3] = 1.0;
|
multimesh->data[i + color_from + 3] = 1.0;
|
||||||
|
custom_data_from = color_from + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE) {
|
||||||
|
//none
|
||||||
|
} else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
|
||||||
|
|
||||||
|
union {
|
||||||
|
uint32_t colu;
|
||||||
|
float colf;
|
||||||
|
} cu;
|
||||||
|
|
||||||
|
cu.colu = 0;
|
||||||
|
multimesh->data[i + custom_data_from + 0] = cu.colf;
|
||||||
|
|
||||||
|
} else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
|
||||||
|
multimesh->data[i + custom_data_from + 0] = 0.0;
|
||||||
|
multimesh->data[i + custom_data_from + 1] = 0.0;
|
||||||
|
multimesh->data[i + custom_data_from + 2] = 0.0;
|
||||||
|
multimesh->data[i + custom_data_from + 3] = 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3958,7 +3993,7 @@ void RasterizerStorageGLES3::multimesh_instance_set_transform(RID p_multimesh, i
|
||||||
ERR_FAIL_INDEX(p_index, multimesh->size);
|
ERR_FAIL_INDEX(p_index, multimesh->size);
|
||||||
ERR_FAIL_COND(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D);
|
ERR_FAIL_COND(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D);
|
||||||
|
|
||||||
int stride = multimesh->color_floats + multimesh->xform_floats;
|
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
|
||||||
float *dataptr = &multimesh->data[stride * p_index];
|
float *dataptr = &multimesh->data[stride * p_index];
|
||||||
|
|
||||||
dataptr[0] = p_transform.basis.elements[0][0];
|
dataptr[0] = p_transform.basis.elements[0][0];
|
||||||
|
@ -3989,7 +4024,7 @@ void RasterizerStorageGLES3::multimesh_instance_set_transform_2d(RID p_multimesh
|
||||||
ERR_FAIL_INDEX(p_index, multimesh->size);
|
ERR_FAIL_INDEX(p_index, multimesh->size);
|
||||||
ERR_FAIL_COND(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_3D);
|
ERR_FAIL_COND(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_3D);
|
||||||
|
|
||||||
int stride = multimesh->color_floats + multimesh->xform_floats;
|
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
|
||||||
float *dataptr = &multimesh->data[stride * p_index];
|
float *dataptr = &multimesh->data[stride * p_index];
|
||||||
|
|
||||||
dataptr[0] = p_transform.elements[0][0];
|
dataptr[0] = p_transform.elements[0][0];
|
||||||
|
@ -4015,7 +4050,7 @@ void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh, int p
|
||||||
ERR_FAIL_INDEX(p_index, multimesh->size);
|
ERR_FAIL_INDEX(p_index, multimesh->size);
|
||||||
ERR_FAIL_COND(multimesh->color_format == VS::MULTIMESH_COLOR_NONE);
|
ERR_FAIL_COND(multimesh->color_format == VS::MULTIMESH_COLOR_NONE);
|
||||||
|
|
||||||
int stride = multimesh->color_floats + multimesh->xform_floats;
|
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
|
||||||
float *dataptr = &multimesh->data[stride * p_index + multimesh->xform_floats];
|
float *dataptr = &multimesh->data[stride * p_index + multimesh->xform_floats];
|
||||||
|
|
||||||
if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
|
if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
|
||||||
|
@ -4041,6 +4076,38 @@ void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh, int p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageGLES3::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_custom_data) {
|
||||||
|
|
||||||
|
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
|
||||||
|
ERR_FAIL_COND(!multimesh);
|
||||||
|
ERR_FAIL_INDEX(p_index, multimesh->size);
|
||||||
|
ERR_FAIL_COND(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE);
|
||||||
|
|
||||||
|
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
|
||||||
|
float *dataptr = &multimesh->data[stride * p_index + multimesh->xform_floats + multimesh->color_floats];
|
||||||
|
|
||||||
|
if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
|
||||||
|
|
||||||
|
uint8_t *data8 = (uint8_t *)dataptr;
|
||||||
|
data8[0] = CLAMP(p_custom_data.r * 255.0, 0, 255);
|
||||||
|
data8[1] = CLAMP(p_custom_data.g * 255.0, 0, 255);
|
||||||
|
data8[2] = CLAMP(p_custom_data.b * 255.0, 0, 255);
|
||||||
|
data8[3] = CLAMP(p_custom_data.a * 255.0, 0, 255);
|
||||||
|
|
||||||
|
} else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
|
||||||
|
dataptr[0] = p_custom_data.r;
|
||||||
|
dataptr[1] = p_custom_data.g;
|
||||||
|
dataptr[2] = p_custom_data.b;
|
||||||
|
dataptr[3] = p_custom_data.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
multimesh->dirty_data = true;
|
||||||
|
multimesh->dirty_aabb = true;
|
||||||
|
|
||||||
|
if (!multimesh->update_list.in_list()) {
|
||||||
|
multimesh_update_list.add(&multimesh->update_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
RID RasterizerStorageGLES3::multimesh_get_mesh(RID p_multimesh) const {
|
RID RasterizerStorageGLES3::multimesh_get_mesh(RID p_multimesh) const {
|
||||||
|
|
||||||
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
|
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
|
||||||
|
@ -4056,7 +4123,7 @@ Transform RasterizerStorageGLES3::multimesh_instance_get_transform(RID p_multime
|
||||||
ERR_FAIL_INDEX_V(p_index, multimesh->size, Transform());
|
ERR_FAIL_INDEX_V(p_index, multimesh->size, Transform());
|
||||||
ERR_FAIL_COND_V(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D, Transform());
|
ERR_FAIL_COND_V(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D, Transform());
|
||||||
|
|
||||||
int stride = multimesh->color_floats + multimesh->xform_floats;
|
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
|
||||||
float *dataptr = &multimesh->data[stride * p_index];
|
float *dataptr = &multimesh->data[stride * p_index];
|
||||||
|
|
||||||
Transform xform;
|
Transform xform;
|
||||||
|
@ -4083,7 +4150,7 @@ Transform2D RasterizerStorageGLES3::multimesh_instance_get_transform_2d(RID p_mu
|
||||||
ERR_FAIL_INDEX_V(p_index, multimesh->size, Transform2D());
|
ERR_FAIL_INDEX_V(p_index, multimesh->size, Transform2D());
|
||||||
ERR_FAIL_COND_V(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_3D, Transform2D());
|
ERR_FAIL_COND_V(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_3D, Transform2D());
|
||||||
|
|
||||||
int stride = multimesh->color_floats + multimesh->xform_floats;
|
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
|
||||||
float *dataptr = &multimesh->data[stride * p_index];
|
float *dataptr = &multimesh->data[stride * p_index];
|
||||||
|
|
||||||
Transform2D xform;
|
Transform2D xform;
|
||||||
|
@ -4105,7 +4172,7 @@ Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh, int
|
||||||
ERR_FAIL_INDEX_V(p_index, multimesh->size, Color());
|
ERR_FAIL_INDEX_V(p_index, multimesh->size, Color());
|
||||||
ERR_FAIL_COND_V(multimesh->color_format == VS::MULTIMESH_COLOR_NONE, Color());
|
ERR_FAIL_COND_V(multimesh->color_format == VS::MULTIMESH_COLOR_NONE, Color());
|
||||||
|
|
||||||
int stride = multimesh->color_floats + multimesh->xform_floats;
|
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
|
||||||
float *dataptr = &multimesh->data[stride * p_index + multimesh->xform_floats];
|
float *dataptr = &multimesh->data[stride * p_index + multimesh->xform_floats];
|
||||||
|
|
||||||
if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
|
if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
|
||||||
|
@ -4131,6 +4198,59 @@ Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh, int
|
||||||
return Color();
|
return Color();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color RasterizerStorageGLES3::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
|
||||||
|
|
||||||
|
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
|
||||||
|
ERR_FAIL_COND_V(!multimesh, Color());
|
||||||
|
ERR_FAIL_INDEX_V(p_index, multimesh->size, Color());
|
||||||
|
ERR_FAIL_COND_V(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE, Color());
|
||||||
|
|
||||||
|
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
|
||||||
|
float *dataptr = &multimesh->data[stride * p_index + multimesh->xform_floats + multimesh->color_floats];
|
||||||
|
|
||||||
|
if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
|
||||||
|
union {
|
||||||
|
uint32_t colu;
|
||||||
|
float colf;
|
||||||
|
} cu;
|
||||||
|
|
||||||
|
cu.colf = dataptr[0];
|
||||||
|
|
||||||
|
return Color::hex(BSWAP32(cu.colu));
|
||||||
|
|
||||||
|
} else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
|
||||||
|
Color c;
|
||||||
|
c.r = dataptr[0];
|
||||||
|
c.g = dataptr[1];
|
||||||
|
c.b = dataptr[2];
|
||||||
|
c.a = dataptr[3];
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Color();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageGLES3::multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) {
|
||||||
|
|
||||||
|
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
|
||||||
|
ERR_FAIL_COND(!multimesh);
|
||||||
|
|
||||||
|
int dsize = multimesh->data.size();
|
||||||
|
|
||||||
|
ERR_FAIL_COND(dsize != p_array.size());
|
||||||
|
|
||||||
|
PoolVector<float>::Read r = p_array.read();
|
||||||
|
copymem(multimesh->data.ptrw(), r.ptr(), dsize * sizeof(float));
|
||||||
|
|
||||||
|
multimesh->dirty_data = true;
|
||||||
|
multimesh->dirty_aabb = true;
|
||||||
|
|
||||||
|
if (!multimesh->update_list.in_list()) {
|
||||||
|
multimesh_update_list.add(&multimesh->update_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerStorageGLES3::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
|
void RasterizerStorageGLES3::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
|
||||||
|
|
||||||
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
|
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
|
||||||
|
@ -4179,7 +4299,7 @@ void RasterizerStorageGLES3::update_dirty_multimeshes() {
|
||||||
mesh_aabb.size += Vector3(0.001, 0.001, 0.001);
|
mesh_aabb.size += Vector3(0.001, 0.001, 0.001);
|
||||||
}
|
}
|
||||||
|
|
||||||
int stride = multimesh->color_floats + multimesh->xform_floats;
|
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
|
||||||
int count = multimesh->data.size();
|
int count = multimesh->data.size();
|
||||||
float *data = multimesh->data.ptrw();
|
float *data = multimesh->data.ptrw();
|
||||||
|
|
||||||
|
|
|
@ -756,6 +756,7 @@ public:
|
||||||
int size;
|
int size;
|
||||||
VS::MultimeshTransformFormat transform_format;
|
VS::MultimeshTransformFormat transform_format;
|
||||||
VS::MultimeshColorFormat color_format;
|
VS::MultimeshColorFormat color_format;
|
||||||
|
VS::MultimeshCustomDataFormat custom_data_format;
|
||||||
Vector<float> data;
|
Vector<float> data;
|
||||||
AABB aabb;
|
AABB aabb;
|
||||||
SelfList<MultiMesh> update_list;
|
SelfList<MultiMesh> update_list;
|
||||||
|
@ -765,6 +766,7 @@ public:
|
||||||
|
|
||||||
int xform_floats;
|
int xform_floats;
|
||||||
int color_floats;
|
int color_floats;
|
||||||
|
int custom_data_floats;
|
||||||
|
|
||||||
bool dirty_aabb;
|
bool dirty_aabb;
|
||||||
bool dirty_data;
|
bool dirty_data;
|
||||||
|
@ -776,11 +778,13 @@ public:
|
||||||
dirty_data = true;
|
dirty_data = true;
|
||||||
xform_floats = 0;
|
xform_floats = 0;
|
||||||
color_floats = 0;
|
color_floats = 0;
|
||||||
|
custom_data_floats = 0;
|
||||||
visible_instances = -1;
|
visible_instances = -1;
|
||||||
size = 0;
|
size = 0;
|
||||||
buffer = 0;
|
buffer = 0;
|
||||||
transform_format = VS::MULTIMESH_TRANSFORM_2D;
|
transform_format = VS::MULTIMESH_TRANSFORM_2D;
|
||||||
color_format = VS::MULTIMESH_COLOR_NONE;
|
color_format = VS::MULTIMESH_COLOR_NONE;
|
||||||
|
custom_data_format = VS::MULTIMESH_CUSTOM_DATA_NONE;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -792,19 +796,23 @@ public:
|
||||||
|
|
||||||
virtual RID multimesh_create();
|
virtual RID multimesh_create();
|
||||||
|
|
||||||
virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format);
|
virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data_format = VS::MULTIMESH_CUSTOM_DATA_NONE);
|
||||||
virtual int multimesh_get_instance_count(RID p_multimesh) const;
|
virtual int multimesh_get_instance_count(RID p_multimesh) const;
|
||||||
|
|
||||||
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
|
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
|
||||||
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform);
|
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform);
|
||||||
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
|
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
|
||||||
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
|
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
|
||||||
|
virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color);
|
||||||
|
|
||||||
virtual RID multimesh_get_mesh(RID p_multimesh) const;
|
virtual RID multimesh_get_mesh(RID p_multimesh) const;
|
||||||
|
|
||||||
virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
|
virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
|
||||||
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const;
|
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const;
|
||||||
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const;
|
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const;
|
||||||
|
virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const;
|
||||||
|
|
||||||
|
virtual void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array);
|
||||||
|
|
||||||
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
|
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
|
||||||
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
|
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
|
||||||
|
|
|
@ -79,6 +79,7 @@
|
||||||
#include "editor/plugins/collision_polygon_2d_editor_plugin.h"
|
#include "editor/plugins/collision_polygon_2d_editor_plugin.h"
|
||||||
#include "editor/plugins/collision_polygon_editor_plugin.h"
|
#include "editor/plugins/collision_polygon_editor_plugin.h"
|
||||||
#include "editor/plugins/collision_shape_2d_editor_plugin.h"
|
#include "editor/plugins/collision_shape_2d_editor_plugin.h"
|
||||||
|
#include "editor/plugins/cpu_particles_editor_plugin.h"
|
||||||
#include "editor/plugins/cube_grid_theme_editor_plugin.h"
|
#include "editor/plugins/cube_grid_theme_editor_plugin.h"
|
||||||
#include "editor/plugins/curve_editor_plugin.h"
|
#include "editor/plugins/curve_editor_plugin.h"
|
||||||
#include "editor/plugins/editor_preview_plugins.h"
|
#include "editor/plugins/editor_preview_plugins.h"
|
||||||
|
@ -5383,6 +5384,7 @@ EditorNode::EditorNode() {
|
||||||
add_editor_plugin(memnew(SpriteEditorPlugin(this)));
|
add_editor_plugin(memnew(SpriteEditorPlugin(this)));
|
||||||
add_editor_plugin(memnew(Skeleton2DEditorPlugin(this)));
|
add_editor_plugin(memnew(Skeleton2DEditorPlugin(this)));
|
||||||
add_editor_plugin(memnew(ParticlesEditorPlugin(this)));
|
add_editor_plugin(memnew(ParticlesEditorPlugin(this)));
|
||||||
|
add_editor_plugin(memnew(CPUParticlesEditorPlugin(this)));
|
||||||
add_editor_plugin(memnew(ResourcePreloaderEditorPlugin(this)));
|
add_editor_plugin(memnew(ResourcePreloaderEditorPlugin(this)));
|
||||||
add_editor_plugin(memnew(ItemListEditorPlugin(this)));
|
add_editor_plugin(memnew(ItemListEditorPlugin(this)));
|
||||||
add_editor_plugin(memnew(Polygon3DEditorPlugin(this)));
|
add_editor_plugin(memnew(Polygon3DEditorPlugin(this)));
|
||||||
|
|
60
editor/icons/icon_c_p_u_particles.svg
Normal file
60
editor/icons/icon_c_p_u_particles.svg
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
id="svg6"
|
||||||
|
sodipodi:docname="icon_c_p_u_particles.svg"
|
||||||
|
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||||
|
<metadata
|
||||||
|
id="metadata12">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs10" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1741"
|
||||||
|
inkscape:window-height="753"
|
||||||
|
id="namedview8"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="14.75"
|
||||||
|
inkscape:cx="8.1355932"
|
||||||
|
inkscape:cy="7.7288136"
|
||||||
|
inkscape:window-x="67"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="svg6" />
|
||||||
|
<path
|
||||||
|
style="fill:#fc9c9c;fill-opacity:0.99607843"
|
||||||
|
d="m 4.5587261,0.60940813 c -0.4226244,0 -0.7617187,0.3410473 -0.7617187,0.76367177 v 0.5078126 c 0,0.1028478 0.020058,0.199689 0.056641,0.2890624 H 2.6602887 c -0.4226245,0 -0.7617188,0.3390944 -0.7617188,0.7617188 v 0.921875 C 1.8581419,3.8469787 1.821771,3.8301112 1.7794293,3.8301112 H 1.2716168 c -0.42262448,0 -0.76367188,0.3410475 -0.76367188,0.7636719 v 0.3730468 c 0,0.4226245 0.3410474,0.7617188 0.76367188,0.7617188 h 0.5078125 c 0.042396,0 0.078663,-0.016851 0.1191406,-0.023437 v 4.4531248 c -0.040428,-0.0066 -0.076799,-0.02344 -0.1191406,-0.02344 H 1.2716168 c -0.42262448,0 -0.76367188,0.341047 -0.76367188,0.763672 v 0.373047 c 0,0.422625 0.3410474,0.761718 0.76367188,0.761718 h 0.5078125 c 0.042396,0 0.078663,-0.01685 0.1191406,-0.02344 v 1.125 c 0,0.422624 0.3390944,0.763672 0.7617188,0.763672 h 1.1367187 v 0.457031 c 0,0.422624 0.3390943,0.763672 0.7617187,0.763672 H 4.931773 c 0.4226244,0 0.7636719,-0.341048 0.7636719,-0.763672 v -0.457031 h 4.4062501 v 0.457031 c 0,0.422624 0.339094,0.763672 0.761719,0.763672 h 0.373047 c 0.422624,0 0.763671,-0.341048 0.763671,-0.763672 v -0.457031 h 1.269532 c 0.422625,0 0.763672,-0.341048 0.763672,-0.763672 v -1.111328 c 0.01774,0.0012 0.03272,0.0098 0.05078,0.0098 h 0.507812 c 0.422624,0 0.763672,-0.339093 0.763672,-0.761718 v -0.373047 c 0,-0.422624 -0.341048,-0.763672 -0.763672,-0.763672 h -0.507812 c -0.01803,0 -0.03307,0.0085 -0.05078,0.0098 V 5.7187831 c 0.01774,0.00122 0.03272,0.00977 0.05078,0.00977 h 0.507812 c 0.422624,0 0.763672,-0.3390943 0.763672,-0.7617188 V 4.5937831 c 0,-0.4226244 -0.341048,-0.7636719 -0.763672,-0.7636719 h -0.507812 c -0.01803,0 -0.03307,0.00855 -0.05078,0.00977 V 2.9316737 c 0,-0.4226244 -0.341047,-0.7617187 -0.763672,-0.7617188 h -1.328125 c 0.03658,-0.089375 0.05859,-0.1862118 0.05859,-0.2890624 V 1.3730799 c 0,-0.42262437 -0.341047,-0.76367177 -0.763671,-0.76367177 h -0.373047 c -0.422625,0 -0.761719,0.3410474 -0.761719,0.76367177 v 0.5078126 c 0,0.1028478 0.02006,0.1996891 0.05664,0.2890624 H 5.6368511 C 5.6734361,2.08058 5.6954449,1.9837431 5.6954449,1.8808925 V 1.3730799 c 0,-0.42262437 -0.3410475,-0.76367177 -0.7636719,-0.76367177 z M 7.7970074,2.9668299 A 3.279661,3.6440678 0 0 1 11.009898,5.9062831 2.1864407,2.1864407 0 0 1 12.89857,8.0683925 2.1864407,2.1864407 0 0 1 10.71107,10.25394 H 4.8809918 A 2.1864407,2.1864407 0 0 1 2.6954449,8.0683925 2.1864407,2.1864407 0 0 1 4.5802105,5.9043299 3.279661,3.6440678 0 0 1 7.7970074,2.9668299 Z M 4.8809918,10.982455 A 0.72881355,0.72881355 0 0 1 5.6095074,11.710971 0.72881355,0.72881355 0 0 1 4.8809918,12.44144 0.72881355,0.72881355 0 0 1 4.1524761,11.710971 0.72881355,0.72881355 0 0 1 4.8809918,10.982455 Z m 5.8300782,0 A 0.72881355,0.72881355 0 0 1 11.441539,11.710971 0.72881355,0.72881355 0 0 1 10.71107,12.44144 0.72881355,0.72881355 0 0 1 9.9825543,11.710971 0.72881355,0.72881355 0 0 1 10.71107,10.982455 Z M 7.7970074,11.710971 A 0.72881355,0.72881355 0 0 1 8.525523,12.44144 0.72881355,0.72881355 0 0 1 7.7970074,13.169955 0.72881355,0.72881355 0 0 1 7.0684918,12.44144 0.72881355,0.72881355 0 0 1 7.7970074,11.710971 Z"
|
||||||
|
id="rect822"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.7 KiB |
114
editor/plugins/cpu_particles_editor_plugin.cpp
Normal file
114
editor/plugins/cpu_particles_editor_plugin.cpp
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
#include "cpu_particles_editor_plugin.h"
|
||||||
|
#include "editor/plugins/spatial_editor_plugin.h"
|
||||||
|
|
||||||
|
void CPUParticlesEditor::_node_removed(Node *p_node) {
|
||||||
|
|
||||||
|
if (p_node == node) {
|
||||||
|
node = NULL;
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPUParticlesEditor::_notification(int p_notification) {
|
||||||
|
|
||||||
|
if (p_notification == NOTIFICATION_ENTER_TREE) {
|
||||||
|
options->set_icon(options->get_popup()->get_icon("CPUParticles", "EditorIcons"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPUParticlesEditor::_menu_option(int p_option) {
|
||||||
|
|
||||||
|
switch (p_option) {
|
||||||
|
|
||||||
|
case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH: {
|
||||||
|
|
||||||
|
emission_file_dialog->popup_centered_ratio();
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE: {
|
||||||
|
|
||||||
|
emission_tree_dialog->popup_centered_ratio();
|
||||||
|
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPUParticlesEditor::edit(CPUParticles *p_particles) {
|
||||||
|
|
||||||
|
base_node = p_particles;
|
||||||
|
node = p_particles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPUParticlesEditor::_generate_emission_points() {
|
||||||
|
|
||||||
|
/// hacer codigo aca
|
||||||
|
PoolVector<Vector3> points;
|
||||||
|
PoolVector<Vector3> normals;
|
||||||
|
|
||||||
|
if (!_generate(points, normals)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normals.size() == 0) {
|
||||||
|
node->set_emission_shape(CPUParticles::EMISSION_SHAPE_POINTS);
|
||||||
|
node->set_emission_points(points);
|
||||||
|
} else {
|
||||||
|
node->set_emission_shape(CPUParticles::EMISSION_SHAPE_DIRECTED_POINTS);
|
||||||
|
node->set_emission_points(points);
|
||||||
|
node->set_emission_normals(normals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPUParticlesEditor::_bind_methods() {
|
||||||
|
|
||||||
|
ClassDB::bind_method("_menu_option", &CPUParticlesEditor::_menu_option);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPUParticlesEditor::CPUParticlesEditor() {
|
||||||
|
|
||||||
|
particles_editor_hb = memnew(HBoxContainer);
|
||||||
|
SpatialEditor::get_singleton()->add_control_to_menu_panel(particles_editor_hb);
|
||||||
|
options = memnew(MenuButton);
|
||||||
|
particles_editor_hb->add_child(options);
|
||||||
|
particles_editor_hb->hide();
|
||||||
|
|
||||||
|
options->set_text(TTR("CPUParticles"));
|
||||||
|
options->get_popup()->add_item(TTR("Create Emission Points From Mesh"), MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH);
|
||||||
|
options->get_popup()->add_item(TTR("Create Emission Points From Node"), MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE);
|
||||||
|
options->get_popup()->connect("id_pressed", this, "_menu_option");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPUParticlesEditorPlugin::edit(Object *p_object) {
|
||||||
|
|
||||||
|
particles_editor->edit(Object::cast_to<CPUParticles>(p_object));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPUParticlesEditorPlugin::handles(Object *p_object) const {
|
||||||
|
|
||||||
|
return p_object->is_class("CPUParticles");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPUParticlesEditorPlugin::make_visible(bool p_visible) {
|
||||||
|
|
||||||
|
if (p_visible) {
|
||||||
|
particles_editor->show();
|
||||||
|
particles_editor->particles_editor_hb->show();
|
||||||
|
} else {
|
||||||
|
particles_editor->particles_editor_hb->hide();
|
||||||
|
particles_editor->hide();
|
||||||
|
particles_editor->edit(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CPUParticlesEditorPlugin::CPUParticlesEditorPlugin(EditorNode *p_node) {
|
||||||
|
|
||||||
|
editor = p_node;
|
||||||
|
particles_editor = memnew(CPUParticlesEditor);
|
||||||
|
editor->get_viewport()->add_child(particles_editor);
|
||||||
|
|
||||||
|
particles_editor->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPUParticlesEditorPlugin::~CPUParticlesEditorPlugin() {
|
||||||
|
}
|
55
editor/plugins/cpu_particles_editor_plugin.h
Normal file
55
editor/plugins/cpu_particles_editor_plugin.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#ifndef CPU_PARTICLES_EDITOR_PLUGIN_H
|
||||||
|
#define CPU_PARTICLES_EDITOR_PLUGIN_H
|
||||||
|
|
||||||
|
#include "editor/plugins/particles_editor_plugin.h"
|
||||||
|
#include "scene/3d/cpu_particles.h"
|
||||||
|
|
||||||
|
class CPUParticlesEditor : public ParticlesEditorBase {
|
||||||
|
|
||||||
|
GDCLASS(CPUParticlesEditor, ParticlesEditorBase);
|
||||||
|
|
||||||
|
enum Menu {
|
||||||
|
|
||||||
|
MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE,
|
||||||
|
MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH,
|
||||||
|
MENU_OPTION_CLEAR_EMISSION_VOLUME,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
CPUParticles *node;
|
||||||
|
|
||||||
|
void _menu_option(int);
|
||||||
|
|
||||||
|
friend class CPUParticlesEditorPlugin;
|
||||||
|
|
||||||
|
virtual void _generate_emission_points();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _notification(int p_notification);
|
||||||
|
void _node_removed(Node *p_node);
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void edit(CPUParticles *p_particles);
|
||||||
|
CPUParticlesEditor();
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPUParticlesEditorPlugin : public EditorPlugin {
|
||||||
|
|
||||||
|
GDCLASS(CPUParticlesEditorPlugin, EditorPlugin);
|
||||||
|
|
||||||
|
CPUParticlesEditor *particles_editor;
|
||||||
|
EditorNode *editor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual String get_name() const { return "CPUParticles"; }
|
||||||
|
bool has_main_screen() const { return false; }
|
||||||
|
virtual void edit(Object *p_object);
|
||||||
|
virtual bool handles(Object *p_object) const;
|
||||||
|
virtual void make_visible(bool p_visible);
|
||||||
|
|
||||||
|
CPUParticlesEditorPlugin(EditorNode *p_node);
|
||||||
|
~CPUParticlesEditorPlugin();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CPU_PARTICLES_EDITOR_PLUGIN_H
|
|
@ -32,15 +32,136 @@
|
||||||
#include "editor/plugins/spatial_editor_plugin.h"
|
#include "editor/plugins/spatial_editor_plugin.h"
|
||||||
#include "io/resource_loader.h"
|
#include "io/resource_loader.h"
|
||||||
|
|
||||||
void ParticlesEditor::_node_removed(Node *p_node) {
|
bool ParticlesEditorBase::_generate(PoolVector<Vector3> &points, PoolVector<Vector3> &normals) {
|
||||||
|
|
||||||
if (p_node == node) {
|
bool use_normals = emission_fill->get_selected() == 1;
|
||||||
node = NULL;
|
|
||||||
hide();
|
if (emission_fill->get_selected() < 2) {
|
||||||
|
|
||||||
|
float area_accum = 0;
|
||||||
|
Map<float, int> triangle_area_map;
|
||||||
|
print_line("geometry size: " + itos(geometry.size()));
|
||||||
|
|
||||||
|
for (int i = 0; i < geometry.size(); i++) {
|
||||||
|
|
||||||
|
float area = geometry[i].get_area();
|
||||||
|
if (area < CMP_EPSILON)
|
||||||
|
continue;
|
||||||
|
triangle_area_map[area_accum] = i;
|
||||||
|
area_accum += area;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!triangle_area_map.size() || area_accum == 0) {
|
||||||
|
|
||||||
|
err_dialog->set_text(TTR("Faces contain no area!"));
|
||||||
|
err_dialog->popup_centered_minsize();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int emissor_count = emission_amount->get_value();
|
||||||
|
|
||||||
|
for (int i = 0; i < emissor_count; i++) {
|
||||||
|
|
||||||
|
float areapos = Math::random(0.0f, area_accum);
|
||||||
|
|
||||||
|
Map<float, int>::Element *E = triangle_area_map.find_closest(areapos);
|
||||||
|
ERR_FAIL_COND_V(!E, false)
|
||||||
|
int index = E->get();
|
||||||
|
ERR_FAIL_INDEX_V(index, geometry.size(), false);
|
||||||
|
|
||||||
|
// ok FINALLY get face
|
||||||
|
Face3 face = geometry[index];
|
||||||
|
//now compute some position inside the face...
|
||||||
|
|
||||||
|
Vector3 pos = face.get_random_point_inside();
|
||||||
|
|
||||||
|
points.push_back(pos);
|
||||||
|
|
||||||
|
if (use_normals) {
|
||||||
|
Vector3 normal = face.get_plane().normal;
|
||||||
|
normals.push_back(normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
int gcount = geometry.size();
|
||||||
|
|
||||||
|
if (gcount == 0) {
|
||||||
|
|
||||||
|
err_dialog->set_text(TTR("No faces!"));
|
||||||
|
err_dialog->popup_centered_minsize();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PoolVector<Face3>::Read r = geometry.read();
|
||||||
|
|
||||||
|
AABB aabb;
|
||||||
|
|
||||||
|
for (int i = 0; i < gcount; i++) {
|
||||||
|
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
|
||||||
|
if (i == 0 && j == 0)
|
||||||
|
aabb.position = r[i].vertex[j];
|
||||||
|
else
|
||||||
|
aabb.expand_to(r[i].vertex[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int emissor_count = emission_amount->get_value();
|
||||||
|
|
||||||
|
for (int i = 0; i < emissor_count; i++) {
|
||||||
|
|
||||||
|
int attempts = 5;
|
||||||
|
|
||||||
|
for (int j = 0; j < attempts; j++) {
|
||||||
|
|
||||||
|
Vector3 dir;
|
||||||
|
dir[Math::rand() % 3] = 1.0;
|
||||||
|
Vector3 ofs = (Vector3(1, 1, 1) - dir) * Vector3(Math::randf(), Math::randf(), Math::randf()) * aabb.size + aabb.position;
|
||||||
|
|
||||||
|
Vector3 ofsv = ofs + aabb.size * dir;
|
||||||
|
|
||||||
|
//space it a little
|
||||||
|
ofs -= dir;
|
||||||
|
ofsv += dir;
|
||||||
|
|
||||||
|
float max = -1e7, min = 1e7;
|
||||||
|
|
||||||
|
for (int k = 0; k < gcount; k++) {
|
||||||
|
|
||||||
|
const Face3 &f3 = r[k];
|
||||||
|
|
||||||
|
Vector3 res;
|
||||||
|
if (f3.intersects_segment(ofs, ofsv, &res)) {
|
||||||
|
|
||||||
|
res -= ofs;
|
||||||
|
float d = dir.dot(res);
|
||||||
|
|
||||||
|
if (d < min)
|
||||||
|
min = d;
|
||||||
|
if (d > max)
|
||||||
|
max = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max < min)
|
||||||
|
continue; //lost attempt
|
||||||
|
|
||||||
|
float val = min + (max - min) * Math::randf();
|
||||||
|
|
||||||
|
Vector3 point = ofs + dir * val;
|
||||||
|
|
||||||
|
points.push_back(point);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticlesEditor::_node_selected(const NodePath &p_path) {
|
void ParticlesEditorBase::_node_selected(const NodePath &p_path) {
|
||||||
|
|
||||||
Node *sel = get_node(p_path);
|
Node *sel = get_node(p_path);
|
||||||
if (!sel)
|
if (!sel)
|
||||||
|
@ -63,7 +184,7 @@ void ParticlesEditor::_node_selected(const NodePath &p_path) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform geom_xform = node->get_global_transform().affine_inverse() * vi->get_global_transform();
|
Transform geom_xform = base_node->get_global_transform().affine_inverse() * vi->get_global_transform();
|
||||||
|
|
||||||
int gc = geometry.size();
|
int gc = geometry.size();
|
||||||
PoolVector<Face3>::Write w = geometry.write();
|
PoolVector<Face3>::Write w = geometry.write();
|
||||||
|
@ -79,6 +200,65 @@ void ParticlesEditor::_node_selected(const NodePath &p_path) {
|
||||||
emission_dialog->popup_centered(Size2(300, 130));
|
emission_dialog->popup_centered(Size2(300, 130));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParticlesEditorBase::_bind_methods() {
|
||||||
|
|
||||||
|
ClassDB::bind_method("_node_selected", &ParticlesEditorBase::_node_selected);
|
||||||
|
ClassDB::bind_method("_generate_emission_points", &ParticlesEditorBase::_generate_emission_points);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticlesEditorBase::ParticlesEditorBase() {
|
||||||
|
|
||||||
|
emission_dialog = memnew(ConfirmationDialog);
|
||||||
|
emission_dialog->set_title(TTR("Create Emitter"));
|
||||||
|
add_child(emission_dialog);
|
||||||
|
VBoxContainer *emd_vb = memnew(VBoxContainer);
|
||||||
|
emission_dialog->add_child(emd_vb);
|
||||||
|
|
||||||
|
emission_amount = memnew(SpinBox);
|
||||||
|
emission_amount->set_min(1);
|
||||||
|
emission_amount->set_max(100000);
|
||||||
|
emission_amount->set_value(512);
|
||||||
|
emd_vb->add_margin_child(TTR("Emission Points:"), emission_amount);
|
||||||
|
|
||||||
|
emission_fill = memnew(OptionButton);
|
||||||
|
emission_fill->add_item(TTR("Surface Points"));
|
||||||
|
emission_fill->add_item(TTR("Surface Points+Normal (Directed)"));
|
||||||
|
emission_fill->add_item(TTR("Volume"));
|
||||||
|
emd_vb->add_margin_child(TTR("Emission Source: "), emission_fill);
|
||||||
|
|
||||||
|
emission_dialog->get_ok()->set_text(TTR("Create"));
|
||||||
|
emission_dialog->connect("confirmed", this, "_generate_emission_points");
|
||||||
|
|
||||||
|
err_dialog = memnew(ConfirmationDialog);
|
||||||
|
add_child(err_dialog);
|
||||||
|
|
||||||
|
emission_file_dialog = memnew(EditorFileDialog);
|
||||||
|
add_child(emission_file_dialog);
|
||||||
|
emission_file_dialog->connect("file_selected", this, "_resource_seleted");
|
||||||
|
emission_tree_dialog = memnew(SceneTreeDialog);
|
||||||
|
add_child(emission_tree_dialog);
|
||||||
|
emission_tree_dialog->connect("selected", this, "_node_selected");
|
||||||
|
|
||||||
|
List<String> extensions;
|
||||||
|
ResourceLoader::get_recognized_extensions_for_type("Mesh", &extensions);
|
||||||
|
|
||||||
|
emission_file_dialog->clear_filters();
|
||||||
|
for (int i = 0; i < extensions.size(); i++) {
|
||||||
|
|
||||||
|
emission_file_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
|
||||||
|
}
|
||||||
|
|
||||||
|
emission_file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticlesEditor::_node_removed(Node *p_node) {
|
||||||
|
|
||||||
|
if (p_node == node) {
|
||||||
|
node = NULL;
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ParticlesEditor::_notification(int p_notification) {
|
void ParticlesEditor::_notification(int p_notification) {
|
||||||
|
|
||||||
if (p_notification == NOTIFICATION_ENTER_TREE) {
|
if (p_notification == NOTIFICATION_ENTER_TREE) {
|
||||||
|
@ -146,145 +326,21 @@ void ParticlesEditor::_generate_aabb() {
|
||||||
|
|
||||||
void ParticlesEditor::edit(Particles *p_particles) {
|
void ParticlesEditor::edit(Particles *p_particles) {
|
||||||
|
|
||||||
|
base_node = p_particles;
|
||||||
node = p_particles;
|
node = p_particles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticlesEditor::_generate_emission_points() {
|
void ParticlesEditor::_generate_emission_points() {
|
||||||
|
|
||||||
/// hacer codigo aca
|
/// hacer codigo aca
|
||||||
PoolVector<float> points;
|
PoolVector<Vector3> points;
|
||||||
bool use_normals = emission_fill->get_selected() == 1;
|
PoolVector<Vector3> normals;
|
||||||
PoolVector<float> normals;
|
|
||||||
|
|
||||||
if (emission_fill->get_selected() < 2) {
|
if (!_generate(points, normals)) {
|
||||||
|
return;
|
||||||
float area_accum = 0;
|
|
||||||
Map<float, int> triangle_area_map;
|
|
||||||
print_line("geometry size: " + itos(geometry.size()));
|
|
||||||
|
|
||||||
for (int i = 0; i < geometry.size(); i++) {
|
|
||||||
|
|
||||||
float area = geometry[i].get_area();
|
|
||||||
if (area < CMP_EPSILON)
|
|
||||||
continue;
|
|
||||||
triangle_area_map[area_accum] = i;
|
|
||||||
area_accum += area;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!triangle_area_map.size() || area_accum == 0) {
|
|
||||||
|
|
||||||
err_dialog->set_text(TTR("Faces contain no area!"));
|
|
||||||
err_dialog->popup_centered_minsize();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int emissor_count = emission_amount->get_value();
|
|
||||||
|
|
||||||
for (int i = 0; i < emissor_count; i++) {
|
|
||||||
|
|
||||||
float areapos = Math::random(0.0f, area_accum);
|
|
||||||
|
|
||||||
Map<float, int>::Element *E = triangle_area_map.find_closest(areapos);
|
|
||||||
ERR_FAIL_COND(!E)
|
|
||||||
int index = E->get();
|
|
||||||
ERR_FAIL_INDEX(index, geometry.size());
|
|
||||||
|
|
||||||
// ok FINALLY get face
|
|
||||||
Face3 face = geometry[index];
|
|
||||||
//now compute some position inside the face...
|
|
||||||
|
|
||||||
Vector3 pos = face.get_random_point_inside();
|
|
||||||
|
|
||||||
points.push_back(pos.x);
|
|
||||||
points.push_back(pos.y);
|
|
||||||
points.push_back(pos.z);
|
|
||||||
|
|
||||||
if (use_normals) {
|
|
||||||
Vector3 normal = face.get_plane().normal;
|
|
||||||
normals.push_back(normal.x);
|
|
||||||
normals.push_back(normal.y);
|
|
||||||
normals.push_back(normal.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
int gcount = geometry.size();
|
|
||||||
|
|
||||||
if (gcount == 0) {
|
|
||||||
|
|
||||||
err_dialog->set_text(TTR("No faces!"));
|
|
||||||
err_dialog->popup_centered_minsize();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PoolVector<Face3>::Read r = geometry.read();
|
|
||||||
|
|
||||||
AABB aabb;
|
|
||||||
|
|
||||||
for (int i = 0; i < gcount; i++) {
|
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++) {
|
|
||||||
|
|
||||||
if (i == 0 && j == 0)
|
|
||||||
aabb.position = r[i].vertex[j];
|
|
||||||
else
|
|
||||||
aabb.expand_to(r[i].vertex[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int emissor_count = emission_amount->get_value();
|
|
||||||
|
|
||||||
for (int i = 0; i < emissor_count; i++) {
|
|
||||||
|
|
||||||
int attempts = 5;
|
|
||||||
|
|
||||||
for (int j = 0; j < attempts; j++) {
|
|
||||||
|
|
||||||
Vector3 dir;
|
|
||||||
dir[Math::rand() % 3] = 1.0;
|
|
||||||
Vector3 ofs = (Vector3(1, 1, 1) - dir) * Vector3(Math::randf(), Math::randf(), Math::randf()) * aabb.size + aabb.position;
|
|
||||||
|
|
||||||
Vector3 ofsv = ofs + aabb.size * dir;
|
|
||||||
|
|
||||||
//space it a little
|
|
||||||
ofs -= dir;
|
|
||||||
ofsv += dir;
|
|
||||||
|
|
||||||
float max = -1e7, min = 1e7;
|
|
||||||
|
|
||||||
for (int k = 0; k < gcount; k++) {
|
|
||||||
|
|
||||||
const Face3 &f3 = r[k];
|
|
||||||
|
|
||||||
Vector3 res;
|
|
||||||
if (f3.intersects_segment(ofs, ofsv, &res)) {
|
|
||||||
|
|
||||||
res -= ofs;
|
|
||||||
float d = dir.dot(res);
|
|
||||||
|
|
||||||
if (d < min)
|
|
||||||
min = d;
|
|
||||||
if (d > max)
|
|
||||||
max = d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (max < min)
|
|
||||||
continue; //lost attempt
|
|
||||||
|
|
||||||
float val = min + (max - min) * Math::randf();
|
|
||||||
|
|
||||||
Vector3 point = ofs + dir * val;
|
|
||||||
|
|
||||||
points.push_back(point.x);
|
|
||||||
points.push_back(point.y);
|
|
||||||
points.push_back(point.z);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int point_count = points.size() / 3;
|
int point_count = points.size();
|
||||||
|
|
||||||
int w = 2048;
|
int w = 2048;
|
||||||
int h = (point_count / 2048) + 1;
|
int h = (point_count / 2048) + 1;
|
||||||
|
@ -295,8 +351,13 @@ void ParticlesEditor::_generate_emission_points() {
|
||||||
{
|
{
|
||||||
PoolVector<uint8_t>::Write iw = point_img.write();
|
PoolVector<uint8_t>::Write iw = point_img.write();
|
||||||
zeromem(iw.ptr(), w * h * 3 * sizeof(float));
|
zeromem(iw.ptr(), w * h * 3 * sizeof(float));
|
||||||
PoolVector<float>::Read r = points.read();
|
PoolVector<Vector3>::Read r = points.read();
|
||||||
copymem(iw.ptr(), r.ptr(), point_count * sizeof(float) * 3);
|
float *wf = (float *)iw.ptr();
|
||||||
|
for (int i = 0; i < point_count; i++) {
|
||||||
|
wf[i * 3 + 0] = r[i].x;
|
||||||
|
wf[i * 3 + 1] = r[i].y;
|
||||||
|
wf[i * 3 + 2] = r[i].z;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Image> image = memnew(Image(w, h, false, Image::FORMAT_RGBF, point_img));
|
Ref<Image> image = memnew(Image(w, h, false, Image::FORMAT_RGBF, point_img));
|
||||||
|
@ -308,7 +369,7 @@ void ParticlesEditor::_generate_emission_points() {
|
||||||
Ref<ParticlesMaterial> material = node->get_process_material();
|
Ref<ParticlesMaterial> material = node->get_process_material();
|
||||||
ERR_FAIL_COND(material.is_null());
|
ERR_FAIL_COND(material.is_null());
|
||||||
|
|
||||||
if (use_normals) {
|
if (normals.size() > 0) {
|
||||||
|
|
||||||
material->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_DIRECTED_POINTS);
|
material->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_DIRECTED_POINTS);
|
||||||
material->set_emission_point_count(point_count);
|
material->set_emission_point_count(point_count);
|
||||||
|
@ -320,8 +381,13 @@ void ParticlesEditor::_generate_emission_points() {
|
||||||
{
|
{
|
||||||
PoolVector<uint8_t>::Write iw = point_img2.write();
|
PoolVector<uint8_t>::Write iw = point_img2.write();
|
||||||
zeromem(iw.ptr(), w * h * 3 * sizeof(float));
|
zeromem(iw.ptr(), w * h * 3 * sizeof(float));
|
||||||
PoolVector<float>::Read r = normals.read();
|
PoolVector<Vector3>::Read r = normals.read();
|
||||||
copymem(iw.ptr(), r.ptr(), point_count * sizeof(float) * 3);
|
float *wf = (float *)iw.ptr();
|
||||||
|
for (int i = 0; i < point_count; i++) {
|
||||||
|
wf[i * 3 + 0] = r[i].x;
|
||||||
|
wf[i * 3 + 1] = r[i].y;
|
||||||
|
wf[i * 3 + 2] = r[i].z;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Image> image2 = memnew(Image(w, h, false, Image::FORMAT_RGBF, point_img2));
|
Ref<Image> image2 = memnew(Image(w, h, false, Image::FORMAT_RGBF, point_img2));
|
||||||
|
@ -342,8 +408,6 @@ void ParticlesEditor::_generate_emission_points() {
|
||||||
void ParticlesEditor::_bind_methods() {
|
void ParticlesEditor::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method("_menu_option", &ParticlesEditor::_menu_option);
|
ClassDB::bind_method("_menu_option", &ParticlesEditor::_menu_option);
|
||||||
ClassDB::bind_method("_node_selected", &ParticlesEditor::_node_selected);
|
|
||||||
ClassDB::bind_method("_generate_emission_points", &ParticlesEditor::_generate_emission_points);
|
|
||||||
ClassDB::bind_method("_generate_aabb", &ParticlesEditor::_generate_aabb);
|
ClassDB::bind_method("_generate_aabb", &ParticlesEditor::_generate_aabb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,48 +426,6 @@ ParticlesEditor::ParticlesEditor() {
|
||||||
options->get_popup()->add_item(TTR("Create Emission Points From Node"), MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE);
|
options->get_popup()->add_item(TTR("Create Emission Points From Node"), MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE);
|
||||||
options->get_popup()->connect("id_pressed", this, "_menu_option");
|
options->get_popup()->connect("id_pressed", this, "_menu_option");
|
||||||
|
|
||||||
emission_dialog = memnew(ConfirmationDialog);
|
|
||||||
emission_dialog->set_title(TTR("Create Emitter"));
|
|
||||||
add_child(emission_dialog);
|
|
||||||
VBoxContainer *emd_vb = memnew(VBoxContainer);
|
|
||||||
emission_dialog->add_child(emd_vb);
|
|
||||||
|
|
||||||
emission_amount = memnew(SpinBox);
|
|
||||||
emission_amount->set_min(1);
|
|
||||||
emission_amount->set_max(100000);
|
|
||||||
emission_amount->set_value(512);
|
|
||||||
emd_vb->add_margin_child(TTR("Emission Points:"), emission_amount);
|
|
||||||
|
|
||||||
emission_fill = memnew(OptionButton);
|
|
||||||
emission_fill->add_item(TTR("Surface Points"));
|
|
||||||
emission_fill->add_item(TTR("Surface Points+Normal (Directed)"));
|
|
||||||
emission_fill->add_item(TTR("Volume"));
|
|
||||||
emd_vb->add_margin_child(TTR("Emission Source: "), emission_fill);
|
|
||||||
|
|
||||||
emission_dialog->get_ok()->set_text(TTR("Create"));
|
|
||||||
emission_dialog->connect("confirmed", this, "_generate_emission_points");
|
|
||||||
|
|
||||||
err_dialog = memnew(ConfirmationDialog);
|
|
||||||
add_child(err_dialog);
|
|
||||||
|
|
||||||
emission_file_dialog = memnew(EditorFileDialog);
|
|
||||||
add_child(emission_file_dialog);
|
|
||||||
emission_file_dialog->connect("file_selected", this, "_resource_seleted");
|
|
||||||
emission_tree_dialog = memnew(SceneTreeDialog);
|
|
||||||
add_child(emission_tree_dialog);
|
|
||||||
emission_tree_dialog->connect("selected", this, "_node_selected");
|
|
||||||
|
|
||||||
List<String> extensions;
|
|
||||||
ResourceLoader::get_recognized_extensions_for_type("Mesh", &extensions);
|
|
||||||
|
|
||||||
emission_file_dialog->clear_filters();
|
|
||||||
for (int i = 0; i < extensions.size(); i++) {
|
|
||||||
|
|
||||||
emission_file_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
|
|
||||||
}
|
|
||||||
|
|
||||||
emission_file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
|
|
||||||
|
|
||||||
generate_aabb = memnew(ConfirmationDialog);
|
generate_aabb = memnew(ConfirmationDialog);
|
||||||
generate_aabb->set_title(TTR("Generate Visibility AABB"));
|
generate_aabb->set_title(TTR("Generate Visibility AABB"));
|
||||||
VBoxContainer *genvb = memnew(VBoxContainer);
|
VBoxContainer *genvb = memnew(VBoxContainer);
|
||||||
|
|
|
@ -40,14 +40,14 @@
|
||||||
@author Juan Linietsky <reduzio@gmail.com>
|
@author Juan Linietsky <reduzio@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ParticlesEditor : public Control {
|
class ParticlesEditorBase : public Control {
|
||||||
|
|
||||||
GDCLASS(ParticlesEditor, Control);
|
|
||||||
|
|
||||||
|
GDCLASS(ParticlesEditorBase, Control)
|
||||||
|
protected:
|
||||||
|
Spatial *base_node;
|
||||||
Panel *panel;
|
Panel *panel;
|
||||||
MenuButton *options;
|
MenuButton *options;
|
||||||
HBoxContainer *particles_editor_hb;
|
HBoxContainer *particles_editor_hb;
|
||||||
Particles *node;
|
|
||||||
|
|
||||||
EditorFileDialog *emission_file_dialog;
|
EditorFileDialog *emission_file_dialog;
|
||||||
SceneTreeDialog *emission_tree_dialog;
|
SceneTreeDialog *emission_tree_dialog;
|
||||||
|
@ -58,8 +58,25 @@ class ParticlesEditor : public Control {
|
||||||
SpinBox *emission_amount;
|
SpinBox *emission_amount;
|
||||||
OptionButton *emission_fill;
|
OptionButton *emission_fill;
|
||||||
|
|
||||||
|
PoolVector<Face3> geometry;
|
||||||
|
|
||||||
|
bool _generate(PoolVector<Vector3> &points, PoolVector<Vector3> &normals);
|
||||||
|
virtual void _generate_emission_points() = 0;
|
||||||
|
void _node_selected(const NodePath &p_path);
|
||||||
|
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
ParticlesEditorBase();
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParticlesEditor : public ParticlesEditorBase {
|
||||||
|
|
||||||
|
GDCLASS(ParticlesEditor, ParticlesEditorBase);
|
||||||
|
|
||||||
ConfirmationDialog *generate_aabb;
|
ConfirmationDialog *generate_aabb;
|
||||||
SpinBox *generate_seconds;
|
SpinBox *generate_seconds;
|
||||||
|
Particles *node;
|
||||||
|
|
||||||
enum Menu {
|
enum Menu {
|
||||||
|
|
||||||
|
@ -70,18 +87,14 @@ class ParticlesEditor : public Control {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PoolVector<Face3> geometry;
|
|
||||||
|
|
||||||
void _generate_aabb();
|
void _generate_aabb();
|
||||||
void _generate_emission_points();
|
|
||||||
void _node_selected(const NodePath &p_path);
|
|
||||||
|
|
||||||
void _menu_option(int);
|
void _menu_option(int);
|
||||||
|
|
||||||
void _populate();
|
|
||||||
|
|
||||||
friend class ParticlesEditorPlugin;
|
friend class ParticlesEditorPlugin;
|
||||||
|
|
||||||
|
virtual void _generate_emission_points();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_notification);
|
void _notification(int p_notification);
|
||||||
void _node_removed(Node *p_node);
|
void _node_removed(Node *p_node);
|
||||||
|
|
1338
scene/3d/cpu_particles.cpp
Normal file
1338
scene/3d/cpu_particles.cpp
Normal file
File diff suppressed because it is too large
Load diff
256
scene/3d/cpu_particles.h
Normal file
256
scene/3d/cpu_particles.h
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
#ifndef CPU_PARTICLES_H
|
||||||
|
#define CPU_PARTICLES_H
|
||||||
|
#include "rid.h"
|
||||||
|
#include "scene/3d/visual_instance.h"
|
||||||
|
#include "scene/main/timer.h"
|
||||||
|
#include "scene/resources/material.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
@author Juan Linietsky <reduzio@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
class CPUParticles : public GeometryInstance {
|
||||||
|
private:
|
||||||
|
GDCLASS(CPUParticles, GeometryInstance);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum DrawOrder {
|
||||||
|
DRAW_ORDER_INDEX,
|
||||||
|
DRAW_ORDER_LIFETIME,
|
||||||
|
DRAW_ORDER_VIEW_DEPTH,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Parameter {
|
||||||
|
|
||||||
|
PARAM_INITIAL_LINEAR_VELOCITY,
|
||||||
|
PARAM_ANGULAR_VELOCITY,
|
||||||
|
//PARAM_ORBIT_VELOCITY,
|
||||||
|
PARAM_LINEAR_ACCEL,
|
||||||
|
PARAM_RADIAL_ACCEL,
|
||||||
|
PARAM_TANGENTIAL_ACCEL,
|
||||||
|
PARAM_DAMPING,
|
||||||
|
PARAM_ANGLE,
|
||||||
|
PARAM_SCALE,
|
||||||
|
PARAM_HUE_VARIATION,
|
||||||
|
PARAM_ANIM_SPEED,
|
||||||
|
PARAM_ANIM_OFFSET,
|
||||||
|
PARAM_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Flags {
|
||||||
|
FLAG_ALIGN_Y_TO_VELOCITY,
|
||||||
|
FLAG_ROTATE_Y,
|
||||||
|
FLAG_DISABLE_Z,
|
||||||
|
FLAG_ANIM_LOOP,
|
||||||
|
FLAG_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EmissionShape {
|
||||||
|
EMISSION_SHAPE_POINT,
|
||||||
|
EMISSION_SHAPE_SPHERE,
|
||||||
|
EMISSION_SHAPE_BOX,
|
||||||
|
EMISSION_SHAPE_POINTS,
|
||||||
|
EMISSION_SHAPE_DIRECTED_POINTS,
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool emitting;
|
||||||
|
|
||||||
|
struct Particle {
|
||||||
|
Transform transform;
|
||||||
|
Color color;
|
||||||
|
float custom[4];
|
||||||
|
Vector3 velocity;
|
||||||
|
bool active;
|
||||||
|
float angle_rand;
|
||||||
|
float scale_rand;
|
||||||
|
float hue_rot_rand;
|
||||||
|
float anim_offset_rand;
|
||||||
|
float time;
|
||||||
|
Color base_color;
|
||||||
|
|
||||||
|
uint32_t seed;
|
||||||
|
};
|
||||||
|
|
||||||
|
float time;
|
||||||
|
float inactive_time;
|
||||||
|
float frame_remainder;
|
||||||
|
int cycle;
|
||||||
|
|
||||||
|
RID multimesh;
|
||||||
|
|
||||||
|
PoolVector<Particle> particles;
|
||||||
|
PoolVector<float> particle_data;
|
||||||
|
PoolVector<int> particle_order;
|
||||||
|
|
||||||
|
struct SortLifetime {
|
||||||
|
const Particle *particles;
|
||||||
|
|
||||||
|
bool operator()(int p_a, int p_b) const {
|
||||||
|
return particles[p_a].time < particles[p_b].time;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SortAxis {
|
||||||
|
const Particle *particles;
|
||||||
|
Vector3 axis;
|
||||||
|
bool operator()(int p_a, int p_b) const {
|
||||||
|
|
||||||
|
return axis.dot(particles[p_a].transform.origin) < axis.dot(particles[p_b].transform.origin);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
bool one_shot;
|
||||||
|
|
||||||
|
float lifetime;
|
||||||
|
float pre_process_time;
|
||||||
|
float explosiveness_ratio;
|
||||||
|
float randomness_ratio;
|
||||||
|
float speed_scale;
|
||||||
|
bool local_coords;
|
||||||
|
int fixed_fps;
|
||||||
|
bool fractional_delta;
|
||||||
|
|
||||||
|
DrawOrder draw_order;
|
||||||
|
|
||||||
|
Ref<Mesh> mesh;
|
||||||
|
|
||||||
|
////////
|
||||||
|
|
||||||
|
float spread;
|
||||||
|
float flatness;
|
||||||
|
|
||||||
|
float parameters[PARAM_MAX];
|
||||||
|
float randomness[PARAM_MAX];
|
||||||
|
|
||||||
|
Ref<Curve> curve_parameters[PARAM_MAX];
|
||||||
|
Color color;
|
||||||
|
Ref<Gradient> color_ramp;
|
||||||
|
|
||||||
|
bool flags[FLAG_MAX];
|
||||||
|
|
||||||
|
EmissionShape emission_shape;
|
||||||
|
float emission_sphere_radius;
|
||||||
|
Vector3 emission_box_extents;
|
||||||
|
PoolVector<Vector3> emission_points;
|
||||||
|
PoolVector<Vector3> emission_normals;
|
||||||
|
PoolVector<Color> emission_colors;
|
||||||
|
int emission_point_count;
|
||||||
|
|
||||||
|
bool anim_loop;
|
||||||
|
Vector3 gravity;
|
||||||
|
|
||||||
|
void _particles_process(float p_delta);
|
||||||
|
void _update_particle_data_buffer();
|
||||||
|
|
||||||
|
Mutex *update_mutex;
|
||||||
|
|
||||||
|
void _update_render_thread();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
void _notification(int p_what);
|
||||||
|
virtual void _validate_property(PropertyInfo &property) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AABB get_aabb() const;
|
||||||
|
PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||||
|
|
||||||
|
void set_emitting(bool p_emitting);
|
||||||
|
void set_amount(int p_amount);
|
||||||
|
void set_lifetime(float p_lifetime);
|
||||||
|
void set_one_shot(bool p_one_shot);
|
||||||
|
void set_pre_process_time(float p_time);
|
||||||
|
void set_explosiveness_ratio(float p_ratio);
|
||||||
|
void set_randomness_ratio(float p_ratio);
|
||||||
|
void set_visibility_aabb(const AABB &p_aabb);
|
||||||
|
void set_use_local_coordinates(bool p_enable);
|
||||||
|
void set_speed_scale(float p_scale);
|
||||||
|
|
||||||
|
bool is_emitting() const;
|
||||||
|
int get_amount() const;
|
||||||
|
float get_lifetime() const;
|
||||||
|
bool get_one_shot() const;
|
||||||
|
float get_pre_process_time() const;
|
||||||
|
float get_explosiveness_ratio() const;
|
||||||
|
float get_randomness_ratio() const;
|
||||||
|
AABB get_visibility_aabb() const;
|
||||||
|
bool get_use_local_coordinates() const;
|
||||||
|
float get_speed_scale() const;
|
||||||
|
|
||||||
|
void set_fixed_fps(int p_count);
|
||||||
|
int get_fixed_fps() const;
|
||||||
|
|
||||||
|
void set_fractional_delta(bool p_enable);
|
||||||
|
bool get_fractional_delta() const;
|
||||||
|
|
||||||
|
void set_draw_order(DrawOrder p_order);
|
||||||
|
DrawOrder get_draw_order() const;
|
||||||
|
|
||||||
|
void set_draw_passes(int p_count);
|
||||||
|
int get_draw_passes() const;
|
||||||
|
|
||||||
|
void set_mesh(const Ref<Mesh> &p_mesh);
|
||||||
|
Ref<Mesh> get_mesh() const;
|
||||||
|
|
||||||
|
///////////////////
|
||||||
|
|
||||||
|
void set_spread(float p_spread);
|
||||||
|
float get_spread() const;
|
||||||
|
|
||||||
|
void set_flatness(float p_flatness);
|
||||||
|
float get_flatness() const;
|
||||||
|
|
||||||
|
void set_param(Parameter p_param, float p_value);
|
||||||
|
float get_param(Parameter p_param) const;
|
||||||
|
|
||||||
|
void set_param_randomness(Parameter p_param, float p_value);
|
||||||
|
float get_param_randomness(Parameter p_param) const;
|
||||||
|
|
||||||
|
void set_param_curve(Parameter p_param, const Ref<Curve> &p_curve);
|
||||||
|
Ref<Curve> get_param_curve(Parameter p_param) const;
|
||||||
|
|
||||||
|
void set_color(const Color &p_color);
|
||||||
|
Color get_color() const;
|
||||||
|
|
||||||
|
void set_color_ramp(const Ref<Gradient> &p_texture);
|
||||||
|
Ref<Gradient> get_color_ramp() const;
|
||||||
|
|
||||||
|
void set_particle_flag(Flags p_flag, bool p_enable);
|
||||||
|
bool get_particle_flag(Flags p_flag) const;
|
||||||
|
|
||||||
|
void set_emission_shape(EmissionShape p_shape);
|
||||||
|
void set_emission_sphere_radius(float p_radius);
|
||||||
|
void set_emission_box_extents(Vector3 p_extents);
|
||||||
|
void set_emission_points(const PoolVector<Vector3> &p_points);
|
||||||
|
void set_emission_normals(const PoolVector<Vector3> &p_normals);
|
||||||
|
void set_emission_colors(const PoolVector<Color> &p_colors);
|
||||||
|
void set_emission_point_count(int p_count);
|
||||||
|
|
||||||
|
EmissionShape get_emission_shape() const;
|
||||||
|
float get_emission_sphere_radius() const;
|
||||||
|
Vector3 get_emission_box_extents() const;
|
||||||
|
PoolVector<Vector3> get_emission_points() const;
|
||||||
|
PoolVector<Vector3> get_emission_normals() const;
|
||||||
|
PoolVector<Color> get_emission_colors() const;
|
||||||
|
int get_emission_point_count() const;
|
||||||
|
|
||||||
|
void set_gravity(const Vector3 &p_gravity);
|
||||||
|
Vector3 get_gravity() const;
|
||||||
|
|
||||||
|
virtual String get_configuration_warning() const;
|
||||||
|
|
||||||
|
void restart();
|
||||||
|
|
||||||
|
CPUParticles();
|
||||||
|
~CPUParticles();
|
||||||
|
};
|
||||||
|
|
||||||
|
VARIANT_ENUM_CAST(CPUParticles::DrawOrder)
|
||||||
|
VARIANT_ENUM_CAST(CPUParticles::Parameter)
|
||||||
|
VARIANT_ENUM_CAST(CPUParticles::Flags)
|
||||||
|
VARIANT_ENUM_CAST(CPUParticles::EmissionShape)
|
||||||
|
|
||||||
|
#endif // CPU_PARTICLES_H
|
|
@ -51,6 +51,7 @@
|
||||||
#include "scene/2d/parallax_background.h"
|
#include "scene/2d/parallax_background.h"
|
||||||
#include "scene/2d/parallax_layer.h"
|
#include "scene/2d/parallax_layer.h"
|
||||||
#include "scene/2d/particles_2d.h"
|
#include "scene/2d/particles_2d.h"
|
||||||
|
|
||||||
#include "scene/2d/path_2d.h"
|
#include "scene/2d/path_2d.h"
|
||||||
#include "scene/2d/physics_body_2d.h"
|
#include "scene/2d/physics_body_2d.h"
|
||||||
#include "scene/2d/polygon_2d.h"
|
#include "scene/2d/polygon_2d.h"
|
||||||
|
@ -161,6 +162,7 @@
|
||||||
#include "scene/resources/world_2d.h"
|
#include "scene/resources/world_2d.h"
|
||||||
#include "scene/scene_string_names.h"
|
#include "scene/scene_string_names.h"
|
||||||
|
|
||||||
|
#include "scene/3d/cpu_particles.h"
|
||||||
#include "scene/3d/particles.h"
|
#include "scene/3d/particles.h"
|
||||||
#include "scene/3d/scenario_fx.h"
|
#include "scene/3d/scenario_fx.h"
|
||||||
#include "scene/3d/spatial.h"
|
#include "scene/3d/spatial.h"
|
||||||
|
@ -383,6 +385,7 @@ void register_scene_types() {
|
||||||
ClassDB::register_class<BakedLightmapData>();
|
ClassDB::register_class<BakedLightmapData>();
|
||||||
ClassDB::register_class<AnimationTreePlayer>();
|
ClassDB::register_class<AnimationTreePlayer>();
|
||||||
ClassDB::register_class<Particles>();
|
ClassDB::register_class<Particles>();
|
||||||
|
ClassDB::register_class<CPUParticles>();
|
||||||
ClassDB::register_class<Position3D>();
|
ClassDB::register_class<Position3D>();
|
||||||
ClassDB::register_class<NavigationMeshInstance>();
|
ClassDB::register_class<NavigationMeshInstance>();
|
||||||
ClassDB::register_class<NavigationMesh>();
|
ClassDB::register_class<NavigationMesh>();
|
||||||
|
|
|
@ -479,6 +479,16 @@ real_t Curve::interpolate_baked(real_t offset) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Curve::ensure_default_setup(float p_min, float p_max) {
|
||||||
|
if (_points.size() == 0 && _min_value == 0 && _max_value == 1) {
|
||||||
|
|
||||||
|
add_point(Vector2(0, 1));
|
||||||
|
add_point(Vector2(1, 1));
|
||||||
|
set_min_value(p_min);
|
||||||
|
set_max_value(p_max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Curve::_bind_methods() {
|
void Curve::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("add_point", "position", "left_tangent", "right_tangent", "left_mode", "right_mode"), &Curve::add_point, DEFVAL(0), DEFVAL(0), DEFVAL(TANGENT_FREE), DEFVAL(TANGENT_FREE));
|
ClassDB::bind_method(D_METHOD("add_point", "position", "left_tangent", "right_tangent", "left_mode", "right_mode"), &Curve::add_point, DEFVAL(0), DEFVAL(0), DEFVAL(TANGENT_FREE), DEFVAL(TANGENT_FREE));
|
||||||
|
|
|
@ -128,6 +128,8 @@ public:
|
||||||
void set_bake_resolution(int p_resolution);
|
void set_bake_resolution(int p_resolution);
|
||||||
real_t interpolate_baked(real_t offset);
|
real_t interpolate_baked(real_t offset);
|
||||||
|
|
||||||
|
void ensure_default_setup(float p_min, float p_max);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
|
|
@ -282,19 +282,23 @@ public:
|
||||||
|
|
||||||
virtual RID multimesh_create() = 0;
|
virtual RID multimesh_create() = 0;
|
||||||
|
|
||||||
virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format) = 0;
|
virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data = VS::MULTIMESH_CUSTOM_DATA_NONE) = 0;
|
||||||
virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
|
virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
|
||||||
|
|
||||||
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
|
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
|
||||||
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0;
|
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0;
|
||||||
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0;
|
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0;
|
||||||
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0;
|
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0;
|
||||||
|
virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0;
|
||||||
|
|
||||||
virtual RID multimesh_get_mesh(RID p_multimesh) const = 0;
|
virtual RID multimesh_get_mesh(RID p_multimesh) const = 0;
|
||||||
|
|
||||||
virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
|
virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
|
||||||
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0;
|
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0;
|
||||||
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
|
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
|
||||||
|
virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
|
||||||
|
|
||||||
|
virtual void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) = 0;
|
||||||
|
|
||||||
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
|
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
|
||||||
virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;
|
virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;
|
||||||
|
|
|
@ -97,6 +97,8 @@ void VisualServerRaster::draw(bool p_swap_buffers) {
|
||||||
|
|
||||||
changes = 0;
|
changes = 0;
|
||||||
|
|
||||||
|
VS::get_singleton()->emit_signal("frame_pre_draw");
|
||||||
|
|
||||||
VSG::rasterizer->begin_frame();
|
VSG::rasterizer->begin_frame();
|
||||||
|
|
||||||
VSG::scene->update_dirty_instances(); //update scene stuff
|
VSG::scene->update_dirty_instances(); //update scene stuff
|
||||||
|
@ -122,7 +124,7 @@ void VisualServerRaster::draw(bool p_swap_buffers) {
|
||||||
frame_drawn_callbacks.pop_front();
|
frame_drawn_callbacks.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_signal("frame_drawn_in_thread");
|
VS::get_singleton()->emit_signal("frame_post_draw");
|
||||||
}
|
}
|
||||||
void VisualServerRaster::sync() {
|
void VisualServerRaster::sync() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,13 +246,14 @@ public:
|
||||||
|
|
||||||
BIND0R(RID, multimesh_create)
|
BIND0R(RID, multimesh_create)
|
||||||
|
|
||||||
BIND4(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat)
|
BIND5(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat, MultimeshCustomDataFormat)
|
||||||
BIND1RC(int, multimesh_get_instance_count, RID)
|
BIND1RC(int, multimesh_get_instance_count, RID)
|
||||||
|
|
||||||
BIND2(multimesh_set_mesh, RID, RID)
|
BIND2(multimesh_set_mesh, RID, RID)
|
||||||
BIND3(multimesh_instance_set_transform, RID, int, const Transform &)
|
BIND3(multimesh_instance_set_transform, RID, int, const Transform &)
|
||||||
BIND3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
|
BIND3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
|
||||||
BIND3(multimesh_instance_set_color, RID, int, const Color &)
|
BIND3(multimesh_instance_set_color, RID, int, const Color &)
|
||||||
|
BIND3(multimesh_instance_set_custom_data, RID, int, const Color &)
|
||||||
|
|
||||||
BIND1RC(RID, multimesh_get_mesh, RID)
|
BIND1RC(RID, multimesh_get_mesh, RID)
|
||||||
BIND1RC(AABB, multimesh_get_aabb, RID)
|
BIND1RC(AABB, multimesh_get_aabb, RID)
|
||||||
|
@ -260,6 +261,9 @@ public:
|
||||||
BIND2RC(Transform, multimesh_instance_get_transform, RID, int)
|
BIND2RC(Transform, multimesh_instance_get_transform, RID, int)
|
||||||
BIND2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
|
BIND2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
|
||||||
BIND2RC(Color, multimesh_instance_get_color, RID, int)
|
BIND2RC(Color, multimesh_instance_get_color, RID, int)
|
||||||
|
BIND2RC(Color, multimesh_instance_get_custom_data, RID, int)
|
||||||
|
|
||||||
|
BIND2(multimesh_set_as_bulk_array, RID, const PoolVector<float> &)
|
||||||
|
|
||||||
BIND2(multimesh_set_visible_instances, RID, int)
|
BIND2(multimesh_set_visible_instances, RID, int)
|
||||||
BIND1RC(int, multimesh_get_visible_instances, RID)
|
BIND1RC(int, multimesh_get_visible_instances, RID)
|
||||||
|
|
|
@ -180,13 +180,14 @@ public:
|
||||||
|
|
||||||
FUNCRID(multimesh)
|
FUNCRID(multimesh)
|
||||||
|
|
||||||
FUNC4(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat)
|
FUNC5(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat, MultimeshCustomDataFormat)
|
||||||
FUNC1RC(int, multimesh_get_instance_count, RID)
|
FUNC1RC(int, multimesh_get_instance_count, RID)
|
||||||
|
|
||||||
FUNC2(multimesh_set_mesh, RID, RID)
|
FUNC2(multimesh_set_mesh, RID, RID)
|
||||||
FUNC3(multimesh_instance_set_transform, RID, int, const Transform &)
|
FUNC3(multimesh_instance_set_transform, RID, int, const Transform &)
|
||||||
FUNC3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
|
FUNC3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
|
||||||
FUNC3(multimesh_instance_set_color, RID, int, const Color &)
|
FUNC3(multimesh_instance_set_color, RID, int, const Color &)
|
||||||
|
FUNC3(multimesh_instance_set_custom_data, RID, int, const Color &)
|
||||||
|
|
||||||
FUNC1RC(RID, multimesh_get_mesh, RID)
|
FUNC1RC(RID, multimesh_get_mesh, RID)
|
||||||
FUNC1RC(AABB, multimesh_get_aabb, RID)
|
FUNC1RC(AABB, multimesh_get_aabb, RID)
|
||||||
|
@ -194,6 +195,9 @@ public:
|
||||||
FUNC2RC(Transform, multimesh_instance_get_transform, RID, int)
|
FUNC2RC(Transform, multimesh_instance_get_transform, RID, int)
|
||||||
FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
|
FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
|
||||||
FUNC2RC(Color, multimesh_instance_get_color, RID, int)
|
FUNC2RC(Color, multimesh_instance_get_color, RID, int)
|
||||||
|
FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int)
|
||||||
|
|
||||||
|
FUNC2(multimesh_set_as_bulk_array, RID, const PoolVector<float> &)
|
||||||
|
|
||||||
FUNC2(multimesh_set_visible_instances, RID, int)
|
FUNC2(multimesh_set_visible_instances, RID, int)
|
||||||
FUNC1RC(int, multimesh_get_visible_instances, RID)
|
FUNC1RC(int, multimesh_get_visible_instances, RID)
|
||||||
|
|
|
@ -1587,19 +1587,22 @@ void VisualServer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("mesh_get_custom_aabb", "mesh"), &VisualServer::mesh_get_custom_aabb);
|
ClassDB::bind_method(D_METHOD("mesh_get_custom_aabb", "mesh"), &VisualServer::mesh_get_custom_aabb);
|
||||||
ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &VisualServer::mesh_clear);
|
ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &VisualServer::mesh_clear);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format"), &VisualServer::multimesh_allocate);
|
ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &VisualServer::multimesh_allocate, DEFVAL(MULTIMESH_CUSTOM_DATA_NONE));
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_get_instance_count", "multimesh"), &VisualServer::multimesh_get_instance_count);
|
ClassDB::bind_method(D_METHOD("multimesh_get_instance_count", "multimesh"), &VisualServer::multimesh_get_instance_count);
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_set_mesh", "multimesh", "mesh"), &VisualServer::multimesh_set_mesh);
|
ClassDB::bind_method(D_METHOD("multimesh_set_mesh", "multimesh", "mesh"), &VisualServer::multimesh_set_mesh);
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform", "multimesh", "index", "transform"), &VisualServer::multimesh_instance_set_transform);
|
ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform", "multimesh", "index", "transform"), &VisualServer::multimesh_instance_set_transform);
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform_2d", "multimesh", "index", "transform"), &VisualServer::multimesh_instance_set_transform_2d);
|
ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform_2d", "multimesh", "index", "transform"), &VisualServer::multimesh_instance_set_transform_2d);
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_instance_set_color", "multimesh", "index", "color"), &VisualServer::multimesh_instance_set_color);
|
ClassDB::bind_method(D_METHOD("multimesh_instance_set_color", "multimesh", "index", "color"), &VisualServer::multimesh_instance_set_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("multimesh_instance_set_custom_data", "multimesh", "index", "custom_data"), &VisualServer::multimesh_instance_set_custom_data);
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_get_mesh", "multimesh"), &VisualServer::multimesh_get_mesh);
|
ClassDB::bind_method(D_METHOD("multimesh_get_mesh", "multimesh"), &VisualServer::multimesh_get_mesh);
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_get_aabb", "multimesh"), &VisualServer::multimesh_get_aabb);
|
ClassDB::bind_method(D_METHOD("multimesh_get_aabb", "multimesh"), &VisualServer::multimesh_get_aabb);
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_instance_get_transform", "multimesh", "index"), &VisualServer::multimesh_instance_get_transform);
|
ClassDB::bind_method(D_METHOD("multimesh_instance_get_transform", "multimesh", "index"), &VisualServer::multimesh_instance_get_transform);
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_instance_get_transform_2d", "multimesh", "index"), &VisualServer::multimesh_instance_get_transform_2d);
|
ClassDB::bind_method(D_METHOD("multimesh_instance_get_transform_2d", "multimesh", "index"), &VisualServer::multimesh_instance_get_transform_2d);
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_instance_get_color", "multimesh", "index"), &VisualServer::multimesh_instance_get_color);
|
ClassDB::bind_method(D_METHOD("multimesh_instance_get_color", "multimesh", "index"), &VisualServer::multimesh_instance_get_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("multimesh_instance_get_custom_data", "multimesh", "index"), &VisualServer::multimesh_instance_get_custom_data);
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_set_visible_instances", "multimesh", "visible"), &VisualServer::multimesh_set_visible_instances);
|
ClassDB::bind_method(D_METHOD("multimesh_set_visible_instances", "multimesh", "visible"), &VisualServer::multimesh_set_visible_instances);
|
||||||
ClassDB::bind_method(D_METHOD("multimesh_get_visible_instances", "multimesh"), &VisualServer::multimesh_get_visible_instances);
|
ClassDB::bind_method(D_METHOD("multimesh_get_visible_instances", "multimesh"), &VisualServer::multimesh_get_visible_instances);
|
||||||
|
ClassDB::bind_method(D_METHOD("multimesh_set_as_bulk_array", "multimesh", "array"), &VisualServer::multimesh_set_as_bulk_array);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("immediate_create"), &VisualServer::immediate_create);
|
ClassDB::bind_method(D_METHOD("immediate_create"), &VisualServer::immediate_create);
|
||||||
ClassDB::bind_method(D_METHOD("immediate_begin", "immediate", "primitive", "texture"), &VisualServer::immediate_begin, DEFVAL(RID()));
|
ClassDB::bind_method(D_METHOD("immediate_begin", "immediate", "primitive", "texture"), &VisualServer::immediate_begin, DEFVAL(RID()));
|
||||||
|
@ -2143,7 +2146,8 @@ void VisualServer::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_2x2);
|
BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_2x2);
|
||||||
BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_3x3);
|
BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_3x3);
|
||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("frame_drawn_in_thread"));
|
ADD_SIGNAL(MethodInfo("frame_pre_draw"));
|
||||||
|
ADD_SIGNAL(MethodInfo("frame_post_draw"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector<float> &p_margins, const Color &p_modulate) {
|
void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector<float> &p_margins, const Color &p_modulate) {
|
||||||
|
|
|
@ -309,13 +309,20 @@ public:
|
||||||
MULTIMESH_COLOR_FLOAT,
|
MULTIMESH_COLOR_FLOAT,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, MultimeshColorFormat p_color_format) = 0;
|
enum MultimeshCustomDataFormat {
|
||||||
|
MULTIMESH_CUSTOM_DATA_NONE,
|
||||||
|
MULTIMESH_CUSTOM_DATA_8BIT,
|
||||||
|
MULTIMESH_CUSTOM_DATA_FLOAT,
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, MultimeshColorFormat p_color_format, MultimeshCustomDataFormat p_data_format = MULTIMESH_CUSTOM_DATA_NONE) = 0;
|
||||||
virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
|
virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
|
||||||
|
|
||||||
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
|
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
|
||||||
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0;
|
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0;
|
||||||
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0;
|
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0;
|
||||||
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0;
|
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0;
|
||||||
|
virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0;
|
||||||
|
|
||||||
virtual RID multimesh_get_mesh(RID p_multimesh) const = 0;
|
virtual RID multimesh_get_mesh(RID p_multimesh) const = 0;
|
||||||
virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0;
|
virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0;
|
||||||
|
@ -323,6 +330,9 @@ public:
|
||||||
virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
|
virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
|
||||||
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0;
|
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0;
|
||||||
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
|
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
|
||||||
|
virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
|
||||||
|
|
||||||
|
virtual void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) = 0;
|
||||||
|
|
||||||
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
|
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
|
||||||
virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;
|
virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;
|
||||||
|
@ -1023,6 +1033,7 @@ VARIANT_ENUM_CAST(VisualServer::RenderInfo);
|
||||||
VARIANT_ENUM_CAST(VisualServer::Features);
|
VARIANT_ENUM_CAST(VisualServer::Features);
|
||||||
VARIANT_ENUM_CAST(VisualServer::MultimeshTransformFormat);
|
VARIANT_ENUM_CAST(VisualServer::MultimeshTransformFormat);
|
||||||
VARIANT_ENUM_CAST(VisualServer::MultimeshColorFormat);
|
VARIANT_ENUM_CAST(VisualServer::MultimeshColorFormat);
|
||||||
|
VARIANT_ENUM_CAST(VisualServer::MultimeshCustomDataFormat);
|
||||||
VARIANT_ENUM_CAST(VisualServer::LightOmniShadowMode);
|
VARIANT_ENUM_CAST(VisualServer::LightOmniShadowMode);
|
||||||
VARIANT_ENUM_CAST(VisualServer::LightOmniShadowDetail);
|
VARIANT_ENUM_CAST(VisualServer::LightOmniShadowDetail);
|
||||||
VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowMode);
|
VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowMode);
|
||||||
|
|
Loading…
Reference in a new issue