Browse Source

Redesign the graph editor for visual shaders

Hendrik Brucker 1 year ago
parent
commit
02a33b67a8

+ 60 - 0
doc/classes/EditorSettings.xml

@@ -445,6 +445,66 @@
 			The color to use for the TileMap editor's grid.
 			The color to use for the TileMap editor's grid.
 			[b]Note:[/b] Only effective if [member editors/tiles_editor/display_grid] is [code]true[/code].
 			[b]Note:[/b] Only effective if [member editors/tiles_editor/display_grid] is [code]true[/code].
 		</member>
 		</member>
+		<member name="editors/visual_editors/category_colors/color_color" type="Color" setter="" getter="">
+			The color of a graph node's header when it belongs to the "Color" category.
+		</member>
+		<member name="editors/visual_editors/category_colors/conditional_color" type="Color" setter="" getter="">
+			The color of a graph node's header when it belongs to the "Conditional" category.
+		</member>
+		<member name="editors/visual_editors/category_colors/input_color" type="Color" setter="" getter="">
+			The color of a graph node's header when it belongs to the "Input" category.
+		</member>
+		<member name="editors/visual_editors/category_colors/output_color" type="Color" setter="" getter="">
+			The color of a graph node's header when it belongs to the "Output" category.
+		</member>
+		<member name="editors/visual_editors/category_colors/particle_color" type="Color" setter="" getter="">
+			The color of a graph node's header when it belongs to the "Particle" category.
+		</member>
+		<member name="editors/visual_editors/category_colors/scalar_color" type="Color" setter="" getter="">
+			The color of a graph node's header when it belongs to the "Scalar" category.
+		</member>
+		<member name="editors/visual_editors/category_colors/special_color" type="Color" setter="" getter="">
+			The color of a graph node's header when it belongs to the "Special" category.
+		</member>
+		<member name="editors/visual_editors/category_colors/textures_color" type="Color" setter="" getter="">
+			The color of a graph node's header when it belongs to the "Textures" category.
+		</member>
+		<member name="editors/visual_editors/category_colors/transform_color" type="Color" setter="" getter="">
+			The color of a graph node's header when it belongs to the "Transform" category.
+		</member>
+		<member name="editors/visual_editors/category_colors/utility_color" type="Color" setter="" getter="">
+			The color of a graph node's header when it belongs to the "Utility" category.
+		</member>
+		<member name="editors/visual_editors/category_colors/vector_color" type="Color" setter="" getter="">
+			The color of a graph node's header when it belongs to the "Vector" category.
+		</member>
+		<member name="editors/visual_editors/color_theme" type="String" setter="" getter="">
+			The color theme to use in the visual shader editor.
+		</member>
+		<member name="editors/visual_editors/connection_colors/boolean_color" type="Color" setter="" getter="">
+			The color of a port/connection of boolean type.
+		</member>
+		<member name="editors/visual_editors/connection_colors/sampler_color" type="Color" setter="" getter="">
+			The color of a port/connection of sampler type.
+		</member>
+		<member name="editors/visual_editors/connection_colors/scalar_color" type="Color" setter="" getter="">
+			The color of a port/connection of scalar type (float, int, unsigned int).
+		</member>
+		<member name="editors/visual_editors/connection_colors/transform_color" type="Color" setter="" getter="">
+			The color of a port/connection of transform type.
+		</member>
+		<member name="editors/visual_editors/connection_colors/vector2_color" type="Color" setter="" getter="">
+			The color of a port/connection of Vector2 type.
+		</member>
+		<member name="editors/visual_editors/connection_colors/vector3_color" type="Color" setter="" getter="">
+			The color of a port/connection of Vector3 type.
+		</member>
+		<member name="editors/visual_editors/connection_colors/vector4_color" type="Color" setter="" getter="">
+			The color of a port/connection of Vector4 type.
+		</member>
+		<member name="editors/visual_editors/grid_pattern" type="int" setter="" getter="">
+			The pattern used for the background grid.
+		</member>
 		<member name="editors/visual_editors/lines_curvature" type="float" setter="" getter="">
 		<member name="editors/visual_editors/lines_curvature" type="float" setter="" getter="">
 			The curvature to use for connection lines in the visual shader editor. Higher values will make connection lines appear more curved, with values above [code]0.5[/code] resulting in more "angular" turns in the middle of connection lines.
 			The curvature to use for connection lines in the visual shader editor. Higher values will make connection lines appear more curved, with values above [code]0.5[/code] resulting in more "angular" turns in the middle of connection lines.
 		</member>
 		</member>

+ 29 - 0
editor/editor_settings.cpp

@@ -766,8 +766,13 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 	_initial_set("editors/shader_editor/behavior/files/restore_shaders_on_load", true);
 	_initial_set("editors/shader_editor/behavior/files/restore_shaders_on_load", true);
 
 
 	// Visual editors
 	// Visual editors
+	EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_ENUM, "editors/visual_editors/color_theme", "Default", "Default,Legacy,Custom")
+
+	_load_default_visual_shader_editor_theme();
+
 	EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/visual_editors/minimap_opacity", 0.85, "0.0,1.0,0.01")
 	EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/visual_editors/minimap_opacity", 0.85, "0.0,1.0,0.01")
 	EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/visual_editors/lines_curvature", 0.5, "0.0,1.0,0.01")
 	EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/visual_editors/lines_curvature", 0.5, "0.0,1.0,0.01")
+	EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "editors/visual_editors/grid_pattern", 1, "Lines,Dots")
 	EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/visual_editors/visual_shader/port_preview_size", 160, "100,400,0.01")
 	EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/visual_editors/visual_shader/port_preview_size", 160, "100,400,0.01")
 
 
 	/* Run */
 	/* Run */
@@ -903,6 +908,30 @@ void EditorSettings::_load_godot2_text_editor_theme() {
 	_initial_set("text_editor/theme/highlighting/search_result_border_color", Color(0.41, 0.61, 0.91, 0.38));
 	_initial_set("text_editor/theme/highlighting/search_result_border_color", Color(0.41, 0.61, 0.91, 0.38));
 }
 }
 
 
