Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement drop-down list properties to the custom visual shader nodes #81688

Merged
merged 1 commit into from
Sep 29, 2023

Conversation

Chaosus
Copy link
Member

@Chaosus Chaosus commented Sep 15, 2023

This PR adds user a possibility to define drop-down lists of options to their custom nodes in visual shaders.
Closes godotengine/godot-proposals#5075

To define those properties, the several new virtual methods were added to VisualShaderNodeCustom:

  • int _get_property_count() - override this to define the number of dropdown lists.
  • int_get_property_default_index(int option_index) - override this to define the default index of the specified property.
  • String _get_property_name(int option_index) - override this to define the property name, or leave it empty, so the text label will not been generated
  • PackedStringArray _get_property_options(int option_index) - the options which are available for each property

Also added one non-virtual method:
int get_option_index(int option_index) - you may need to call this function to define a specific behavior for each option in the _get_code/_get_global_code.

image

Demo project: Test.zip
Please comment if something I need to change or improve.

@paddy-exe
Copy link
Contributor

paddy-exe commented Sep 15, 2023

First off: Thanks for your work on this!
I tested the changes and it works so far pretty good.

I have some improvement requests:
It seems like the int get_option_index(int option_index) doesn't seem to work inside the init method.

Here is a showcase of how it looks when I set Circle as the option (index=1)
image

My code in case I made a mistake:
@tool
extends VisualShaderNodeCustom
class_name VisualShaderNodeShapes

func _init():
	var op = get_option_index(0)
	
	match op:
		0:
			set_input_port_default_value(1, Vector2(0.5, 0.5))
			set_input_port_default_value(2, Vector2(0.25, 0.25))
		1:
			set_input_port_default_value(1, Vector2(0.5, 0.5))
			set_input_port_default_value(2, 0.25)
		2:
			set_input_port_default_value(1, Vector2(0.5, 0.25))
			set_input_port_default_value(2, Vector2(0.25, 0.5))

func _get_name():
	return "Shapes"

func _get_category():
	return "VisualShaderExtras"

func _get_description():
	return "Signed Distance Shapes"

func _get_return_icon_type():
	return VisualShaderNode.PORT_TYPE_SCALAR

func _get_dropdown_list_property_name(index):
	return ""

func _get_dropdown_list_property_count():
	return 1

func _get_dropdown_list_property_options(index):
	return ["Box", "Circle", "Triangle"]

func _get_input_port_count():
	return 3

func _get_input_port_name(port):
	var op = get_option_index(0)
	
	match op:
		0:
			match port:
				0:
					return "UV"
				1:
					return "Position"
				2:
					return "Proportions"
		1:
			match port:
				0:
					return "UV"
				1:
					return "Position"
				2:
					return "Radius"
		2:
			match port:
				0:
					return "UV"
				1:
					return "Position"
				2:
					return "Proportions"

func _get_input_port_type(port):
	var op = get_option_index(0)
	
	match op:
		0:
			match port:
				0:
					return VisualShaderNode.PORT_TYPE_VECTOR_2D
				1:
					return VisualShaderNode.PORT_TYPE_VECTOR_2D
				2:
					return VisualShaderNode.PORT_TYPE_VECTOR_2D
		1:
			match port:
				0:
					return VisualShaderNode.PORT_TYPE_VECTOR_2D
				1:
					return VisualShaderNode.PORT_TYPE_VECTOR_2D
				2:
					return VisualShaderNode.PORT_TYPE_SCALAR
		2:
			match port:
				0:
					return VisualShaderNode.PORT_TYPE_VECTOR_2D
				1:
					return VisualShaderNode.PORT_TYPE_VECTOR_2D
				2:
					return VisualShaderNode.PORT_TYPE_VECTOR_2D

func _get_output_port_count():
	return 1

func _get_output_port_name(port):
	return ""

func _get_output_port_type(port):
	return VisualShaderNode.PORT_TYPE_SCALAR

