summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/navigation_region_2d.cpp2
-rw-r--r--scene/gui/color_picker.cpp8
-rw-r--r--scene/gui/range.cpp14
-rw-r--r--scene/gui/range.h1
-rw-r--r--scene/resources/skeleton_modification_2d_ccdik.cpp4
-rw-r--r--scene/resources/visual_shader.cpp1
-rw-r--r--scene/resources/visual_shader_particle_nodes.cpp289
-rw-r--r--scene/resources/visual_shader_particle_nodes.h14
8 files changed, 252 insertions, 81 deletions
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index bdb6cda5af..204ed72878 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -464,7 +464,7 @@ void NavigationRegion2D::_notification(int p_what) {
draw_line(a, b, doors_color);
// Draw a circle to illustrate the margins.
- real_t angle = b.angle_to_point(a);
+ real_t angle = a.angle_to_point(b);
draw_arc(a, radius, angle + Math_PI / 2.0, angle - Math_PI / 2.0 + Math_TAU, 10, doors_color);
draw_arc(b, radius, angle - Math_PI / 2.0, angle + Math_PI / 2.0, 10, doors_color);
}
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 049cdb5bef..5a378554c9 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -833,7 +833,7 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
real_t dist = center.distance_to(bev->get_position());
if (dist <= center.x) {
- real_t rad = bev->get_position().angle_to_point(center);
+ real_t rad = center.angle_to_point(bev->get_position());
h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU;
s = CLAMP(dist / center.x, 0, 1);
} else {
@@ -850,7 +850,7 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
real_t dist = center.distance_to(bev->get_position());
if (dist >= center.x * 0.84 && dist <= center.x) {
- real_t rad = bev->get_position().angle_to_point(center);
+ real_t rad = center.angle_to_point(bev->get_position());
h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU;
spinning = true;
} else {
@@ -895,12 +895,12 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
Vector2 center = c->get_size() / 2.0;
if (picker_type == SHAPE_VHS_CIRCLE) {
real_t dist = center.distance_to(mev->get_position());
- real_t rad = mev->get_position().angle_to_point(center);
+ real_t rad = center.angle_to_point(mev->get_position());
h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU;
s = CLAMP(dist / center.x, 0, 1);
} else {
if (spinning) {
- real_t rad = mev->get_position().angle_to_point(center);
+ real_t rad = center.angle_to_point(mev->get_position());
h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU;
} else {
real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0;
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index 92d4261d8d..c4f05a7975 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -61,6 +61,11 @@ void Range::_changed_notify(const char *p_what) {
update();
}
+void Range::_validate_values() {
+ shared->max = MAX(shared->max, shared->min);
+ shared->page = CLAMP(shared->page, 0, shared->max - shared->min);
+}
+
void Range::Shared::emit_changed(const char *p_what) {
for (Set<Range *>::Element *E = owners.front(); E; E = E->next()) {
Range *r = E->get();
@@ -100,6 +105,7 @@ void Range::set_value(double p_val) {
void Range::set_min(double p_min) {
shared->min = p_min;
set_value(shared->val);
+ _validate_values();
shared->emit_changed("min");
@@ -109,6 +115,7 @@ void Range::set_min(double p_min) {
void Range::set_max(double p_max) {
shared->max = p_max;
set_value(shared->val);
+ _validate_values();
shared->emit_changed("max");
}
@@ -121,6 +128,7 @@ void Range::set_step(double p_step) {
void Range::set_page(double p_page) {
shared->page = p_page;
set_value(shared->val);
+ _validate_values();
shared->emit_changed("page");
}
@@ -270,6 +278,12 @@ void Range::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rounded"), "set_use_rounded_values", "is_using_rounded_values");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_greater"), "set_allow_greater", "is_greater_allowed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_lesser"), "set_allow_lesser", "is_lesser_allowed");
+
+ ADD_LINKED_PROPERTY("min_value", "value");
+ ADD_LINKED_PROPERTY("min_value", "max_value");
+ ADD_LINKED_PROPERTY("min_value", "page");
+ ADD_LINKED_PROPERTY("max_value", "value");
+ ADD_LINKED_PROPERTY("max_value", "page");
}
void Range::set_use_rounded_values(bool p_enable) {
diff --git a/scene/gui/range.h b/scene/gui/range.h
index 7a129e88d6..0dc702b19c 100644
--- a/scene/gui/range.h
+++ b/scene/gui/range.h
@@ -59,6 +59,7 @@ class Range : public Control {
void _value_changed_notify();
void _changed_notify(const char *p_what = "");
+ void _validate_values();
protected:
virtual void _value_changed(double) {}
diff --git a/scene/resources/skeleton_modification_2d_ccdik.cpp b/scene/resources/skeleton_modification_2d_ccdik.cpp
index 6eab8d4afe..bea42109cb 100644
--- a/scene/resources/skeleton_modification_2d_ccdik.cpp
+++ b/scene/resources/skeleton_modification_2d_ccdik.cpp
@@ -205,8 +205,8 @@ void SkeletonModification2DCCDIK::_execute_ccdik_joint(int p_joint_idx, Node2D *
} else {
// How to rotate from the tip: get the difference of rotation needed from the tip to the target, from the perspective of the joint.
// Because we are only using the offset, we do not need to account for the bone angle of the Bone2D node.
- float joint_to_tip = operation_transform.get_origin().angle_to_point(p_tip->get_global_position());
- float joint_to_target = operation_transform.get_origin().angle_to_point(p_target->get_global_position());
+ float joint_to_tip = p_tip->get_global_position().angle_to_point(operation_transform.get_origin());
+ float joint_to_target = p_target->get_global_position().angle_to_point(operation_transform.get_origin());
operation_transform.set_rotation(
operation_transform.get_rotation() + (joint_to_target - joint_to_tip));
}
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 0bdc81330e..87ff225de9 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -1835,6 +1835,7 @@ void VisualShader::_update_shader() const {
code += " float __scalar_buff1;\n";
code += " float __scalar_buff2;\n";
code += " int __scalar_ibuff;\n";
+ code += " vec4 __vec4_buff;\n";
code += " vec3 __ndiff = normalize(__diff);\n\n";
}
if (has_start) {
diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp
index 7dd4eed15b..1a829968e3 100644
--- a/scene/resources/visual_shader_particle_nodes.cpp
+++ b/scene/resources/visual_shader_particle_nodes.cpp
@@ -264,7 +264,7 @@ String VisualShaderNodeParticleMeshEmitter::get_caption() const {
}
int VisualShaderNodeParticleMeshEmitter::get_output_port_count() const {
- return 2;
+ return 6;
}
VisualShaderNodeParticleBoxEmitter::PortType VisualShaderNodeParticleMeshEmitter::get_output_port_type(int p_port) const {
@@ -273,6 +273,14 @@ VisualShaderNodeParticleBoxEmitter::PortType VisualShaderNodeParticleMeshEmitter
return PORT_TYPE_VECTOR; // position
case 1:
return PORT_TYPE_VECTOR; // normal
+ case 2:
+ return PORT_TYPE_VECTOR; // color
+ case 3:
+ return PORT_TYPE_SCALAR; // alpha
+ case 4:
+ return PORT_TYPE_VECTOR; // uv
+ case 5:
+ return PORT_TYPE_VECTOR; // uv2
}
return PORT_TYPE_SCALAR;
}
@@ -283,6 +291,14 @@ String VisualShaderNodeParticleMeshEmitter::get_output_port_name(int p_port) con
return "position";
case 1:
return "normal";
+ case 2:
+ return "color";
+ case 3:
+ return "alpha";
+ case 4:
+ return "uv";
+ case 5:
+ return "uv2";
}
return String();
}
@@ -299,135 +315,263 @@ String VisualShaderNodeParticleMeshEmitter::get_input_port_name(int p_port) cons
return String();
}
-String VisualShaderNodeParticleMeshEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+String VisualShaderNodeParticleMeshEmitter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code;
if (mesh.is_valid()) {
- code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n";
- code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n";
+ if (is_output_port_connected(0)) { // position
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n";
+ }
+
+ if (is_output_port_connected(1)) { // normal
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n";
+ }
+
+ if (is_output_port_connected(2) || is_output_port_connected(3)) { // color & alpha
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_col") + ";\n";
+ }
+
+ if (is_output_port_connected(4)) { // uv
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv") + ";\n";
+ }
+
+ if (is_output_port_connected(5)) { // uv2
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv2") + ";\n";
+ }
}
return code;
}
-String VisualShaderNodeParticleMeshEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+String VisualShaderNodeParticleMeshEmitter::_generate_code(VisualShader::Type p_type, int p_id, const String *p_output_vars, int p_index, const String &p_texture_name, bool p_ignore_mode2d) const {
String code;
-
- code += " __scalar_ibuff = int(__rand_from_seed(__seed) * 65535.0) % " + itos(position_texture->get_width()) + ";\n";
-
- if (position_texture->get_width() == 0) {
- code += " " + p_output_vars[0] + " = vec3(0.0);\n";
- } else {
- if (mode_2d) {
- code += " " + p_output_vars[0] + " = vec3(";
+ if (is_output_port_connected(p_index)) {
+ if (mode_2d && !p_ignore_mode2d) {
+ code += " " + p_output_vars[p_index] + " = vec3(";
code += "texelFetch(";
- code += make_unique_id(p_type, p_id, "mesh_vx") + ", ";
+ code += make_unique_id(p_type, p_id, p_texture_name) + ", ";
code += "ivec2(__scalar_ibuff, 0), 0).xy, 0.0);\n";
} else {
- code += " " + p_output_vars[0] + " = texelFetch(";
- code += make_unique_id(p_type, p_id, "mesh_vx") + ", ";
+ code += " " + p_output_vars[p_index] + " = texelFetch(";
+ code += make_unique_id(p_type, p_id, p_texture_name) + ", ";
code += "ivec2(__scalar_ibuff, 0), 0).xyz;\n";
}
}
+ return code;
+}
- if (normal_texture->get_width() == 0) {
- code += " " + p_output_vars[1] + " = vec3(0.0);\n";
- } else {
- if (mode_2d) {
- code += " " + p_output_vars[1] + " = vec3(";
- code += "texelFetch(";
- code += make_unique_id(p_type, p_id, "mesh_nm") + ", ";
- code += "ivec2(__scalar_ibuff, 0), 0).xy, 0.0);\n";
+String VisualShaderNodeParticleMeshEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ code += " __scalar_ibuff = int(__rand_from_seed(__seed) * 65535.0) % " + itos(position_texture->get_width()) + ";\n";
+
+ code += _generate_code(p_type, p_id, p_output_vars, 0, "mesh_vx");
+ code += _generate_code(p_type, p_id, p_output_vars, 1, "mesh_nm");
+
+ if (is_output_port_connected(2) || is_output_port_connected(3)) {
+ code += " __vec4_buff = texelFetch(";
+ code += make_unique_id(p_type, p_id, "mesh_col") + ", ";
+ code += "ivec2(__scalar_ibuff, 0), 0);\n";
+ if (is_output_port_connected(2)) {
+ code += " " + p_output_vars[2] + " = __vec4_buff.rgb;\n";
} else {
- code += " " + p_output_vars[1] + " = texelFetch(";
- code += make_unique_id(p_type, p_id, "mesh_nm") + ", ";
- code += "ivec2(__scalar_ibuff, 0), 0).xyz;\n";
+ code += " " + p_output_vars[2] + " = vec3(0.0);\n";
+ }
+ if (is_output_port_connected(3)) {
+ code += " " + p_output_vars[3] + " = __vec4_buff.a;\n";
+ } else {
+ code += " " + p_output_vars[3] + " = 0.0;\n";
}
}
+ code += _generate_code(p_type, p_id, p_output_vars, 4, "mesh_uv", true);
+ code += _generate_code(p_type, p_id, p_output_vars, 5, "mesh_uv2", true);
+
return code;
}
Vector<VisualShader::DefaultTextureParam> VisualShaderNodeParticleMeshEmitter::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const {
- VisualShader::DefaultTextureParam dtp_vx;
- dtp_vx.name = make_unique_id(p_type, p_id, "mesh_vx");
- dtp_vx.params.push_back(position_texture);
+ Vector<VisualShader::DefaultTextureParam> ret;
- VisualShader::DefaultTextureParam dtp_nm;
- dtp_nm.name = make_unique_id(p_type, p_id, "mesh_nm");
- dtp_nm.params.push_back(normal_texture);
+ if (is_output_port_connected(0)) {
+ VisualShader::DefaultTextureParam dtp;
+ dtp.name = make_unique_id(p_type, p_id, "mesh_vx");
+ dtp.params.push_back(position_texture);
+ ret.push_back(dtp);
+ }
+
+ if (is_output_port_connected(1)) {
+ VisualShader::DefaultTextureParam dtp;
+ dtp.name = make_unique_id(p_type, p_id, "mesh_nm");
+ dtp.params.push_back(normal_texture);
+ ret.push_back(dtp);
+ }
+
+ if (is_output_port_connected(2) || is_output_port_connected(3)) {
+ VisualShader::DefaultTextureParam dtp;
+ dtp.name = make_unique_id(p_type, p_id, "mesh_col");
+ dtp.params.push_back(color_texture);
+ ret.push_back(dtp);
+ }
+
+ if (is_output_port_connected(4)) {
+ VisualShader::DefaultTextureParam dtp;
+ dtp.name = make_unique_id(p_type, p_id, "mesh_uv");
+ dtp.params.push_back(uv_texture);
+ ret.push_back(dtp);
+ }
+
+ if (is_output_port_connected(5)) {
+ VisualShader::DefaultTextureParam dtp;
+ dtp.name = make_unique_id(p_type, p_id, "mesh_uv2");
+ dtp.params.push_back(uv2_texture);
+ ret.push_back(dtp);
+ }
- Vector<VisualShader::DefaultTextureParam> ret;
- ret.push_back(dtp_vx);
- ret.push_back(dtp_nm);
return ret;
}
-void VisualShaderNodeParticleMeshEmitter::update_texture() {
+void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Vector2> &p_array, Ref<ImageTexture> &r_texture) {
+ Ref<Image> image;
+ image.instantiate();
+
+ if (p_array.size() == 0) {
+ image->create(1, 1, false, Image::Format::FORMAT_RGBF);
+ } else {
+ image->create(p_array.size(), 1, false, Image::Format::FORMAT_RGBF);
+ }
+
+ for (int i = 0; i < p_array.size(); i++) {
+ Vector2 v = p_array[i];
+ image->set_pixel(i, 0, Color(v.x, v.y, 0));
+ }
+ if (r_texture->get_width() != p_array.size() || p_array.size() == 0) {
+ r_texture->create_from_image(image);
+ } else {
+ r_texture->update(image);
+ }
+}
+
+void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Vector3> &p_array, Ref<ImageTexture> &r_texture) {
+ Ref<Image> image;
+ image.instantiate();
+
+ if (p_array.size() == 0) {
+ image->create(1, 1, false, Image::Format::FORMAT_RGBF);
+ } else {
+ image->create(p_array.size(), 1, false, Image::Format::FORMAT_RGBF);
+ }
+
+ for (int i = 0; i < p_array.size(); i++) {
+ Vector3 v = p_array[i];
+ image->set_pixel(i, 0, Color(v.x, v.y, v.z));
+ }
+ if (r_texture->get_width() != p_array.size() || p_array.size() == 0) {
+ r_texture->create_from_image(image);
+ } else {
+ r_texture->update(image);
+ }
+}
+
+void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Color> &p_array, Ref<ImageTexture> &r_texture) {
+ Ref<Image> image;
+ image.instantiate();
+
+ if (p_array.size() == 0) {
+ image->create(1, 1, false, Image::Format::FORMAT_RGBA8);
+ } else {
+ image->create(p_array.size(), 1, false, Image::Format::FORMAT_RGBA8);
+ }
+
+ for (int i = 0; i < p_array.size(); i++) {
+ image->set_pixel(i, 0, p_array[i]);
+ }
+ if (r_texture->get_width() != p_array.size() || p_array.size() == 0) {
+ r_texture->create_from_image(image);
+ } else {
+ r_texture->update(image);
+ }
+}
+
+void VisualShaderNodeParticleMeshEmitter::_update_textures() {
if (!mesh.is_valid()) {
return;
}
Vector<Vector3> vertices;
Vector<Vector3> normals;
+ Vector<Color> colors;
+ Vector<Vector2> uvs;
+ Vector<Vector2> uvs2;
if (use_all_surfaces) {
for (int i = 0; i < max_surface_index; i++) {
+ // position
Array vertex_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_VERTEX];
for (int j = 0; j < vertex_array.size(); j++) {
vertices.push_back((Vector3)vertex_array[j]);
}
+ // normal
Array normal_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_NORMAL];
- for (int j = 0; j < vertex_array.size(); j++) {
- normals.push_back((Vector3)vertex_array[j]);
+ for (int j = 0; j < normal_array.size(); j++) {
+ normals.push_back((Vector3)normal_array[j]);
+ }
+
+ // color
+ Array color_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_COLOR];
+ for (int j = 0; j < color_array.size(); j++) {
+ colors.push_back((Color)color_array[j]);
+ }
+
+ // uv
+ Array uv_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_TEX_UV];
+ for (int j = 0; j < uv_array.size(); j++) {
+ uvs.push_back((Vector2)uv_array[j]);
+ }
+
+ // uv2
+ Array uv2_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_TEX_UV2];
+ for (int j = 0; j < uv2_array.size(); j++) {
+ uvs2.push_back((Vector2)uv2_array[j]);
}
}
} else {
+ // position
Array vertex_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_VERTEX];
for (int i = 0; i < vertex_array.size(); i++) {
vertices.push_back((Vector3)vertex_array[i]);
}
+ // normal
Array normal_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_NORMAL];
for (int i = 0; i < normal_array.size(); i++) {
normals.push_back((Vector3)normal_array[i]);
}
- }
- // vertices
- {
- Ref<Image> image;
- image.instantiate();
- image->create(vertices.size(), 1, false, Image::Format::FORMAT_RGBF);
-
- for (int i = 0; i < vertices.size(); i++) {
- Vector3 v = vertices[i];
- image->set_pixel(i, 0, Color(v.x, v.y, v.z));
- }
- if (position_texture->get_width() != vertices.size()) {
- position_texture->create_from_image(image);
- } else {
- position_texture->update(image);
+ // color
+ Array color_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_COLOR];
+ for (int i = 0; i < color_array.size(); i++) {
+ colors.push_back((Color)color_array[i]);
}
- }
-
- // normals
- {
- Ref<Image> image;
- image.instantiate();
- image->create(normals.size(), 1, false, Image::Format::FORMAT_RGBF);
- for (int i = 0; i < normals.size(); i++) {
- Vector3 v = normals[i];
- image->set_pixel(i, 0, Color(v.x, v.y, v.z));
+ // uv
+ Array uv_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV];
+ for (int j = 0; j < uv_array.size(); j++) {
+ uvs.push_back((Vector2)uv_array[j]);
}
- if (normal_texture->get_width() != normals.size()) {
- normal_texture->create_from_image(image);
- } else {
- normal_texture->update(image);
+
+ // uv2
+ Array uv2_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV2];
+ for (int j = 0; j < uv2_array.size(); j++) {
+ uvs2.push_back((Vector2)uv2_array[j]);
}
}
+
+ _update_texture(vertices, position_texture);
+ _update_texture(normals, normal_texture);
+ _update_texture(colors, color_texture);
+ _update_texture(uvs, uv_texture);
+ _update_texture(uvs2, uv2_texture);
}
void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) {
@@ -442,7 +586,7 @@ void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) {
}
if (mesh.is_valid()) {
- Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture);
+ Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures);
if (mesh->is_connected(CoreStringNames::get_singleton()->changed, callable)) {
mesh->disconnect(CoreStringNames::get_singleton()->changed, callable);
@@ -452,7 +596,7 @@ void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) {
mesh = p_mesh;
if (mesh.is_valid()) {
- Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture);
+ Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures);
if (!mesh->is_connected(CoreStringNames::get_singleton()->changed, callable)) {
mesh->connect(CoreStringNames::get_singleton()->changed, callable);
@@ -528,10 +672,13 @@ void VisualShaderNodeParticleMeshEmitter::_bind_methods() {
}
VisualShaderNodeParticleMeshEmitter::VisualShaderNodeParticleMeshEmitter() {
- connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture));
+ connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures));
position_texture.instantiate();
normal_texture.instantiate();
+ color_texture.instantiate();
+ uv_texture.instantiate();
+ uv2_texture.instantiate();
}
// VisualShaderNodeParticleMultiplyByAxisAngle
diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h
index 0d0f21e4bf..79459432f1 100644
--- a/scene/resources/visual_shader_particle_nodes.h
+++ b/scene/resources/visual_shader_particle_nodes.h
@@ -115,6 +115,16 @@ class VisualShaderNodeParticleMeshEmitter : public VisualShaderNodeParticleEmitt
Ref<ImageTexture> position_texture;
Ref<ImageTexture> normal_texture;
+ Ref<ImageTexture> color_texture;
+ Ref<ImageTexture> uv_texture;
+ Ref<ImageTexture> uv2_texture;
+
+ String _generate_code(VisualShader::Type p_type, int p_id, const String *p_output_vars, int p_index, const String &p_texture_name, bool p_ignore_mode2d = false) const;
+
+ void _update_texture(const Vector<Vector2> &p_array, Ref<ImageTexture> &r_texture);
+ void _update_texture(const Vector<Vector3> &p_array, Ref<ImageTexture> &r_texture);
+ void _update_texture(const Vector<Color> &p_array, Ref<ImageTexture> &r_texture);
+ void _update_textures();
protected:
static void _bind_methods();
@@ -130,11 +140,9 @@ public:
virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
- virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
+ virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
- void update_texture();
-
void set_mesh(Ref<Mesh> p_mesh);
Ref<Mesh> get_mesh() const;