瀏覽代碼

Merge pull request #54599 from Chaosus/vs_particles_2d_emitters

Rémi Verschelde 3 年之前
父節點
當前提交
56cfebbe98

+ 6 - 0
doc/classes/VisualShaderNodeParticleEmitter.xml

@@ -1,9 +1,15 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="VisualShaderNodeParticleEmitter" inherits="VisualShaderNode" version="4.0">
 	<brief_description>
+		A base class for particle emitters.
 	</brief_description>
 	<description>
 	</description>
 	<tutorials>
 	</tutorials>
+	<members>
+		<member name="mode_2d" type="bool" setter="set_mode_2d" getter="is_mode_2d" default="false">
+			If [code]true[/code], the result of this emitter is projected to 2D space. By default it is [code]false[/code] and meant for use in 3D space.
+		</member>
+	</members>
 </class>

+ 7 - 3
editor/plugins/visual_shader_editor_plugin.cpp

@@ -4977,7 +4977,7 @@ public:
 		}
 	}
 
-	void setup(Ref<Resource> p_parent_resource, Vector<EditorProperty *> p_properties, const Vector<StringName> &p_names, Ref<VisualShaderNode> p_node) {
+	void setup(Ref<Resource> p_parent_resource, Vector<EditorProperty *> p_properties, const Vector<StringName> &p_names, const Map<StringName, String> &p_overrided_names, Ref<VisualShaderNode> p_node) {
 		parent_resource = p_parent_resource;
 		updating = false;
 		node = p_node;
@@ -4993,7 +4993,11 @@ public:
 
 			Label *prop_name = memnew(Label);
 			String prop_name_str = p_names[i];
-			prop_name_str = prop_name_str.capitalize() + ":";
+			if (p_overrided_names.has(p_names[i])) {
+				prop_name_str = p_overrided_names[p_names[i]] + ":";
+			} else {
+				prop_name_str = prop_name_str.capitalize() + ":";
+			}
 			prop_name->set_text(prop_name_str);
 			prop_name->set_visible(false);
 			hbox->add_child(prop_name);
@@ -5085,7 +5089,7 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_par
 		properties.push_back(pinfo[i].name);
 	}
 	VisualShaderNodePluginDefaultEditor *editor = memnew(VisualShaderNodePluginDefaultEditor);
-	editor->setup(p_parent_resource, editors, properties, p_node);
+	editor->setup(p_parent_resource, editors, properties, p_node->get_editable_properties_names(), p_node);
 	return editor;
 }
 

+ 8 - 0
scene/resources/visual_shader.cpp

@@ -199,6 +199,10 @@ Vector<StringName> VisualShaderNode::get_editable_properties() const {
 	return Vector<StringName>();
 }
 
+Map<StringName, String> VisualShaderNode::get_editable_properties_names() const {
+	return Map<StringName, String>();
+}
+
 Array VisualShaderNode::get_default_input_values() const {
 	Array ret;
 	for (const KeyValue<int, Variant> &E : default_input_values) {
@@ -1922,6 +1926,10 @@ void VisualShader::_update_shader() const {
 		global_compute_code += "	return mat4(vec4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0), vec4(oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0), vec4(oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0), vec4(0, 0, 0, 1));\n";
 		global_compute_code += "}\n\n";
 
+		global_compute_code += "vec2 __get_random_unit_vec2(inout uint seed) {\n";
+		global_compute_code += "	return normalize(vec2(__rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed)));\n";
+		global_compute_code += "}\n\n";
+
 		global_compute_code += "vec3 __get_random_unit_vec3(inout uint seed) {\n";
 		global_compute_code += "	return normalize(vec3(__rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed)));\n";
 		global_compute_code += "}\n\n";

+ 1 - 0
scene/resources/visual_shader.h

@@ -272,6 +272,7 @@ public:
 	void set_disabled(bool p_disabled = true);
 
 	virtual Vector<StringName> get_editable_properties() const;
+	virtual Map<StringName, String> get_editable_properties_names() const;
 
 	virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const;
 	virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;

+ 75 - 6
scene/resources/visual_shader_particle_nodes.cpp

@@ -51,6 +51,38 @@ bool VisualShaderNodeParticleEmitter::has_output_port_preview(int p_port) const
 	return false;
 }
 
+void VisualShaderNodeParticleEmitter::set_mode_2d(bool p_enabled) {
+	mode_2d = p_enabled;
+	emit_changed();
+}
+
+bool VisualShaderNodeParticleEmitter::is_mode_2d() const {
+	return mode_2d;
+}
+
+Vector<StringName> VisualShaderNodeParticleEmitter::get_editable_properties() const {
+	Vector<StringName> props;
+	props.push_back("mode_2d");
+	return props;
+}
+
+Map<StringName, String> VisualShaderNodeParticleEmitter::get_editable_properties_names() const {
+	Map<StringName, String> names;
+	names.insert("mode_2d", TTR("2D Mode"));
+	return names;
+}
+
+bool VisualShaderNodeParticleEmitter::is_show_prop_names() const {
+	return true;
+}
+
+void VisualShaderNodeParticleEmitter::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("set_mode_2d", "enabled"), &VisualShaderNodeParticleEmitter::set_mode_2d);
+	ClassDB::bind_method(D_METHOD("is_mode_2d"), &VisualShaderNodeParticleEmitter::is_mode_2d);
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_2d"), "set_mode_2d", "is_mode_2d");
+}
+
 VisualShaderNodeParticleEmitter::VisualShaderNodeParticleEmitter() {
 }
 
@@ -79,15 +111,27 @@ String VisualShaderNodeParticleSphereEmitter::get_input_port_name(int p_port) co
 
 String VisualShaderNodeParticleSphereEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
 	String code;