+void EditorSettings::_load_default_visual_shader_editor_theme() {
+	// Connection type colors
+	_initial_set("editors/visual_editors/connection_colors/scalar_color", Color(0.55, 0.55, 0.55));
+	_initial_set("editors/visual_editors/connection_colors/vector2_color", Color(0.44, 0.43, 0.64));
+	_initial_set("editors/visual_editors/connection_colors/vector3_color", Color(0.337, 0.314, 0.71));
+	_initial_set("editors/visual_editors/connection_colors/vector4_color", Color(0.7, 0.65, 0.147));
+	_initial_set("editors/visual_editors/connection_colors/boolean_color", Color(0.243, 0.612, 0.349));
+	_initial_set("editors/visual_editors/connection_colors/transform_color", Color(0.71, 0.357, 0.64));
+	_initial_set("editors/visual_editors/connection_colors/sampler_color", Color(0.659, 0.4, 0.137));
+
+	// Node category colors (used for the node headers)
+	_initial_set("editors/visual_editors/category_colors/output_color", Color(0.26, 0.10, 0.15));
+	_initial_set("editors/visual_editors/category_colors/color_color", Color(0.5, 0.5, 0.1));
+	_initial_set("editors/visual_editors/category_colors/conditional_color", Color(0.208, 0.522, 0.298));
+	_initial_set("editors/visual_editors/category_colors/input_color", Color(0.502, 0.2, 0.204));
+	_initial_set("editors/visual_editors/category_colors/scalar_color", Color(0.1, 0.5, 0.6));
+	_initial_set("editors/visual_editors/category_colors/textures_color", Color(0.5, 0.3, 0.1));
+	_initial_set("editors/visual_editors/category_colors/transform_color", Color(0.5, 0.3, 0.5));
+	_initial_set("editors/visual_editors/category_colors/utility_color", Color(0.2, 0.2, 0.2));
+	_initial_set("editors/visual_editors/category_colors/vector_color", Color(0.2, 0.2, 0.5));
+	_initial_set("editors/visual_editors/category_colors/special_color", Color(0.098, 0.361, 0.294));
+	_initial_set("editors/visual_editors/category_colors/particle_color", Color(0.12, 0.358, 0.8));
+}
+
 bool EditorSettings::_save_text_editor_theme(String p_file) {
 bool EditorSettings::_save_text_editor_theme(String p_file) {
 	String theme_section = "color_theme";
 	String theme_section = "color_theme";
 	Ref<ConfigFile> cf = memnew(ConfigFile); // hex is better?
 	Ref<ConfigFile> cf = memnew(ConfigFile); // hex is better?

+ 1 - 0
editor/editor_settings.h

@@ -110,6 +110,7 @@ private:
 
 
 	void _load_defaults(Ref<ConfigFile> p_extra_config = Ref<ConfigFile>());
 	void _load_defaults(Ref<ConfigFile> p_extra_config = Ref<ConfigFile>());
 	void _load_godot2_text_editor_theme();
 	void _load_godot2_text_editor_theme();
+	void _load_default_visual_shader_editor_theme();
 	bool _save_text_editor_theme(String p_file);
 	bool _save_text_editor_theme(String p_file);
 	bool _is_default_text_editor_theme(String p_theme_name);
 	bool _is_default_text_editor_theme(String p_theme_name);
 	const String _get_project_metadata_path() const;
 	const String _get_project_metadata_path() const;

+ 2 - 0
editor/editor_settings_dialog.cpp

@@ -71,6 +71,8 @@ void EditorSettingsDialog::_settings_property_edited(const String &p_name) {
 		EditorSettings::get_singleton()->set_manually("interface/theme/spacing_preset", "Custom");
 		EditorSettings::get_singleton()->set_manually("interface/theme/spacing_preset", "Custom");
 	} else if (full_name.begins_with("text_editor/theme/highlighting")) {
 	} else if (full_name.begins_with("text_editor/theme/highlighting")) {
 		EditorSettings::get_singleton()->set_manually("text_editor/theme/color_theme", "Custom");
 		EditorSettings::get_singleton()->set_manually("text_editor/theme/color_theme", "Custom");
+	} else if (full_name.begins_with("editors/visual_editors/connection_colors") || full_name.begins_with("editors/visual_editors/category_colors")) {
+		EditorSettings::get_singleton()->set_manually("editors/visual_editors/color_theme", "Custom");
 	}
 	}
 }
 }
 
 

+ 55 - 25
editor/plugins/visual_shader_editor_plugin.cpp

@@ -104,6 +104,7 @@ void VisualShaderNodePlugin::_bind_methods() {
 ///////////////////
 ///////////////////
 
 
 VisualShaderGraphPlugin::VisualShaderGraphPlugin() {
 VisualShaderGraphPlugin::VisualShaderGraphPlugin() {
+	vs_msdf_fonts_theme.instantiate();
 }
 }
 
 
 void VisualShaderGraphPlugin::_bind_methods() {
 void VisualShaderGraphPlugin::_bind_methods() {
@@ -358,6 +359,13 @@ void VisualShaderGraphPlugin::update_theme() {
 	vector_expanded_color[1] = editor->get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor)); // green
 	vector_expanded_color[1] = editor->get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor)); // green
 	vector_expanded_color[2] = editor->get_theme_color(SNAME("axis_z_color"), EditorStringName(Editor)); // blue
 	vector_expanded_color[2] = editor->get_theme_color(SNAME("axis_z_color"), EditorStringName(Editor)); // blue
 	vector_expanded_color[3] = editor->get_theme_color(SNAME("axis_w_color"), EditorStringName(Editor)); // alpha
 	vector_expanded_color[3] = editor->get_theme_color(SNAME("axis_w_color"), EditorStringName(Editor)); // alpha
+
+	Ref<Font> label_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_msdf", EditorStringName(EditorFonts));
+	Ref<Font> label_bold_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_bold_msdf", EditorStringName(EditorFonts));
+	vs_msdf_fonts_theme->set_font("font", "Label", label_font);
+	vs_msdf_fonts_theme->set_font("font", "GraphNodeTitleLabel", label_bold_font);
+	vs_msdf_fonts_theme->set_font("font", "LineEdit", label_font);
+	vs_msdf_fonts_theme->set_font("font", "Button", label_font);
 }
 }
 
 
 bool VisualShaderGraphPlugin::is_node_has_parameter_instances_relatively(VisualShader::Type p_type, int p_node) const {
 bool VisualShaderGraphPlugin::is_node_has_parameter_instances_relatively(VisualShader::Type p_type, int p_node) const {
@@ -398,34 +406,35 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
 
 
 	Control *offset;
 	Control *offset;
 
 
-	static const Color type_color[] = {
-		Color(0.38, 0.85, 0.96), // scalar (float)
-		Color(0.49, 0.78, 0.94), // scalar (int)
-		Color(0.20, 0.88, 0.67), // scalar (uint)
-		Color(0.74, 0.57, 0.95), // vector2
-		Color(0.84, 0.49, 0.93), // vector3
-		Color(1.0, 0.125, 0.95), // vector4
-		Color(0.55, 0.65, 0.94), // boolean
-		Color(0.96, 0.66, 0.43), // transform
-		Color(1.0, 1.0, 0.0), // sampler
+	const Color type_color[] = {
+		EDITOR_GET("editors/visual_editors/connection_colors/scalar_color"),
+		EDITOR_GET("editors/visual_editors/connection_colors/scalar_color"),
+		EDITOR_GET("editors/visual_editors/connection_colors/scalar_color"),
+		EDITOR_GET("editors/visual_editors/connection_colors/vector2_color"),
+		EDITOR_GET("editors/visual_editors/connection_colors/vector3_color"),
+		EDITOR_GET("editors/visual_editors/connection_colors/vector4_color"),
+		EDITOR_GET("editors/visual_editors/connection_colors/boolean_color"),
+		EDITOR_GET("editors/visual_editors/connection_colors/transform_color"),
+		EDITOR_GET("editors/visual_editors/connection_colors/sampler_color"),
 	};
 	};
 
 
-	static const String vector_expanded_name[4] = {
-		"red",
-		"green",
-		"blue",
-		"alpha"
+	// Keep in sync with VisualShaderNode::Category.
+	const Color category_color[VisualShaderNode::Category::CATEGORY_MAX] = {
+		Color(0.0, 0.0, 0.0), // None (default, not used)
+		EDITOR_GET("editors/visual_editors/category_colors/output_color"),
+		EDITOR_GET("editors/visual_editors/category_colors/color_color"),
+		EDITOR_GET("editors/visual_editors/category_colors/conditional_color"),
+		EDITOR_GET("editors/visual_editors/category_colors/input_color"),
+		EDITOR_GET("editors/visual_editors/category_colors/scalar_color"),
+		EDITOR_GET("editors/visual_editors/category_colors/textures_color"),
+		EDITOR_GET("editors/visual_editors/category_colors/transform_color"),
+		EDITOR_GET("editors/visual_editors/category_colors/utility_color"),
+		EDITOR_GET("editors/visual_editors/category_colors/vector_color"),
+		EDITOR_GET("editors/visual_editors/category_colors/special_color"),
+		EDITOR_GET("editors/visual_editors/category_colors/particle_color"),
 	};
 	};
 
 
-	// Visual shader specific theme for MSDF font.
-	Ref<Theme> vstheme;
-	vstheme.instantiate();
-	Ref<Font> label_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_msdf", EditorStringName(EditorFonts));
-	Ref<Font> label_bold_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_bold_msdf", EditorStringName(EditorFonts));
-	vstheme->set_font("font", "Label", label_font);
-	vstheme->set_font("font", "GraphNodeTitleLabel", label_bold_font);
-	vstheme->set_font("font", "LineEdit", label_font);
-	vstheme->set_font("font", "Button", label_font);
+	static const String vector_expanded_name[4] = { "red", "green", "blue", "alpha" };
 
 
 	Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id);
 	Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id);
 
 
