Merge pull request #54660 from Chaosus/vs_particles_mesh_emitter
This commit is contained in:
commit
a6412e132a
17
doc/classes/VisualShaderNodeParticleMeshEmitter.xml
Normal file
17
doc/classes/VisualShaderNodeParticleMeshEmitter.xml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<class name="VisualShaderNodeParticleMeshEmitter" inherits="VisualShaderNodeParticleEmitter" version="4.0">
|
||||||
|
<brief_description>
|
||||||
|
</brief_description>
|
||||||
|
<description>
|
||||||
|
</description>
|
||||||
|
<tutorials>
|
||||||
|
</tutorials>
|
||||||
|
<members>
|
||||||
|
<member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh">
|
||||||
|
</member>
|
||||||
|
<member name="surface_index" type="int" setter="set_surface_index" getter="get_surface_index" default="0">
|
||||||
|
</member>
|
||||||
|
<member name="use_all_surfaces" type="bool" setter="set_use_all_surfaces" getter="is_use_all_surfaces" default="true">
|
||||||
|
</member>
|
||||||
|
</members>
|
||||||
|
</class>
|
|
@ -4527,6 +4527,7 @@ VisualShaderEditor::VisualShaderEditor() {
|
||||||
add_options.push_back(AddOption("MultiplyByAxisAngle", "Particles", "Transform", "VisualShaderNodeParticleMultiplyByAxisAngle", "A node for help to multiply a position input vector by rotation using specific axis. Intended to work with emitters.", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT | TYPE_FLAGS_PROCESS | TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
|
add_options.push_back(AddOption("MultiplyByAxisAngle", "Particles", "Transform", "VisualShaderNodeParticleMultiplyByAxisAngle", "A node for help to multiply a position input vector by rotation using specific axis. Intended to work with emitters.", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT | TYPE_FLAGS_PROCESS | TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
|
||||||
|
|
||||||
add_options.push_back(AddOption("BoxEmitter", "Particles", "Emitters", "VisualShaderNodeParticleBoxEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
|
add_options.push_back(AddOption("BoxEmitter", "Particles", "Emitters", "VisualShaderNodeParticleBoxEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
|
||||||
|
add_options.push_back(AddOption("MeshEmitter", "Particles", "Emitters", "VisualShaderNodeParticleMeshEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
|
||||||
add_options.push_back(AddOption("RingEmitter", "Particles", "Emitters", "VisualShaderNodeParticleRingEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
|
add_options.push_back(AddOption("RingEmitter", "Particles", "Emitters", "VisualShaderNodeParticleRingEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
|
||||||
add_options.push_back(AddOption("SphereEmitter", "Particles", "Emitters", "VisualShaderNodeParticleSphereEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
|
add_options.push_back(AddOption("SphereEmitter", "Particles", "Emitters", "VisualShaderNodeParticleSphereEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
|
||||||
|
|
||||||
|
|
|
@ -628,6 +628,7 @@ void register_scene_types() {
|
||||||
GDREGISTER_CLASS(VisualShaderNodeParticleSphereEmitter);
|
GDREGISTER_CLASS(VisualShaderNodeParticleSphereEmitter);
|
||||||
GDREGISTER_CLASS(VisualShaderNodeParticleBoxEmitter);
|
GDREGISTER_CLASS(VisualShaderNodeParticleBoxEmitter);
|
||||||
GDREGISTER_CLASS(VisualShaderNodeParticleRingEmitter);
|
GDREGISTER_CLASS(VisualShaderNodeParticleRingEmitter);
|
||||||
|
GDREGISTER_CLASS(VisualShaderNodeParticleMeshEmitter);
|
||||||
GDREGISTER_CLASS(VisualShaderNodeParticleMultiplyByAxisAngle);
|
GDREGISTER_CLASS(VisualShaderNodeParticleMultiplyByAxisAngle);
|
||||||
GDREGISTER_CLASS(VisualShaderNodeParticleConeVelocity);
|
GDREGISTER_CLASS(VisualShaderNodeParticleConeVelocity);
|
||||||
GDREGISTER_CLASS(VisualShaderNodeParticleRandomness);
|
GDREGISTER_CLASS(VisualShaderNodeParticleRandomness);
|
||||||
|
|
|
@ -36,6 +36,11 @@
|
||||||
#include "visual_shader_particle_nodes.h"
|
#include "visual_shader_particle_nodes.h"
|
||||||
#include "visual_shader_sdf_nodes.h"
|
#include "visual_shader_sdf_nodes.h"
|
||||||
|
|
||||||
|
String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name) {
|
||||||
|
static const char *typepf[VisualShader::TYPE_MAX] = { "vtx", "frg", "lgt", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog" };
|
||||||
|
return p_name + "_" + String(typepf[p_type]) + "_" + itos(p_id);
|
||||||
|
}
|
||||||
|
|
||||||
bool VisualShaderNode::is_simple_decl() const {
|
bool VisualShaderNode::is_simple_decl() const {
|
||||||
return simple_decl;
|
return simple_decl;
|
||||||
}
|
}
|
||||||
|
@ -1829,6 +1834,7 @@ void VisualShader::_update_shader() const {
|
||||||
code += " vec3 __vec3_buff2;\n";
|
code += " vec3 __vec3_buff2;\n";
|
||||||
code += " float __scalar_buff1;\n";
|
code += " float __scalar_buff1;\n";
|
||||||
code += " float __scalar_buff2;\n";
|
code += " float __scalar_buff2;\n";
|
||||||
|
code += " int __scalar_ibuff;\n";
|
||||||
code += " vec3 __ndiff = normalize(__diff);\n\n";
|
code += " vec3 __ndiff = normalize(__diff);\n\n";
|
||||||
}
|
}
|
||||||
if (has_start) {
|
if (has_start) {
|
||||||
|
|
|
@ -697,4 +697,6 @@ public:
|
||||||
VisualShaderNodeGlobalExpression();
|
VisualShaderNodeGlobalExpression();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name);
|
||||||
|
|
||||||
#endif // VISUAL_SHADER_H
|
#endif // VISUAL_SHADER_H
|
||||||
|
|
|
@ -494,11 +494,6 @@ String VisualShaderNodeTexture::get_input_port_default_hint(int p_port) const {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name) {
|
|
||||||
static const char *typepf[VisualShader::TYPE_MAX] = { "vtx", "frg", "lgt" };
|
|
||||||
return p_name + "_" + String(typepf[p_type]) + "_" + itos(p_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const {
|
Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const {
|
||||||
VisualShader::DefaultTextureParam dtp;
|
VisualShader::DefaultTextureParam dtp;
|
||||||
dtp.name = make_unique_id(p_type, p_id, "tex");
|
dtp.name = make_unique_id(p_type, p_id, "tex");
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
|
|
||||||
#include "visual_shader_particle_nodes.h"
|
#include "visual_shader_particle_nodes.h"
|
||||||
|
|
||||||
|
#include "core/core_string_names.h"
|
||||||
|
|
||||||
// VisualShaderNodeParticleEmitter
|
// VisualShaderNodeParticleEmitter
|
||||||
|
|
||||||
int VisualShaderNodeParticleEmitter::get_output_port_count() const {
|
int VisualShaderNodeParticleEmitter::get_output_port_count() const {
|
||||||
|
@ -255,6 +257,283 @@ VisualShaderNodeParticleRingEmitter::VisualShaderNodeParticleRingEmitter() {
|
||||||
set_input_port_default_value(2, 0.0);
|
set_input_port_default_value(2, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VisualShaderNodeParticleMeshEmitter
|
||||||
|
|
||||||
|
String VisualShaderNodeParticleMeshEmitter::get_caption() const {
|
||||||
|
return "MeshEmitter";
|
||||||
|
}
|
||||||
|
|
||||||
|
int VisualShaderNodeParticleMeshEmitter::get_output_port_count() const {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
VisualShaderNodeParticleBoxEmitter::PortType VisualShaderNodeParticleMeshEmitter::get_output_port_type(int p_port) const {
|
||||||
|
switch (p_port) {
|
||||||
|
case 0:
|
||||||
|
return PORT_TYPE_VECTOR; // position
|
||||||
|
case 1:
|
||||||
|
return PORT_TYPE_VECTOR; // normal
|
||||||
|
}
|
||||||
|
return PORT_TYPE_SCALAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
String VisualShaderNodeParticleMeshEmitter::get_output_port_name(int p_port) const {
|
||||||
|
switch (p_port) {
|
||||||
|
case 0:
|
||||||
|
return "position";
|
||||||
|
case 1:
|
||||||
|
return "normal";
|
||||||
|
}
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
|
||||||
|
int VisualShaderNodeParticleMeshEmitter::get_input_port_count() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VisualShaderNodeParticleBoxEmitter::PortType VisualShaderNodeParticleMeshEmitter::get_input_port_type(int p_port) const {
|
||||||
|
return PORT_TYPE_SCALAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
String VisualShaderNodeParticleMeshEmitter::get_input_port_name(int p_port) const {
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
|
||||||
|
String VisualShaderNodeParticleMeshEmitter::generate_global_per_node(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";
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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(";
|
||||||
|
code += "texelFetch(";
|
||||||
|
code += make_unique_id(p_type, p_id, "mesh_vx") + ", ";
|
||||||
|
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 += "ivec2(__scalar_ibuff, 0), 0).xyz;\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
} 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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.param = position_texture;
|
||||||
|
|
||||||
|
VisualShader::DefaultTextureParam dtp_nm;
|
||||||
|
dtp_nm.name = make_unique_id(p_type, p_id, "mesh_nm");
|
||||||
|
dtp_nm.param = normal_texture;
|
||||||
|
|
||||||
|
Vector<VisualShader::DefaultTextureParam> ret;
|
||||||
|
ret.push_back(dtp_vx);
|
||||||
|
ret.push_back(dtp_nm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualShaderNodeParticleMeshEmitter::update_texture() {
|
||||||
|
if (!mesh.is_valid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<Vector3> vertices;
|
||||||
|
Vector<Vector3> normals;
|
||||||
|
|
||||||
|
if (use_all_surfaces) {
|
||||||
|
for (int i = 0; i < max_surface_index; i++) {
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
if (normal_texture->get_width() != normals.size()) {
|
||||||
|
normal_texture->create_from_image(image);
|
||||||
|
} else {
|
||||||
|
normal_texture->update(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) {
|
||||||
|
if (mesh == p_mesh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_mesh.is_valid()) {
|
||||||
|
max_surface_index = p_mesh->get_surface_count();
|
||||||
|
} else {
|
||||||
|
max_surface_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh.is_valid()) {
|
||||||
|
Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture);
|
||||||
|
|
||||||
|
if (mesh->is_connected(CoreStringNames::get_singleton()->changed, callable)) {
|
||||||
|
mesh->disconnect(CoreStringNames::get_singleton()->changed, callable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh = p_mesh;
|
||||||
|
|
||||||
|
if (mesh.is_valid()) {
|
||||||
|
Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture);
|
||||||
|
|
||||||
|
if (!mesh->is_connected(CoreStringNames::get_singleton()->changed, callable)) {
|
||||||
|
mesh->connect(CoreStringNames::get_singleton()->changed, callable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Mesh> VisualShaderNodeParticleMeshEmitter::get_mesh() const {
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualShaderNodeParticleMeshEmitter::set_use_all_surfaces(bool p_enabled) {
|
||||||
|
if (use_all_surfaces == p_enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
use_all_surfaces = p_enabled;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VisualShaderNodeParticleMeshEmitter::is_use_all_surfaces() const {
|
||||||
|
return use_all_surfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualShaderNodeParticleMeshEmitter::set_surface_index(int p_surface_index) {
|
||||||
|
if (p_surface_index == surface_index || p_surface_index < 0 || p_surface_index >= max_surface_index) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
surface_index = p_surface_index;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
int VisualShaderNodeParticleMeshEmitter::get_surface_index() const {
|
||||||
|
return surface_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<StringName> VisualShaderNodeParticleMeshEmitter::get_editable_properties() const {
|
||||||
|
Vector<StringName> props = VisualShaderNodeParticleEmitter::get_editable_properties();
|
||||||
|
|
||||||
|
props.push_back("mesh");
|
||||||
|
props.push_back("use_all_surfaces");
|
||||||
|
if (!use_all_surfaces) {
|
||||||
|
props.push_back("surface_index");
|
||||||
|
}
|
||||||
|
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<StringName, String> VisualShaderNodeParticleMeshEmitter::get_editable_properties_names() const {
|
||||||
|
Map<StringName, String> names = VisualShaderNodeParticleEmitter::get_editable_properties_names();
|
||||||
|
|
||||||
|
names.insert("mesh", TTR("Mesh"));
|
||||||
|
names.insert("use_all_surfaces", TTR("Use All Surfaces"));
|
||||||
|
if (!use_all_surfaces) {
|
||||||
|
names.insert("surface_index", TTR("Surface Index"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualShaderNodeParticleMeshEmitter::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &VisualShaderNodeParticleMeshEmitter::set_mesh);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_mesh"), &VisualShaderNodeParticleMeshEmitter::get_mesh);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_use_all_surfaces", "enabled"), &VisualShaderNodeParticleMeshEmitter::set_use_all_surfaces);
|
||||||
|
ClassDB::bind_method(D_METHOD("is_use_all_surfaces"), &VisualShaderNodeParticleMeshEmitter::is_use_all_surfaces);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_surface_index", "surface_index"), &VisualShaderNodeParticleMeshEmitter::set_surface_index);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_surface_index"), &VisualShaderNodeParticleMeshEmitter::get_surface_index);
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_all_surfaces"), "set_use_all_surfaces", "is_use_all_surfaces");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "surface_index"), "set_surface_index", "get_surface_index");
|
||||||
|
}
|
||||||
|
|
||||||
|
VisualShaderNodeParticleMeshEmitter::VisualShaderNodeParticleMeshEmitter() {
|
||||||
|
connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture));
|
||||||
|
|
||||||
|
position_texture.instantiate();
|
||||||
|
normal_texture.instantiate();
|
||||||
|
}
|
||||||
|
|
||||||
// VisualShaderNodeParticleMultiplyByAxisAngle
|
// VisualShaderNodeParticleMultiplyByAxisAngle
|
||||||
|
|
||||||
void VisualShaderNodeParticleMultiplyByAxisAngle::_bind_methods() {
|
void VisualShaderNodeParticleMultiplyByAxisAngle::_bind_methods() {
|
||||||
|
@ -334,7 +613,6 @@ bool VisualShaderNodeParticleMultiplyByAxisAngle::is_degrees_mode() const {
|
||||||
Vector<StringName> VisualShaderNodeParticleMultiplyByAxisAngle::get_editable_properties() const {
|
Vector<StringName> VisualShaderNodeParticleMultiplyByAxisAngle::get_editable_properties() const {
|
||||||
Vector<StringName> props;
|
Vector<StringName> props;
|
||||||
props.push_back("degrees_mode");
|
props.push_back("degrees_mode");
|
||||||
props.push_back("axis_amount");
|
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
bool is_mode_2d() const;
|
bool is_mode_2d() const;
|
||||||
|
|
||||||
Vector<StringName> get_editable_properties() const override;
|
Vector<StringName> get_editable_properties() const override;
|
||||||
Map<StringName, String> get_editable_properties_names() const override;
|
virtual Map<StringName, String> get_editable_properties_names() const override;
|
||||||
bool is_show_prop_names() const override;
|
bool is_show_prop_names() const override;
|
||||||
|
|
||||||
VisualShaderNodeParticleEmitter();
|
VisualShaderNodeParticleEmitter();
|
||||||
|
@ -106,6 +106,51 @@ public:
|
||||||
VisualShaderNodeParticleRingEmitter();
|
VisualShaderNodeParticleRingEmitter();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class VisualShaderNodeParticleMeshEmitter : public VisualShaderNodeParticleEmitter {
|
||||||
|
GDCLASS(VisualShaderNodeParticleMeshEmitter, VisualShaderNodeParticleEmitter);
|
||||||
|
Ref<Mesh> mesh;
|
||||||
|
bool use_all_surfaces = true;
|
||||||
|
int surface_index = 0;
|
||||||
|
int max_surface_index = 0;
|
||||||
|
|
||||||
|
Ref<ImageTexture> position_texture;
|
||||||
|
Ref<ImageTexture> normal_texture;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual String get_caption() const override;
|
||||||
|
|
||||||
|
virtual int get_output_port_count() const override;
|
||||||
|
virtual PortType get_output_port_type(int p_port) const override;
|
||||||
|
virtual String get_output_port_name(int p_port) const override;
|
||||||
|
|
||||||
|
virtual int get_input_port_count() const override;
|
||||||
|
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_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;
|
||||||
|
|
||||||
|
void set_use_all_surfaces(bool p_enabled);
|
||||||
|
bool is_use_all_surfaces() const;
|
||||||
|
|
||||||
|
void set_surface_index(int p_surface_index);
|
||||||
|
int get_surface_index() const;
|
||||||
|
|
||||||
|
Vector<StringName> get_editable_properties() const override;
|
||||||
|
Map<StringName, String> get_editable_properties_names() const override;
|
||||||
|
Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override;
|
||||||
|
|
||||||
|
VisualShaderNodeParticleMeshEmitter();
|
||||||
|
};
|
||||||
|
|
||||||
class VisualShaderNodeParticleMultiplyByAxisAngle : public VisualShaderNode {
|
class VisualShaderNodeParticleMultiplyByAxisAngle : public VisualShaderNode {
|
||||||
GDCLASS(VisualShaderNodeParticleMultiplyByAxisAngle, VisualShaderNode);
|
GDCLASS(VisualShaderNodeParticleMultiplyByAxisAngle, VisualShaderNode);
|
||||||
bool degrees_mode = true;
|
bool degrees_mode = true;
|
||||||
|
|
Loading…
Reference in a new issue