+
+	code += "vec2 __get_random_point_in_circle(inout uint seed, float radius, float inner_radius) {\n";
+	code += "	return __get_random_unit_vec2(seed) * __randf_range(seed, inner_radius, radius);\n";
+	code += "}\n\n";
+
 	code += "vec3 __get_random_point_in_sphere(inout uint seed, float radius, float inner_radius) {\n";
 	code += "	return __get_random_unit_vec3(seed) * __randf_range(seed, inner_radius, radius);\n";
 	code += "}\n\n";
+
 	return code;
 }
 
 String VisualShaderNodeParticleSphereEmitter::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 += "	" + p_output_vars[0] + " = __get_random_point_in_sphere(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ");\n";
+
+	if (mode_2d) {
+		code += "	" + p_output_vars[0] + " = vec3(__get_random_point_in_circle(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + "), 0.0);\n";
+	} else {
+		code += "	" + p_output_vars[0] + " = __get_random_point_in_sphere(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ");\n";
+	}
+
 	return code;
 }
 
@@ -122,16 +166,27 @@ String VisualShaderNodeParticleBoxEmitter::get_input_port_name(int p_port) const
 
 String VisualShaderNodeParticleBoxEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
 	String code;
-	code += "vec3 __get_random_point_in_box(inout uint seed, vec3 extents) {\n";
+
+	code += "vec2 __get_random_point_in_box2d(inout uint seed, vec2 extents) {\n";
+	code += "	vec2 half_extents = extents / 2.0;\n";
+	code += "	return vec2(__randf_range(seed, -half_extents.x, half_extents.x), __randf_range(seed, -half_extents.y, half_extents.y));\n";
+	code += "}\n\n";
+
+	code += "vec3 __get_random_point_in_box3d(inout uint seed, vec3 extents) {\n";
 	code += "	vec3 half_extents = extents / 2.0;\n";
 	code += "	return vec3(__randf_range(seed, -half_extents.x, half_extents.x), __randf_range(seed, -half_extents.y, half_extents.y), __randf_range(seed, -half_extents.z, half_extents.z));\n";
 	code += "}\n\n";
+
 	return code;
 }
 
 String VisualShaderNodeParticleBoxEmitter::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 += "	" + p_output_vars[0] + " = __get_random_point_in_box(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ");\n";
+	if (mode_2d) {
+		code += "	" + p_output_vars[0] + " = vec3(__get_random_point_in_box2d(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ".xy), 0.0);\n";
+	} else {
+		code += "	" + p_output_vars[0] + " = __get_random_point_in_box3d(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ");\n";
+	}
 	return code;
 }
 
@@ -166,17 +221,31 @@ String VisualShaderNodeParticleRingEmitter::get_input_port_name(int p_port) cons
 
 String VisualShaderNodeParticleRingEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
 	String code;
-	code += "vec3 __get_random_point_on_ring(inout uint seed, float radius, float inner_radius, float height) {\n";
-	code += "	float angle = __rand_from_seed(seed) * PI * 2.0;\n";
+
+	code += "vec2 __get_random_point_on_ring2d(inout uint seed, float radius, float inner_radius) {\n";
+	code += "	float angle = __rand_from_seed(seed) * TAU;\n";
+	code += "	vec2 ring = vec2(sin(angle), cos(angle)) * __randf_range(seed, inner_radius, radius);\n";
+	code += "	return vec2(ring.x, ring.y);\n";
+	code += "}\n\n";
+
+	code += "vec3 __get_random_point_on_ring3d(inout uint seed, float radius, float inner_radius, float height) {\n";
+	code += "	float angle = __rand_from_seed(seed) * TAU;\n";
 	code += "	vec2 ring = vec2(sin(angle), cos(angle)) * __randf_range(seed, inner_radius, radius);\n";
 	code += "	return vec3(ring.x, __randf_range(seed, min(0.0, height), max(0.0, height)), ring.y);\n";
 	code += "}\n\n";
+
 	return code;
 }
 
 String VisualShaderNodeParticleRingEmitter::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 = "	" + p_output_vars[0] + " = __get_random_point_on_ring(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ", " + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ");\n";
+
+	if (mode_2d) {
+		code = "	" + p_output_vars[0] + " = vec3(__get_random_point_on_ring2d(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + "), 0.0);\n";
+	} else {
+		code = "	" + p_output_vars[0] + " = __get_random_point_on_ring3d(__seed, " + (p_input_vars[0].is_empty() ? (String)get_input_port_default_value(0) : p_input_vars[0]) + ", " + (p_input_vars[1].is_empty() ? (String)get_input_port_default_value(1) : p_input_vars[1]) + ", " + (p_input_vars[2].is_empty() ? (String)get_input_port_default_value(2) : p_input_vars[2]) + ");\n";
+	}
+
 	return code;
 }
 

+ 11 - 0
scene/resources/visual_shader_particle_nodes.h

@@ -38,12 +38,23 @@
 class VisualShaderNodeParticleEmitter : public VisualShaderNode {
 	GDCLASS(VisualShaderNodeParticleEmitter, VisualShaderNode);
 
+protected:
+	bool mode_2d = false;
+	static void _bind_methods();
+
 public:
 	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 bool has_output_port_preview(int p_port) const override;
 
+	void set_mode_2d(bool p_enabled);
+	bool is_mode_2d() const;
+
+	Vector<StringName> get_editable_properties() const override;
+	Map<StringName, String> get_editable_properties_names() const override;
+	bool is_show_prop_names() const override;
+
 	VisualShaderNodeParticleEmitter();
 };