@@ -457,7 +466,18 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
 		node->connect("delete_request", callable_mp(editor, &VisualShaderEditor::_delete_node_request).bind(p_type, p_id), CONNECT_DEFERRED);
 		node->connect("delete_request", callable_mp(editor, &VisualShaderEditor::_delete_node_request).bind(p_type, p_id), CONNECT_DEFERRED);
 	}
 	}
 	graph->add_child(node);
 	graph->add_child(node);
-	node->set_theme(vstheme);
+	node->set_theme(vs_msdf_fonts_theme);
+
+	// Set the node's titlebar color based on its category.
+	if (vsnode->get_category() != VisualShaderNode::CATEGORY_NONE) {
+		Ref<StyleBoxFlat> sb_colored = editor->get_theme_stylebox("titlebar", "GraphNode")->duplicate();
+		sb_colored->set_bg_color(category_color[vsnode->get_category()]);
+		node->add_theme_style_override("titlebar", sb_colored);
+
+		Ref<StyleBoxFlat> sb_colored_selected = editor->get_theme_stylebox("titlebar_selected", "GraphNode")->duplicate();
+		sb_colored_selected->set_bg_color(category_color[vsnode->get_category()].lightened(0.2));
+		node->add_theme_style_override("titlebar_selected", sb_colored_selected);
+	}
 
 
 	if (p_just_update) {
 	if (p_just_update) {
 		Link &link = links[p_id];
 		Link &link = links[p_id];
@@ -506,6 +526,11 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
 		port_offset += 1;
 		port_offset += 1;
 	}
 	}
 
 
+	// Set the minimum width of a node based on the preview size to avoid a resize when toggling the preview.
+	Ref<StyleBoxFlat> graph_node_stylebox = graph->get_theme_stylebox("panel", "GraphNode");
+	int port_preview_size = EDITOR_GET("editors/visual_editors/visual_shader/port_preview_size");
+	node->set_custom_minimum_size(Size2((Math::ceil(graph_node_stylebox->get_minimum_size().width) + port_preview_size) * EDSCALE, 0));
+
 	Ref<VisualShaderNodeParticleEmit> emit = vsnode;
 	Ref<VisualShaderNodeParticleEmit> emit = vsnode;
 	if (emit.is_valid()) {
 	if (emit.is_valid()) {
 		node->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
 		node->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
@@ -4313,7 +4338,9 @@ void VisualShaderEditor::_notification(int p_what) {
 			}
 			}
 			if (EditorSettings::get_singleton()->check_changed_settings_in_group("editors/visual_editors")) {
 			if (EditorSettings::get_singleton()->check_changed_settings_in_group("editors/visual_editors")) {
 				graph->set_minimap_opacity(EDITOR_GET("editors/visual_editors/minimap_opacity"));
 				graph->set_minimap_opacity(EDITOR_GET("editors/visual_editors/minimap_opacity"));
+				graph->set_grid_pattern((GraphEdit::GridPattern) int(EDITOR_GET("editors/visual_editors/grid_pattern")));
 				graph->set_connection_lines_curvature(EDITOR_GET("editors/visual_editors/lines_curvature"));
 				graph->set_connection_lines_curvature(EDITOR_GET("editors/visual_editors/lines_curvature"));
+
 				_update_graph();
 				_update_graph();
 			}
 			}
 		} break;
 		} break;