func _get_global_code(mode):
	var op = get_option_index(0)
	
	match op:
		0:
			return """
				float sdBox( in vec2 __position, in vec2 __proportions )
				{
					vec2 __d = abs(__position) - __proportions;
					return length(max(__d, 0.0)) + min(max(__d.x, __d.y), 0.0);
				}
			"""
		1:
			return """
				float sdCircle(vec2 pos, float r) {
					return length(pos) - r;
				}
			"""
		2:
			return """
				float sdTriangleIsosceles( in vec2 p, in vec2 q )
				{
					p.x = abs(p.x);
					vec2 a = p - q*clamp( dot(p,q)/dot(q,q), 0.0, 1.0 );
					vec2 b = p - q*vec2( clamp( p.x/q.x, 0.0, 1.0 ), 1.0 );
					float s = -sign( q.y );
					vec2 d = min( vec2( dot(a,a), s*(p.x*q.y-p.y*q.x) ),
								  vec2( dot(b,b), s*(p.y-q.y)  ));
					return -sqrt(d.x)*sign(d.y);
				}
			"""

func _get_code(input_vars, output_vars, mode, type):
	var uv = "UV"
	var op = get_option_index(0)
	
	if input_vars[0]:
		uv = input_vars[0]
	
	match op:
		0:
			return "%s = sdBox(%s.xy - %s.xy, %s.xy);" % [output_vars[0], uv, input_vars[1], input_vars[2]]
		1:
			return "%s = sdCircle(%s.xy - %s.xy, %s);" % [output_vars[0], uv, input_vars[1], input_vars[2]]
		2:
			return "%s = sdTriangleIsosceles(%s.xy - %s.xy, %s.xy);" % [output_vars[0], uv, input_vars[1], input_vars[2]]

@paddy-exe
Copy link
Contributor

Okay it seems like after a little more testing that _get_input_port_type and _get_input_port_name don't get updated consistently either

@Chaosus Chaosus force-pushed the vs_custom_dropdown_list_props branch from c27d773 to 9ecb8f0 Compare September 15, 2023 16:57
@Chaosus
Copy link
Member Author

Chaosus commented Sep 15, 2023

@paddy-exe Try again - I think I've fixed it.

@Chaosus Chaosus force-pushed the vs_custom_dropdown_list_props branch from 9ecb8f0 to 7bbf5b9 Compare September 15, 2023 17:04
@paddy-exe
Copy link
Contributor

@paddy-exe Try again - I think I've fixed it.

image

Seems like it still doesn't work for the init method specifically for the float. I get a compilation error even though the initial value (index 1) is set

@Chaosus Chaosus force-pushed the vs_custom_dropdown_list_props branch from 7bbf5b9 to 3712921 Compare September 28, 2023 08:51
@Chaosus
Copy link
Member Author

Chaosus commented Sep 28, 2023

@paddy-exe Ok, I did not manage to force _init to call on every change of that drop-down property, instead I've added a new _get_input_port_default_value method to VisualShaderNodeCustom, and this works perfectly, so for your task add the following method to shapes code:

func _get_input_port_default_value(port):
	var op = get_option_index(0)
	match op:
		0:
			match port:
				1:
					return Vector2(0.5, 0.5)
				2:
					return Vector2(0.25, 0.25)
		1:
			match port:
				1:
					return Vector2(0.5, 0.5)
				2:
					return 0.25
		2:
			match port:
				1:
					return Vector2(0.5, 0.25)
				2:
					return Vector2(0.25, 0.5)

@Chaosus Chaosus force-pushed the vs_custom_dropdown_list_props branch from 3712921 to 2b71bd4 Compare September 28, 2023 09:13
@Chaosus
Copy link
Member Author

Chaosus commented Sep 28, 2023

Renamed _get_dropdown_list_property to get_property - I think we may manage to introduce new type of properties such TextField or NumberField in the future, so better to reserve a space for it now.

Copy link
Contributor

@paddy-exe paddy-exe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works as expected now 👍🏻 thanks for your work on this!

Note about the video: Apparently you can't see the drop-down in the video but it's shown in the editor so just FYI

VS-OptionsDropDown-PRTest.mp4

@Chaosus Chaosus force-pushed the vs_custom_dropdown_list_props branch 2 times, most recently from 1c2e417 to a119db7 Compare September 29, 2023 07:43
@Chaosus Chaosus force-pushed the vs_custom_dropdown_list_props branch from a119db7 to 4575cc0 Compare September 29, 2023 07:55
@akien-mga akien-mga merged commit 55ba576 into godotengine:master Sep 29, 2023
15 checks passed
@akien-mga
Copy link
Member

Thanks!

@Chaosus Chaosus deleted the vs_custom_dropdown_list_props branch September 29, 2023 18:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Expose Options-Drop-Down in Visual Shader CustomNodes
3 participants