From 475cee9c0fc7b1975de1c5380178763dc2c2df38 Mon Sep 17 00:00:00 2001
From: geequlim <geequlim@gmail.com>
Date: Tue, 17 Oct 2017 22:35:49 +0800
Subject: [PATCH] Abstract some method for script system

---
 core/script_language.h               |  7 ++++-
 modules/gdscript/gdscript.cpp        | 19 +++++++++++-
 modules/gdscript/gdscript.h          |  8 +++--
 modules/gdscript/gdscript_editor.cpp | 45 ++++++++++++++++++++++++++--
 4 files changed, 72 insertions(+), 7 deletions(-)

diff --git a/core/script_language.h b/core/script_language.h
index 5da72d04920..3d01381f3b8 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -120,6 +120,9 @@ public:
 
 	virtual int get_member_line(const StringName &p_member) const { return -1; }
 
+	virtual void get_constants(Map<StringName, Variant> *p_constants) {}
+	virtual void get_members(Set<StringName> *p_constants) {}
+
 	Script() {}
 };
 
@@ -130,6 +133,7 @@ public:
 	virtual void get_property_list(List<PropertyInfo> *p_properties) const = 0;
 	virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const = 0;
 
+	virtual Object *get_owner() { return NULL; }
 	virtual void get_property_state(List<Pair<StringName, Variant> > &state);
 
 	virtual void get_method_list(List<MethodInfo> *p_list) const = 0;
@@ -244,7 +248,8 @@ public:
 	virtual String debug_get_stack_level_source(int p_level) const = 0;
 	virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
 	virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
-	virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
+	virtual ScriptInstance *debug_get_stack_level_instance(int p_level) { return NULL; }
+	virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
 	virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1) = 0;
 
 	struct StackInfo {
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 55ea8a5f248..41a810ff004 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -100,7 +100,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco
 #endif
 	instance->owner->set_script_instance(instance);
 
-/* STEP 2, INITIALIZE AND CONSRTUCT */
+	/* STEP 2, INITIALIZE AND CONSRTUCT */
 
 #ifndef NO_THREADS
 	GDScriptLanguage::singleton->lock->lock();
@@ -615,6 +615,23 @@ ScriptLanguage *GDScript::get_language() const {
 	return GDScriptLanguage::get_singleton();
 }
 
+void GDScript::get_constants(Map<StringName, Variant> *p_constants) {
+
+	if (p_constants) {
+		for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
+			(*p_constants)[E->key()] = E->value();
+		}
+	}
+}
+
+void GDScript::get_members(Set<StringName> *p_members) {
+	if (p_members) {
+		for (Set<StringName>::Element *E = members.front(); E; E = E->next()) {
+			p_members->insert(E->get());
+		}
+	}
+}
+
 Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
 
 	GDScript *top = this;
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 3f6f4319380..6e5d59ad0e6 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -198,6 +198,9 @@ public:
 			return -1;
 	}
 
+	virtual void get_constants(Map<StringName, Variant> *p_constants);
+	virtual void get_members(Set<StringName> *p_members);
+
 	GDScript();
 	~GDScript();
 };
@@ -219,7 +222,7 @@ class GDScriptInstance : public ScriptInstance {
 	void _ml_call_reversed(GDScript *sptr, const StringName &p_method, const Variant **p_args, int p_argcount);
 
 public:
-	_FORCE_INLINE_ Object *get_owner() { return owner; }
+	virtual Object *get_owner() { return owner; }
 
 	virtual bool set(const StringName &p_name, const Variant &p_value);
 	virtual bool get(const StringName &p_name, Variant &r_ret) const;
@@ -407,7 +410,8 @@ public:
 	virtual String debug_get_stack_level_source(int p_level) const;
 	virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
 	virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
-	virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
+	virtual ScriptInstance *debug_get_stack_level_instance(int p_level);
+	virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
 	virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1);
 
 	virtual void reload_all_scripts();
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index a74b8a84839..de7adc7e4a9 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -280,10 +280,49 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *
 		p_values->push_back(instance->debug_get_member_by_index(E->get().index));
 	}
 }
-void GDScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
 
-	//no globals are really reachable in gdscript
+ScriptInstance *GDScriptLanguage::debug_get_stack_level_instance(int p_level) {
+
+	ERR_FAIL_COND_V(_debug_parse_err_line >= 0, NULL);
+	ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, NULL);
+
+	int l = _debug_call_stack_pos - p_level - 1;
+	GDInstance *instance = _call_stack[l].instance;
+
+	return instance;
 }
+
+void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
+
+	const Map<StringName, int> &name_idx = GDScriptLanguage::get_singleton()->get_global_map();
+	const Variant *globals = GDScriptLanguage::get_singleton()->get_global_array();
+
+	for (const Map<StringName, int>::Element *E = name_idx.front(); E; E = E->next()) {
+
+		if (ClassDB::class_exists(E->key()) || ProjectSettings::get_singleton()->has_singleton(E->key()) || E->key() == "PI" || E->key() == "INF" || E->key() == "NAN")
+			continue;
+
+		const Variant &var = globals[E->value()];
+		if (Object *obj = var) {
+			if (Object::cast_to<GDNativeClass>(obj))
+				continue;
+		}
+
+		bool skip = false;
+		for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) {
+			if (E->key() == GlobalConstants::get_global_constant_name(i)) {
+				skip = true;
+				break;
+			}
+		}
+		if (skip)
+			continue;
+
+		p_globals->push_back(E->key());
+		p_values->push_back(var);
+	}
+}
+
 String GDScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) {
 
 	if (_debug_parse_err_line >= 0)
@@ -1743,7 +1782,7 @@ static void _find_type_arguments(GDScriptCompletionContext &context, const GDScr
 			}
 
 		} else {
-//regular method
+		//regular method
 
 #if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED)
 			if (p_argidx < m->get_argument_count()) {