@@ -5424,6 +5451,9 @@ VisualShaderEditor::VisualShaderEditor() {
 	graph->get_menu_hbox()->set_h_size_flags(SIZE_EXPAND_FILL);
 	graph->get_menu_hbox()->set_h_size_flags(SIZE_EXPAND_FILL);
 	graph->set_v_size_flags(SIZE_EXPAND_FILL);
 	graph->set_v_size_flags(SIZE_EXPAND_FILL);
 	graph->set_h_size_flags(SIZE_EXPAND_FILL);
 	graph->set_h_size_flags(SIZE_EXPAND_FILL);
+	graph->set_grid_pattern(GraphEdit::GridPattern::GRID_PATTERN_DOTS);
+	int grid_pattern = EDITOR_GET("editors/visual_editors/grid_pattern");
+	graph->set_grid_pattern((GraphEdit::GridPattern)grid_pattern);
 	graph->set_show_zoom_label(true);
 	graph->set_show_zoom_label(true);
 	add_child(graph);
 	add_child(graph);
 	SET_DRAG_FORWARDING_GCD(graph, VisualShaderEditor);
 	SET_DRAG_FORWARDING_GCD(graph, VisualShaderEditor);

+ 3 - 0
editor/plugins/visual_shader_editor_plugin.h

@@ -99,6 +99,9 @@ private:
 
 
 	Color vector_expanded_color[4];
 	Color vector_expanded_color[4];
 
 
+	// Visual shader specific theme for using MSDF fonts (on GraphNodes) which reduce aliasing at higher zoom levels.
+	Ref<Theme> vs_msdf_fonts_theme;
+
 protected:
 protected:
 	static void _bind_methods();
 	static void _bind_methods();
 
 

+ 111 - 25
editor/themes/editor_theme_manager.cpp

@@ -39,6 +39,7 @@
 #include "editor/themes/editor_icons.h"
 #include "editor/themes/editor_icons.h"
 #include "editor/themes/editor_scale.h"
 #include "editor/themes/editor_scale.h"
 #include "editor/themes/editor_theme.h"
 #include "editor/themes/editor_theme.h"
+#include "scene/gui/graph_edit.h"
 #include "scene/resources/image_texture.h"
 #include "scene/resources/image_texture.h"
 #include "scene/resources/style_box_flat.h"
 #include "scene/resources/style_box_flat.h"
 #include "scene/resources/style_box_line.h"
 #include "scene/resources/style_box_line.h"
@@ -213,6 +214,7 @@ Ref<EditorTheme> EditorThemeManager::_create_base_theme(const Ref<EditorTheme> &
 	_populate_standard_styles(theme, config);
 	_populate_standard_styles(theme, config);
 	_populate_editor_styles(theme, config);
 	_populate_editor_styles(theme, config);
 	_populate_text_editor_styles(theme, config);
 	_populate_text_editor_styles(theme, config);
+	_populate_visual_shader_styles(theme, config);
 
 
 	OS::get_singleton()->benchmark_end_measure(get_benchmark_key(), "Create Base Theme");
 	OS::get_singleton()->benchmark_end_measure(get_benchmark_key(), "Create Base Theme");
 	return theme;
 	return theme;
@@ -1432,13 +1434,22 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the
 		p_theme->set_stylebox("panel", "GraphEdit", p_config.tree_panel_style);
 		p_theme->set_stylebox("panel", "GraphEdit", p_config.tree_panel_style);
 		p_theme->set_stylebox("menu_panel", "GraphEdit", make_flat_stylebox(p_config.dark_color_1 * Color(1, 1, 1, 0.6), 4, 2, 4, 2, 3));
 		p_theme->set_stylebox("menu_panel", "GraphEdit", make_flat_stylebox(p_config.dark_color_1 * Color(1, 1, 1, 0.6), 4, 2, 4, 2, 3));
 
 
-		if (p_config.dark_theme) {
-			p_theme->set_color("grid_major", "GraphEdit", Color(1.0, 1.0, 1.0, 0.1));
-			p_theme->set_color("grid_minor", "GraphEdit", Color(1.0, 1.0, 1.0, 0.05));
-		} else {
-			p_theme->set_color("grid_major", "GraphEdit", Color(0.0, 0.0, 0.0, 0.15));
-			p_theme->set_color("grid_minor", "GraphEdit", Color(0.0, 0.0, 0.0, 0.07));
+		float grid_base_brightness = p_config.dark_theme ? 1.0 : 0.0;
+		GraphEdit::GridPattern grid_pattern = (GraphEdit::GridPattern) int(EDITOR_GET("editors/visual_editors/grid_pattern"));
+		switch (grid_pattern) {
+			case GraphEdit::GRID_PATTERN_LINES:
+				p_theme->set_color("grid_major", "GraphEdit", Color(grid_base_brightness, grid_base_brightness, grid_base_brightness, 0.10));
+				p_theme->set_color("grid_minor", "GraphEdit", Color(grid_base_brightness, grid_base_brightness, grid_base_brightness, 0.05));
+				break;
+			case GraphEdit::GRID_PATTERN_DOTS:
+				p_theme->set_color("grid_major", "GraphEdit", Color(grid_base_brightness, grid_base_brightness, grid_base_brightness, 0.07));
+				p_theme->set_color("grid_minor", "GraphEdit", Color(grid_base_brightness, grid_base_brightness, grid_base_brightness, 0.07));
+				break;
+			default:
+				WARN_PRINT("Unknown grid pattern.");
+				break;
 		}
 		}
+
 		p_theme->set_color("selection_fill", "GraphEdit", p_theme->get_color(SNAME("box_selection_fill_color"), EditorStringName(Editor)));
 		p_theme->set_color("selection_fill", "GraphEdit", p_theme->get_color(SNAME("box_selection_fill_color"), EditorStringName(Editor)));
 		p_theme->set_color("selection_stroke", "GraphEdit", p_theme->get_color(SNAME("box_selection_stroke_color"), EditorStringName(Editor)));
 		p_theme->set_color("selection_stroke", "GraphEdit", p_theme->get_color(SNAME("box_selection_stroke_color"), EditorStringName(Editor)));
 		p_theme->set_color("activity", "GraphEdit", p_config.dark_theme ? Color(1, 1, 1) : Color(0, 0, 0));
 		p_theme->set_color("activity", "GraphEdit", p_config.dark_theme ? Color(1, 1, 1) : Color(0, 0, 0));
@@ -1489,31 +1500,48 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the
 			const int gn_margin_side = 2;
 			const int gn_margin_side = 2;
 			const int gn_margin_bottom = 2;
 			const int gn_margin_bottom = 2;
 
 
+			const int gn_corner_radius = 3;
+
 			const Color gn_bg_color = p_config.dark_theme ? p_config.dark_color_3 : p_config.dark_color_1.lerp(p_config.mono_color, 0.09);
 			const Color gn_bg_color = p_config.dark_theme ? p_config.dark_color_3 : p_config.dark_color_1.lerp(p_config.mono_color, 0.09);
-			const Color gn_selected_border_color = gn_bg_color.lerp(p_config.accent_color, 0.275);
+			const Color gn_selected_border_color = p_config.dark_theme ? Color(1, 1, 1) : Color(0, 0, 0);
 			const Color gn_frame_bg = gn_bg_color.lerp(p_config.tree_panel_style->get_bg_color(), 0.3);
 			const Color gn_frame_bg = gn_bg_color.lerp(p_config.tree_panel_style->get_bg_color(), 0.3);
 
 
-			Ref<StyleBoxFlat> gn_panel_style = make_flat_stylebox(gn_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, p_config.corner_radius);
-			gn_panel_style->set_border_width_all(p_config.border_width);
-			gn_panel_style->set_border_color(gn_bg_color);
-			gn_panel_style->set_corner_radius_individual(0, 0, p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE);
-			gn_panel_style->set_expand_margin(SIDE_TOP, 17 * EDSCALE);
+			const bool high_contrast_borders = p_config.draw_extra_borders && p_config.dark_theme;
 
 
-			Ref<StyleBoxFlat> gn_panel_selected_style = make_flat_stylebox(gn_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, p_config.corner_radius);
-			gn_panel_selected_style->set_border_width_all(2 * EDSCALE + p_config.border_width);
+			Ref<StyleBoxFlat> gn_panel_style = make_flat_stylebox(gn_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, p_config.corner_radius);
+			gn_panel_style->set_border_width(SIDE_BOTTOM, 2 * EDSCALE);
+			gn_panel_style->set_border_width(SIDE_LEFT, 2 * EDSCALE);
+			gn_panel_style->set_border_width(SIDE_RIGHT, 2 * EDSCALE);
+			gn_panel_style->set_border_color(high_contrast_borders ? gn_bg_color.lightened(0.2) : gn_bg_color.darkened(0.3));
+			gn_panel_style->set_corner_radius_individual(0, 0, gn_corner_radius * EDSCALE, gn_corner_radius * EDSCALE);
+			gn_panel_style->set_anti_aliased(true);
+
+			Ref<StyleBoxFlat> gn_panel_selected_style = gn_panel_style->duplicate();
+			gn_panel_selected_style->set_bg_color(p_config.dark_theme ? gn_bg_color.lightened(0.15) : gn_bg_color.darkened(0.15));
+			gn_panel_selected_style->set_border_width(SIDE_TOP, 0);
+			gn_panel_selected_style->set_border_width(SIDE_BOTTOM, 2 * EDSCALE);
+			gn_panel_selected_style->set_border_width(SIDE_LEFT, 2 * EDSCALE);
+			gn_panel_selected_style->set_border_width(SIDE_RIGHT, 2 * EDSCALE);
 			gn_panel_selected_style->set_border_color(gn_selected_border_color);
 			gn_panel_selected_style->set_border_color(gn_selected_border_color);
-			gn_panel_selected_style->set_corner_radius_individual(0, 0, p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE);
-			gn_panel_selected_style->set_expand_margin(SIDE_TOP, 17 * EDSCALE);
 
 
-			const int gn_titlebar_margin_left = 12;
-			const int gn_titlebar_margin_right = 4; // The rest is for the close button.
+			const int gn_titlebar_margin_top = 8;
+			const int gn_titlebar_margin_side = 12;
+			const int gn_titlebar_margin_bottom = 8;
 
 
-			Ref<StyleBoxFlat> gn_titlebar_style = make_flat_stylebox(gn_bg_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, p_config.corner_radius);
+			Ref<StyleBoxFlat> gn_titlebar_style = make_flat_stylebox(gn_bg_color, gn_titlebar_margin_side, gn_titlebar_margin_top, gn_titlebar_margin_side, gn_titlebar_margin_bottom, p_config.corner_radius);
+			gn_titlebar_style->set_border_width(SIDE_TOP, 2 * EDSCALE);
+			gn_titlebar_style->set_border_width(SIDE_LEFT, 2 * EDSCALE);
+			gn_titlebar_style->set_border_width(SIDE_RIGHT, 2 * EDSCALE);
+			gn_titlebar_style->set_border_color(high_contrast_borders ? gn_bg_color.lightened(0.2) : gn_bg_color.darkened(0.3));
 			gn_titlebar_style->set_expand_margin(SIDE_TOP, 2 * EDSCALE);
 			gn_titlebar_style->set_expand_margin(SIDE_TOP, 2 * EDSCALE);
-			gn_titlebar_style->set_corner_radius_individual(p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE, 0, 0);
-
-			Ref<StyleBoxFlat> gn_titlebar_selected_style = make_flat_stylebox(gn_selected_border_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, p_config.corner_radius);
-			gn_titlebar_selected_style->set_corner_radius_individual(p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE, 0, 0);
+			gn_titlebar_style->set_corner_radius_individual(gn_corner_radius * EDSCALE, gn_corner_radius * EDSCALE, 0, 0);
+			gn_titlebar_style->set_anti_aliased(true);
+
+			Ref<StyleBoxFlat> gn_titlebar_selected_style = gn_titlebar_style->duplicate();
+			gn_titlebar_selected_style->set_border_color(gn_selected_border_color);
+			gn_titlebar_selected_style->set_border_width(SIDE_TOP, 2 * EDSCALE);
+			gn_titlebar_selected_style->set_border_width(SIDE_LEFT, 2 * EDSCALE);
+			gn_titlebar_selected_style->set_border_width(SIDE_RIGHT, 2 * EDSCALE);
 			gn_titlebar_selected_style->set_expand_margin(SIDE_TOP, 2 * EDSCALE);
 			gn_titlebar_selected_style->set_expand_margin(SIDE_TOP, 2 * EDSCALE);
 
 
 			Color gn_decoration_color = p_config.dark_color_1.inverted();
 			Color gn_decoration_color = p_config.dark_color_1.inverted();
@@ -1540,7 +1568,7 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the
 
 
 			p_theme->set_color("resizer_color", "GraphNode", gn_decoration_color);
 			p_theme->set_color("resizer_color", "GraphNode", gn_decoration_color);
 
 
-			p_theme->set_constant("port_h_offset", "GraphNode", 0);
+			p_theme->set_constant("port_h_offset", "GraphNode", 1);
 			p_theme->set_constant("separation", "GraphNode", 1 * EDSCALE);
 			p_theme->set_constant("separation", "GraphNode", 1 * EDSCALE);
 
 
 			Ref<ImageTexture> port_icon = p_theme->get_icon(SNAME("GuiGraphNodePort"), EditorStringName(EditorIcons));
 			Ref<ImageTexture> port_icon = p_theme->get_icon(SNAME("GuiGraphNodePort"), EditorStringName(EditorIcons));
@@ -1551,7 +1579,11 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the
 			// GraphNode's title Label.
 			// GraphNode's title Label.
 			p_theme->set_type_variation("GraphNodeTitleLabel", "Label");
 			p_theme->set_type_variation("GraphNodeTitleLabel", "Label");
 			p_theme->set_stylebox("normal", "GraphNodeTitleLabel", make_empty_stylebox(0, 0, 0, 0));
 			p_theme->set_stylebox("normal", "GraphNodeTitleLabel", make_empty_stylebox(0, 0, 0, 0));
-			p_theme->set_color("font_color", "GraphNodeTitleLabel", p_config.font_color);
+			p_theme->set_color("font_color", "GraphNodeTitleLabel", p_config.dark_theme ? p_config.font_color : Color(1, 1, 1)); // Also use a bright font color for light themes.
+			p_theme->set_color("font_shadow_color", "GraphNodeTitleLabel", Color(0, 0, 0, 0.35));
+			p_theme->set_constant("shadow_outline_size", "GraphNodeTitleLabel", 4);
+			p_theme->set_constant("shadow_offset_x", "GraphNodeTitleLabel", 0);
+			p_theme->set_constant("shadow_offset_y", "GraphNodeTitleLabel", 1);
 			p_theme->set_constant("line_spacing", "GraphNodeTitleLabel", 3 * EDSCALE);
 			p_theme->set_constant("line_spacing", "GraphNodeTitleLabel", 3 * EDSCALE);
 		}
 		}
 	}
 	}
