From 6914597026f6deb284a510f41b90d53b4addce1d Mon Sep 17 00:00:00 2001
From: Yuri Roubinsky <chaosus89@gmail.com>
Date: Tue, 13 Oct 2020 11:53:06 +0300
Subject: [PATCH] FIx autocompletion for emit_particle in shader editor

---
 servers/rendering/shader_language.cpp | 59 ++++++++++++++++++++++++++-
 servers/rendering/shader_language.h   |  1 +
 2 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 6c835fcadf9..1883b6b3389 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -5912,6 +5912,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
 	int instance_index = 0;
 	ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
 
+	stages = &p_functions;
+
 	while (tk.type != TK_EOF) {
 		switch (tk.type) {
 			case TK_RENDER_MODE: {
@@ -7326,6 +7328,12 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
 				int idx = 0;
 				bool low_end = RenderingServer::get_singleton()->is_low_end();
 
+				if (stages && stages->has(skip_function)) {
+					for (const Map<StringName, StageFunctionInfo>::Element *E = (*stages)[skip_function].stage_functions.front(); E; E = E->next()) {
+						matches.insert(String(E->key()), ScriptCodeCompletionOption::KIND_FUNCTION);
+					}
+				}
+
 				while (builtin_func_defs[idx].name) {
 					if (low_end && builtin_func_defs[idx].high_end) {
 						idx++;
@@ -7362,6 +7370,16 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
 			return OK;
 		} break;
 		case COMPLETION_CALL_ARGUMENTS: {
+			StringName block_function;
+			BlockNode *block = completion_block;
+
+			while (block) {
+				if (block->parent_function) {
+					block_function = block->parent_function->name;
+				}
+				block = block->parent_block;
+			}
+
 			for (int i = 0; i < shader->functions.size(); i++) {
 				if (!shader->functions[i].callable) {
 					continue;
@@ -7421,6 +7439,45 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
 			String calltip;
 			bool low_end = RenderingServer::get_singleton()->is_low_end();
 
+			if (stages && stages->has(block_function)) {
+				for (const Map<StringName, StageFunctionInfo>::Element *E = (*stages)[block_function].stage_functions.front(); E; E = E->next()) {
+					if (completion_function == E->key()) {
+						calltip += get_datatype_name(E->get().return_type);
+						calltip += " ";
+						calltip += E->key();
+						calltip += "(";
+
+						for (int i = 0; i < E->get().arguments.size(); i++) {
+							if (i > 0) {
+								calltip += ", ";
+							} else {
+								calltip += " ";
+							}
+
+							if (i == completion_argument) {
+								calltip += char32_t(0xFFFF);
+							}
+
+							calltip += get_datatype_name(E->get().arguments[i].type);
+							calltip += " ";
+							calltip += E->get().arguments[i].name;
+
+							if (i == completion_argument) {
+								calltip += char32_t(0xFFFF);
+							}
+						}
+
+						if (E->get().arguments.size()) {
+							calltip += " ";
+						}
+						calltip += ")";
+
+						r_call_hint = calltip;
+						return OK;
+					}
+				}
+			}
+
 			while (builtin_func_defs[idx].name) {
 				if (low_end && builtin_func_defs[idx].high_end) {
 					idx++;
@@ -7453,7 +7510,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
 					calltip += "(";
 
 					bool found_arg = false;
-					for (int i = 0; i < 4; i++) {
+					for (int i = 0; i < BuiltinFuncDef::MAX_ARGS - 1; i++) {
 						if (builtin_func_defs[idx].args[i] == TYPE_VOID) {
 							break;
 						}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 0d044a21c72..3c0a10809be 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -846,6 +846,7 @@ private:
 	StringName completion_function;
 	StringName completion_struct;
 	int completion_argument;
+	const Map<StringName, FunctionInfo> *stages = nullptr;
 
 	bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
 	static const BuiltinFuncDef builtin_func_defs[];