@@ -2306,6 +2338,59 @@ void EditorThemeManager::_populate_text_editor_styles(const Ref<EditorTheme> &p_
 	/* clang-format on */
 	/* clang-format on */
 }
 }
 
 
+void EditorThemeManager::_populate_visual_shader_styles(const Ref<EditorTheme> &p_theme, ThemeConfiguration &p_config) {
+	EditorSettings *ed_settings = EditorSettings::get_singleton();
+	String visual_shader_color_theme = ed_settings->get("editors/visual_editors/color_theme");
+	if (visual_shader_color_theme == "Default") {
+		// Connection type colors
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/scalar_color", Color(0.55, 0.55, 0.55), true);
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/vector2_color", Color(0.44, 0.43, 0.64), true);
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/vector3_color", Color(0.337, 0.314, 0.71), true);
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/vector4_color", Color(0.7, 0.65, 0.147), true);
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/boolean_color", Color(0.243, 0.612, 0.349), true);
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/transform_color", Color(0.71, 0.357, 0.64), true);
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/sampler_color", Color(0.659, 0.4, 0.137), true);
+
+		// Node category colors (used for the node headers)
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/output_color", Color(0.26, 0.10, 0.15), true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/color_color", Color(0.5, 0.5, 0.1), true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/conditional_color", Color(0.208, 0.522, 0.298), true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/input_color", Color(0.502, 0.2, 0.204), true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/scalar_color", Color(0.1, 0.5, 0.6), true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/textures_color", Color(0.5, 0.3, 0.1), true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/transform_color", Color(0.5, 0.3, 0.5), true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/utility_color", Color(0.2, 0.2, 0.2), true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/vector_color", Color(0.2, 0.2, 0.5), true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/special_color", Color(0.098, 0.361, 0.294), true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/particle_color", Color(0.12, 0.358, 0.8), true);
+
+	} else if (visual_shader_color_theme == "Legacy") {
+		// Connection type colors
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/scalar_color", Color(0.38, 0.85, 0.96), true);
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/vector2_color", Color(0.74, 0.57, 0.95), true);
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/vector3_color", Color(0.84, 0.49, 0.93), true);
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/vector4_color", Color(1.0, 0.125, 0.95), true);
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/boolean_color", Color(0.55, 0.65, 0.94), true);
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/transform_color", Color(0.96, 0.66, 0.43), true);
+		ed_settings->set_initial_value("editors/visual_editors/connection_colors/sampler_color", Color(1.0, 1.0, 0.0), true);
+
+		// Node category colors (used for the node headers)
+		Ref<StyleBoxFlat> gn_panel_style = p_theme->get_stylebox("panel", "GraphNode");
+		Color gn_bg_color = gn_panel_style->get_bg_color();
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/output_color", gn_bg_color, true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/color_color", gn_bg_color, true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/conditional_color", gn_bg_color, true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/input_color", gn_bg_color, true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/scalar_color", gn_bg_color, true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/textures_color", gn_bg_color, true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/transform_color", gn_bg_color, true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/utility_color", gn_bg_color, true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/vector_color", gn_bg_color, true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/special_color", gn_bg_color, true);
+		ed_settings->set_initial_value("editors/visual_editors/category_colors/particle_color", gn_bg_color, true);
+	}
+}
+
 void EditorThemeManager::_reset_dirty_flag() {
 void EditorThemeManager::_reset_dirty_flag() {
 	outdated_cache_dirty = true;
 	outdated_cache_dirty = true;
 }
 }
@@ -2348,6 +2433,7 @@ bool EditorThemeManager::is_generated_theme_outdated() {
 				EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/code_font") ||
 				EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/code_font") ||
 				EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/increase_scrollbar_touch_area") ||
 				EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/increase_scrollbar_touch_area") ||
 				EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/scale_gizmo_handles") ||
 				EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/scale_gizmo_handles") ||
+				EditorSettings::get_singleton()->check_changed_settings_in_group("editors/visual_editors") ||
 				EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/theme") ||
 				EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/theme") ||
 				EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/help/help") ||
 				EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/help/help") ||
 				EditorSettings::get_singleton()->check_changed_settings_in_group("docks/property_editor/subresource_hue_tint") ||
 				EditorSettings::get_singleton()->check_changed_settings_in_group("docks/property_editor/subresource_hue_tint") ||

+ 1 - 0
editor/themes/editor_theme_manager.h

@@ -156,6 +156,7 @@ class EditorThemeManager {
 
 
 	static void _generate_text_editor_defaults(ThemeConfiguration &p_config);
 	static void _generate_text_editor_defaults(ThemeConfiguration &p_config);
 	static void _populate_text_editor_styles(const Ref<EditorTheme> &p_theme, ThemeConfiguration &p_config);
 	static void _populate_text_editor_styles(const Ref<EditorTheme> &p_theme, ThemeConfiguration &p_config);
+	static void _populate_visual_shader_styles(const Ref<EditorTheme> &p_theme, ThemeConfiguration &p_config);
 
 
 	static void _reset_dirty_flag();
 	static void _reset_dirty_flag();
 
 

+ 3 - 2
scene/gui/graph_edit.cpp

@@ -52,6 +52,7 @@ constexpr int MINIMAP_PADDING = 5;
 constexpr int MIN_DRAG_DISTANCE_FOR_VALID_CONNECTION = 20;
 constexpr int MIN_DRAG_DISTANCE_FOR_VALID_CONNECTION = 20;
 constexpr int MAX_CONNECTION_LINE_CURVE_TESSELATION_STAGES = 5;
 constexpr int MAX_CONNECTION_LINE_CURVE_TESSELATION_STAGES = 5;
 constexpr int GRID_MINOR_STEPS_PER_MAJOR_LINE = 10;
 constexpr int GRID_MINOR_STEPS_PER_MAJOR_LINE = 10;
+constexpr int GRID_MINOR_STEPS_PER_MAJOR_DOT = 5;
 constexpr int GRID_MIN_SNAPPING_DISTANCE = 2;
 constexpr int GRID_MIN_SNAPPING_DISTANCE = 2;
 constexpr int GRID_MAX_SNAPPING_DISTANCE = 100;
 constexpr int GRID_MAX_SNAPPING_DISTANCE = 100;
 
 
@@ -1349,13 +1350,13 @@ void GraphEdit::_draw_grid() {
 		} break;
 		} break;
 		case GRID_PATTERN_DOTS: {
 		case GRID_PATTERN_DOTS: {
 			Color transparent_grid_minor = theme_cache.grid_minor;
 			Color transparent_grid_minor = theme_cache.grid_minor;
-			transparent_grid_minor.a *= CLAMP(2 * (zoom - 0.4), 0, 1);
+			transparent_grid_minor.a *= CLAMP(1.0 * (zoom - 0.4), 0, 1);
 
 
 			for (int i = from_pos.x; i < from_pos.x + len.x; i++) {
 			for (int i = from_pos.x; i < from_pos.x + len.x; i++) {
 				for (int j = from_pos.y; j < from_pos.y + len.y; j++) {
 				for (int j = from_pos.y; j < from_pos.y + len.y; j++) {
 					Color color = transparent_grid_minor;
 					Color color = transparent_grid_minor;
 
 
-					if (ABS(i) % GRID_MINOR_STEPS_PER_MAJOR_LINE == 0 && ABS(j) % GRID_MINOR_STEPS_PER_MAJOR_LINE == 0) {
+					if (ABS(i) % GRID_MINOR_STEPS_PER_MAJOR_DOT == 0 && ABS(j) % GRID_MINOR_STEPS_PER_MAJOR_DOT == 0) {
 						color = theme_cache.grid_major;
 						color = theme_cache.grid_major;
 					}
 					}
 
 

+ 5 - 0
scene/resources/visual_shader.cpp

@@ -403,6 +403,11 @@ String VisualShaderNode::get_warning(Shader::Mode p_mode, VisualShader::Type p_t
 	return String();
 	return String();
 }
 }
 
 
+VisualShaderNode::Category VisualShaderNode::get_category() const {
+	WARN_PRINT(get_caption() + " is missing a category.");
+	return CATEGORY_NONE;
+}
+
 bool VisualShaderNode::is_input_port_default(int p_port, Shader::Mode p_mode) const {
 bool VisualShaderNode::is_input_port_default(int p_port, Shader::Mode p_mode) const {
 	return false;
 	return false;
 }
 }

+ 49 - 13
scene/resources/visual_shader.h

@@ -255,6 +255,37 @@ VARIANT_ENUM_CAST(VisualShader::VaryingType)
 class VisualShaderNode : public Resource {
 class VisualShaderNode : public Resource {
 	GDCLASS(VisualShaderNode, Resource);
 	GDCLASS(VisualShaderNode, Resource);
 
 
+public:
+	enum PortType {
+		PORT_TYPE_SCALAR,
+		PORT_TYPE_SCALAR_INT,
+		PORT_TYPE_SCALAR_UINT,
+		PORT_TYPE_VECTOR_2D,
+		PORT_TYPE_VECTOR_3D,
+		PORT_TYPE_VECTOR_4D,
+		PORT_TYPE_BOOLEAN,
+		PORT_TYPE_TRANSFORM,
+		PORT_TYPE_SAMPLER,
+		PORT_TYPE_MAX,
+	};
+
+	enum Category {
+		CATEGORY_NONE,
+		CATEGORY_OUTPUT,
+		CATEGORY_COLOR,
+		CATEGORY_CONDITIONAL,
+		CATEGORY_INPUT,
+		CATEGORY_SCALAR,
+		CATEGORY_TEXTURES,
+		CATEGORY_TRANSFORM,
+		CATEGORY_UTILITY,
+		CATEGORY_VECTOR,
+		CATEGORY_SPECIAL,
+		CATEGORY_PARTICLE,
+		CATEGORY_MAX
+	};
+
+private:
 	int port_preview = -1;
 	int port_preview = -1;
 
 
 	HashMap<int, bool> connected_input_ports;
 	HashMap<int, bool> connected_input_ports;
@@ -270,19 +301,6 @@ protected:
 	static void _bind_methods();
 	static void _bind_methods();
 
 
 public:
 public:
-	enum PortType {
-		PORT_TYPE_SCALAR,
-		PORT_TYPE_SCALAR_INT,
-		PORT_TYPE_SCALAR_UINT,
-		PORT_TYPE_VECTOR_2D,
-		PORT_TYPE_VECTOR_3D,
-		PORT_TYPE_VECTOR_4D,
-		PORT_TYPE_BOOLEAN,
-		PORT_TYPE_TRANSFORM,
-		PORT_TYPE_SAMPLER,
-		PORT_TYPE_MAX,
-	};
-
 	bool is_simple_decl() const;
 	bool is_simple_decl() const;
 
 
 	virtual String get_caption() const = 0;
 	virtual String get_caption() const = 0;
@@ -348,6 +366,8 @@ public:
 
 
 	virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const;
 	virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const;
 
 
+	virtual Category get_category() const;
+
 	VisualShaderNode();
 	VisualShaderNode();
 };
 };
 
 
@@ -507,6 +527,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_INPUT; }
+
 	VisualShaderNodeInput();
 	VisualShaderNodeInput();
 };
 };
 
 
@@ -546,6 +568,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_OUTPUT; }
+
 	VisualShaderNodeOutput();
 	VisualShaderNodeOutput();
 };
 };
 
 
@@ -589,6 +613,8 @@ public:
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
 	virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_INPUT; }
+
 	VisualShaderNodeParameter();
 	VisualShaderNodeParameter();
 };
 };
 
 
@@ -661,6 +687,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_INPUT; }
+
 	VisualShaderNodeParameterRef();
 	VisualShaderNodeParameterRef();
 };
 };
 
 
@@ -713,6 +741,8 @@ public:
 	void set_description(const String &p_description);
 	void set_description(const String &p_description);
 	String get_description() const;
 	String get_description() const;
 
 
+	virtual Category get_category() const override { return CATEGORY_SPECIAL; }
+
 	VisualShaderNodeComment();
 	VisualShaderNodeComment();
 };
 };
 
 
@@ -781,6 +811,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_SPECIAL; }
+
 	VisualShaderNodeGroupBase();
 	VisualShaderNodeGroupBase();
 };
 };
 
 
@@ -887,6 +919,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_OUTPUT; }
+
 	VisualShaderNodeVaryingSetter();
 	VisualShaderNodeVaryingSetter();
 };
 };
 
 
@@ -907,6 +941,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_INPUT; }
+
 	VisualShaderNodeVaryingGetter();
 	VisualShaderNodeVaryingGetter();
 };
 };
 
 

+ 101 - 0
scene/resources/visual_shader_nodes.h

@@ -76,6 +76,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_VECTOR; }
+
 	VisualShaderNodeVectorBase();
 	VisualShaderNodeVectorBase();
 };
 };
 
 
@@ -101,6 +103,8 @@ public:
 
 
 	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 = 0;
 	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 = 0;
 
 
+	virtual Category get_category() const override { return CATEGORY_INPUT; }
+
 	VisualShaderNodeConstant();
 	VisualShaderNodeConstant();
 };
 };
 
 
@@ -437,6 +441,8 @@ public:
 
 
 	virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
 	virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_TEXTURES; }
+
 	VisualShaderNodeTexture();
 	VisualShaderNodeTexture();
 };
 };
 
 
@@ -473,6 +479,8 @@ public:
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual bool is_use_prop_slots() const override;
 	virtual bool is_use_prop_slots() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_TEXTURES; }
+
 	VisualShaderNodeCurveTexture();
 	VisualShaderNodeCurveTexture();
 };
 };
 
 
@@ -543,6 +551,8 @@ public:
 
 
 	virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
 	virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_TEXTURES; }
+
 	VisualShaderNodeSample3D();
 	VisualShaderNodeSample3D();
 };
 };
 
 
@@ -671,8 +681,11 @@ public:
 	virtual bool has_output_port_preview(int p_port) const override;
 	virtual bool has_output_port_preview(int p_port) const override;
 
 
 	virtual String generate_global(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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_TEXTURES; }
+
 	VisualShaderNodeLinearSceneDepth();
 	VisualShaderNodeLinearSceneDepth();
 };
 };
 
 
@@ -695,6 +708,8 @@ public:
 	virtual String generate_global(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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_TEXTURES; }
+
 	VisualShaderNodeWorldPositionFromDepth();
 	VisualShaderNodeWorldPositionFromDepth();
 };
 };
 
 
@@ -717,6 +732,8 @@ public:
 	virtual String generate_global(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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_TEXTURES; }
+
 	VisualShaderNodeScreenNormalWorldSpace();
 	VisualShaderNodeScreenNormalWorldSpace();
 };
 };
 
 
@@ -765,6 +782,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_SCALAR; }
+
 	VisualShaderNodeFloatOp();
 	VisualShaderNodeFloatOp();
 };
 };
 
 
@@ -957,6 +976,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_COLOR; }
+
 	VisualShaderNodeColorOp();
 	VisualShaderNodeColorOp();
 };
 };
 
 
@@ -1006,6 +1027,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_TRANSFORM; }
+
 	VisualShaderNodeTransformOp();
 	VisualShaderNodeTransformOp();
 };
 };
 
 
@@ -1050,6 +1073,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_TRANSFORM; }
+
 	VisualShaderNodeTransformVecMult();
 	VisualShaderNodeTransformVecMult();
 };
 };
 
 
@@ -1122,6 +1147,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_SCALAR; }
+
 	VisualShaderNodeFloatFunc();
 	VisualShaderNodeFloatFunc();
 };
 };
 
 
@@ -1166,6 +1193,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_SCALAR; }
+
 	VisualShaderNodeIntFunc();
 	VisualShaderNodeIntFunc();
 };
 };
 
 
@@ -1208,6 +1237,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_SCALAR; }
+
 	VisualShaderNodeUIntFunc();
 	VisualShaderNodeUIntFunc();
 };
 };
 
 
@@ -1327,6 +1358,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_COLOR; }
+
 	VisualShaderNodeColorFunc();
 	VisualShaderNodeColorFunc();
 };
 };
 
 
@@ -1369,6 +1402,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_TRANSFORM; }
+
 	VisualShaderNodeTransformFunc();
 	VisualShaderNodeTransformFunc();
 };
 };
 
 
@@ -1414,6 +1449,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_TEXTURES; }
+
 	VisualShaderNodeUVFunc();
 	VisualShaderNodeUVFunc();
 };
 };
 
 
@@ -1440,6 +1477,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_TEXTURES; }
+
 	VisualShaderNodeUVPolarCoord();
 	VisualShaderNodeUVPolarCoord();
 };
 };
 
 
@@ -1620,6 +1659,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_UTILITY; }
+
 	VisualShaderNodeDerivativeFunc();
 	VisualShaderNodeDerivativeFunc();
 };
 };
 
 
@@ -1669,6 +1710,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_TRANSFORM; }
+
 	VisualShaderNodeOuterProduct();
 	VisualShaderNodeOuterProduct();
 };
 };
 
 
@@ -1714,6 +1757,14 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override {
+		if (op_type == OP_TYPE_SCALAR) {
+			return CATEGORY_SCALAR;
+		} else {
+			return CATEGORY_VECTOR;
+		}
+	}
+
 	VisualShaderNodeStep();
 	VisualShaderNodeStep();
 };
 };
 
 
@@ -1761,6 +1812,14 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override {
+		if (op_type == OP_TYPE_SCALAR) {
+			return CATEGORY_SCALAR;
+		} else {
+			return CATEGORY_VECTOR;
+		}
+	}
+
 	VisualShaderNodeSmoothStep();
 	VisualShaderNodeSmoothStep();
 };
 };
 
 
@@ -1852,6 +1911,14 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override {
+		if (op_type == OP_TYPE_SCALAR) {
+			return CATEGORY_SCALAR;
+		} else {
+			return CATEGORY_VECTOR;
+		}
+	}
+
 	VisualShaderNodeMix();
 	VisualShaderNodeMix();
 };
 };
 
 
@@ -1898,6 +1965,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_TRANSFORM; }
+
 	VisualShaderNodeTransformCompose();
 	VisualShaderNodeTransformCompose();
 };
 };
 
 
@@ -1921,6 +1990,8 @@ public:
 	virtual void set_op_type(OpType p_op_type) override;
 	virtual void set_op_type(OpType p_op_type) 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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_VECTOR; }
+
 	VisualShaderNodeVectorDecompose();
 	VisualShaderNodeVectorDecompose();
 };
 };
 
 
@@ -1942,6 +2013,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_TRANSFORM; }
+
 	VisualShaderNodeTransformDecompose();
 	VisualShaderNodeTransformDecompose();
 };
 };
 
 
@@ -2584,6 +2657,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_CONDITIONAL; }
+
 	VisualShaderNodeIf();
 	VisualShaderNodeIf();
 };
 };
 
 
@@ -2630,6 +2705,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_CONDITIONAL; }
+
 	VisualShaderNodeSwitch();
 	VisualShaderNodeSwitch();
 };
 };
 
 
@@ -2698,6 +2775,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_CONDITIONAL; }
+
 	VisualShaderNodeIs();
 	VisualShaderNodeIs();
 };
 };
 
 
@@ -2772,6 +2851,8 @@ public:
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
 	virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_CONDITIONAL; }
+
 	VisualShaderNodeCompare();
 	VisualShaderNodeCompare();
 };
 };
 
 
@@ -2815,6 +2896,14 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override {
+		if (op_type == OP_TYPE_SCALAR) {
+			return CATEGORY_SCALAR;
+		} else {
+			return CATEGORY_VECTOR;
+		}
+	}
+
 	VisualShaderNodeMultiplyAdd();
 	VisualShaderNodeMultiplyAdd();
 };
 };
 
 
@@ -2862,6 +2951,8 @@ public:
 
 
 	virtual Vector<StringName> get_editable_properties() const override;
 	virtual Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_UTILITY; }
+
 	VisualShaderNodeBillboard();
 	VisualShaderNodeBillboard();
 };
 };
 
 
@@ -2888,6 +2979,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_UTILITY; }
+
 	VisualShaderNodeDistanceFade();
 	VisualShaderNodeDistanceFade();
 };
 };
 
 
@@ -2909,6 +3002,8 @@ public:
 	virtual String generate_global(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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_UTILITY; }
+
 	VisualShaderNodeProximityFade();
 	VisualShaderNodeProximityFade();
 };
 };
 
 
@@ -2929,6 +3024,8 @@ public:
 	virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override;
 	virtual String generate_global_per_node(Shader::Mode p_mode, 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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_UTILITY; }
+
 	VisualShaderNodeRandomRange();
 	VisualShaderNodeRandomRange();
 };
 };
 
 
@@ -2948,6 +3045,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_UTILITY; }
+
 	VisualShaderNodeRemap();
 	VisualShaderNodeRemap();
 };
 };
 
 
@@ -2968,6 +3067,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_UTILITY; }
+
 	VisualShaderNodeRotationByAxis();
 	VisualShaderNodeRotationByAxis();
 };
 };
 
 

+ 20 - 0
scene/resources/visual_shader_particle_nodes.h

@@ -57,6 +57,8 @@ public:
 	virtual HashMap<StringName, String> get_editable_properties_names() const override;
 	virtual HashMap<StringName, String> get_editable_properties_names() const override;
 	bool is_show_prop_names() const override;
 	bool is_show_prop_names() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_PARTICLE; }
+
 	VisualShaderNodeParticleEmitter();
 	VisualShaderNodeParticleEmitter();
 };
 };
 
 
@@ -73,6 +75,8 @@ public:
 	virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override;
 	virtual String generate_global_per_node(Shader::Mode p_mode, 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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_PARTICLE; }
+
 	VisualShaderNodeParticleSphereEmitter();
 	VisualShaderNodeParticleSphereEmitter();
 };
 };
 
 
@@ -90,6 +94,8 @@ public:
 	virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override;
 	virtual String generate_global_per_node(Shader::Mode p_mode, 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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_PARTICLE; }
+
 	VisualShaderNodeParticleBoxEmitter();
 	VisualShaderNodeParticleBoxEmitter();
 };
 };
 
 
@@ -106,6 +112,8 @@ public:
 	virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override;
 	virtual String generate_global_per_node(Shader::Mode p_mode, 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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_PARTICLE; }
+
 	VisualShaderNodeParticleRingEmitter();
 	VisualShaderNodeParticleRingEmitter();
 };
 };
 
 
@@ -158,6 +166,8 @@ public:
 	HashMap<StringName, String> get_editable_properties_names() const override;
 	HashMap<StringName, String> get_editable_properties_names() const override;
 	Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override;
 	Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_PARTICLE; }
+
 	VisualShaderNodeParticleMeshEmitter();
 	VisualShaderNodeParticleMeshEmitter();
 };
 };
 
 
@@ -187,6 +197,8 @@ public:
 	bool is_degrees_mode() const;
 	bool is_degrees_mode() const;
 	Vector<StringName> get_editable_properties() const override;
 	Vector<StringName> get_editable_properties() const override;
 
 
+	virtual Category get_category() const override { return CATEGORY_PARTICLE; }
+
 	VisualShaderNodeParticleMultiplyByAxisAngle();
 	VisualShaderNodeParticleMultiplyByAxisAngle();
 };
 };
 
 
@@ -207,6 +219,8 @@ public:
 
 
 	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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_PARTICLE; }
+
 	VisualShaderNodeParticleConeVelocity();
 	VisualShaderNodeParticleConeVelocity();
 };
 };
 
 
@@ -248,6 +262,8 @@ public:
 	void set_op_type(OpType p_type);
 	void set_op_type(OpType p_type);
 	OpType get_op_type() const;
 	OpType get_op_type() const;
 
 
+	virtual Category get_category() const override { return CATEGORY_PARTICLE; }
+
 	VisualShaderNodeParticleRandomness();
 	VisualShaderNodeParticleRandomness();
 };
 };
 
 
@@ -290,6 +306,8 @@ public:
 	void set_mode(Mode p_mode);
 	void set_mode(Mode p_mode);
 	Mode get_mode() const;
 	Mode get_mode() const;
 
 
+	virtual Category get_category() const override { return CATEGORY_PARTICLE; }
+
 	VisualShaderNodeParticleAccelerator();
 	VisualShaderNodeParticleAccelerator();
 };
 };
 
 
@@ -352,6 +370,8 @@ public:
 	virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override;
 	virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) 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;
 	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;
 
 
+	virtual Category get_category() const override { return CATEGORY_PARTICLE; }
+
 	VisualShaderNodeParticleEmit();
 	VisualShaderNodeParticleEmit();
 };
 };