diff options
-rw-r--r-- | core/class_db.cpp | 29 | ||||
-rw-r--r-- | core/class_db.h | 2 | ||||
-rw-r--r-- | core/make_binders.py | 20 | ||||
-rw-r--r-- | core/method_bind.cpp | 46 | ||||
-rw-r--r-- | core/method_bind.h | 52 | ||||
-rw-r--r-- | core/object.cpp | 4 | ||||
-rw-r--r-- | core/object.h | 19 | ||||
-rw-r--r-- | core/reference.h | 8 | ||||
-rw-r--r-- | core/script_language.h | 2 | ||||
-rw-r--r-- | core/type_info.h | 85 | ||||
-rw-r--r-- | editor/code_editor.cpp | 6 | ||||
-rw-r--r-- | editor/code_editor.h | 2 | ||||
-rw-r--r-- | editor/doc/doc_data.cpp | 206 | ||||
-rw-r--r-- | editor/doc/doc_data.h | 4 | ||||
-rw-r--r-- | editor/editor_help.cpp | 201 | ||||
-rw-r--r-- | editor/editor_help.h | 3 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.cpp | 1 | ||||
-rw-r--r-- | editor/plugins/script_text_editor.cpp | 8 | ||||
-rw-r--r-- | editor/plugins/script_text_editor.h | 4 | ||||
-rw-r--r-- | modules/gdnative/config.py | 2 | ||||
-rw-r--r-- | modules/gdscript/gd_editor.cpp | 153 | ||||
-rw-r--r-- | modules/gdscript/gd_parser.cpp | 18 | ||||
-rw-r--r-- | modules/gdscript/gd_parser.h | 1 | ||||
-rw-r--r-- | modules/gdscript/gd_script.h | 2 | ||||
-rw-r--r-- | modules/nativescript/config.py | 2 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 16 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 3 |
27 files changed, 600 insertions, 299 deletions
diff --git a/core/class_db.cpp b/core/class_db.cpp index 6cd7586a54..cd55219b53 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -538,9 +538,7 @@ void ClassDB::get_method_list(StringName p_class, List<MethodInfo> *p_methods, b minfo.arguments.push_back(method->get_argument_info(i)); } - if (method->get_argument_type(-1) != Variant::NIL) { - minfo.return_val = method->get_argument_info(-1); - } + minfo.return_val = method->get_return_info(); minfo.flags = method->get_hint_flags(); p_methods->push_back(minfo); @@ -600,14 +598,23 @@ void ClassDB::bind_integer_constant(const StringName &p_class, const StringName type->constant_map[p_name] = p_constant; #ifdef DEBUG_METHODS_ENABLED - List<StringName> *constants_list = type->enum_map.getptr(p_enum); - if (constants_list) { - constants_list->push_back(p_name); - } else { - List<StringName> new_list; - new_list.push_back(p_name); - type->enum_map[p_enum] = new_list; + String enum_name = p_enum; + if (enum_name!=String()) { + if (enum_name.find(".")!=-1) { + enum_name=enum_name.get_slicec('.',1); + } + + List<StringName> *constants_list = type->enum_map.getptr(enum_name); + + if (constants_list) { + constants_list->push_back(p_name); + } else { + List<StringName> new_list; + new_list.push_back(p_name); + type->enum_map[enum_name] = new_list; + } + } type->constant_order.push_back(p_name); @@ -680,7 +687,7 @@ StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const S List<StringName> &constants_list = type->enum_map.get(*k); const List<StringName>::Element *found = constants_list.find(p_name); if (found) - return found->get(); + return *k; } if (p_no_inheritance) diff --git a/core/class_db.h b/core/class_db.h index 8d9192adcc..0943cd36cc 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -457,7 +457,7 @@ public: } type->method_map[p_name] = bind; #ifdef DEBUG_METHODS_ENABLED - bind->set_return_type("Variant"); +// bind->set_return_type("Variant"); type->method_order.push_back(p_name); #endif diff --git a/core/make_binders.py b/core/make_binders.py index a5cdb78443..0252bb638b 100644 --- a/core/make_binders.py +++ b/core/make_binders.py @@ -16,12 +16,11 @@ public: $ return Variant::NIL; } - virtual StringName _gen_argument_type_name(int p_arg) const { return _gen_argument_type_hint(p_arg); } - StringName _gen_argument_type_hint(int p_argument) const { - $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_name();$ - $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_name(); + virtual PropertyInfo _gen_argument_type_info(int p_argument) const { + $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_info();$ + $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_info(); $ - return StringName(); + return PropertyInfo(); } #endif virtual String get_instance_class() const { @@ -104,14 +103,13 @@ public: return Variant::NIL; } - virtual StringName _gen_argument_type_name(int p_arg) const { return _gen_argument_type_hint(p_arg); } - - StringName _gen_argument_type_hint(int p_argument) const { - $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_name();$ - $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_name(); + virtual PropertyInfo _gen_argument_type_info(int p_argument) const { + $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_info();$ + $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_info(); $ - return StringName(); + return PropertyInfo(); } + #endif virtual String get_instance_class() const { return type_name; diff --git a/core/method_bind.cpp b/core/method_bind.cpp index 6792b62703..660350b899 100644 --- a/core/method_bind.cpp +++ b/core/method_bind.cpp @@ -36,31 +36,16 @@ #ifdef DEBUG_METHODS_ENABLED PropertyInfo MethodBind::get_argument_info(int p_argument) const { - if (p_argument >= 0) { + ERR_FAIL_INDEX_V(p_argument, get_argument_count(), PropertyInfo()); - String name = p_argument < arg_names.size() ? String(arg_names[p_argument]) : String("arg" + itos(p_argument)); - PropertyInfo pi(get_argument_type(p_argument), name); - - if (!is_vararg() && pi.type == Variant::OBJECT) { - StringName type_hint = arg_type_hints[p_argument]; - - if (type_hint != StringName()) { - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = type_hint.operator String(); - } - } - return pi; + PropertyInfo info = _gen_argument_type_info(p_argument); + info.name = p_argument < arg_names.size() ? String(arg_names[p_argument]) : String("arg" + itos(p_argument)); + return info; +} - } else { +PropertyInfo MethodBind::get_return_info() const { - Variant::Type at = get_argument_type(-1); - if (at == Variant::OBJECT && ret_type) - return PropertyInfo(at, "ret", PROPERTY_HINT_RESOURCE_TYPE, ret_type); - else - return PropertyInfo(at, "ret"); - } - - return PropertyInfo(); + return _gen_argument_type_info(-1); } #endif @@ -91,16 +76,6 @@ Vector<StringName> MethodBind::get_argument_names() const { return arg_names; } -void MethodBind::set_argument_type_hints(const Vector<StringName> &p_type_hints) { - - arg_type_hints = p_type_hints; -} - -Vector<StringName> MethodBind::get_argument_type_hints() const { - - return arg_type_hints; -} - #endif void MethodBind::set_default_arguments(const Vector<Variant> &p_defargs) { @@ -114,18 +89,13 @@ void MethodBind::_generate_argument_types(int p_count) { set_argument_count(p_count); Variant::Type *argt = memnew_arr(Variant::Type, p_count + 1); - - arg_type_hints.resize(p_count); - argt[0] = _gen_argument_type(-1); // return type - set_return_type(_gen_argument_type_hint(-1)); for (int i = 0; i < p_count; i++) { argt[i + 1] = _gen_argument_type(i); - arg_type_hints[i] = _gen_argument_type_hint(i); } - set_argument_types(argt); + argument_types = argt; } #endif diff --git a/core/method_bind.h b/core/method_bind.h index 157a67ca20..1f4c3ff66b 100644 --- a/core/method_bind.h +++ b/core/method_bind.h @@ -188,23 +188,22 @@ class MethodBind { Vector<Variant> default_arguments; int default_argument_count; int argument_count; -#ifdef DEBUG_METHODS_ENABLED - Vector<StringName> arg_names; - Vector<StringName> arg_type_hints; - Variant::Type *argument_types; - StringName ret_type; -#endif + bool _const; bool _returns; protected: +#ifdef DEBUG_METHODS_ENABLED + Variant::Type *argument_types; + Vector<StringName> arg_names; +#endif void _set_const(bool p_const); void _set_returns(bool p_returns); #ifdef DEBUG_METHODS_ENABLED virtual Variant::Type _gen_argument_type(int p_arg) const = 0; - virtual StringName _gen_argument_type_hint(int p_arg) const = 0; + virtual PropertyInfo _gen_argument_type_info(int p_arg) const = 0; void _generate_argument_types(int p_count); - void set_argument_types(Variant::Type *p_types) { argument_types = p_types; } + #endif void set_argument_count(int p_count) { argument_count = p_count; } @@ -234,9 +233,6 @@ public: #ifdef DEBUG_METHODS_ENABLED - _FORCE_INLINE_ void set_return_type(const StringName &p_type) { ret_type = p_type; } - _FORCE_INLINE_ StringName get_return_type() const { return ret_type; } - _FORCE_INLINE_ Variant::Type get_argument_type(int p_argument) const { ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, Variant::NIL); @@ -244,12 +240,11 @@ public: } PropertyInfo get_argument_info(int p_argument) const; + PropertyInfo get_return_info() const; - void set_argument_names(const Vector<StringName> &p_names); + void set_argument_names(const Vector<StringName> &p_names); //set by class, db, cant be inferred otherwise Vector<StringName> get_argument_names() const; - void set_argument_type_hints(const Vector<StringName> &p_type_hints); - Vector<StringName> get_argument_type_hints() const; #endif void set_hint_flags(uint32_t p_hint) { hint_flags = p_hint; } uint32_t get_hint_flags() const { return hint_flags | (is_const() ? METHOD_FLAG_CONST : 0) | (is_vararg() ? METHOD_FLAG_VARARG : 0); } @@ -305,18 +300,36 @@ public: protected: NativeCall call_method; +#ifdef DEBUG_METHODS_ENABLED + + MethodInfo arguments; +#endif public: - virtual Variant::Type _gen_argument_type(int p_arg) const { +#ifdef DEBUG_METHODS_ENABLED - return Variant::NIL; + virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + + if (p_arg < 0) { + return arguments.return_val; + } else if (p_arg < arguments.arguments.size()) { + return arguments.arguments[p_arg]; + } else { + return PropertyInfo(Variant::NIL, "arg_" + itos(p_arg), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); + } } - virtual StringName _gen_argument_type_hint(int p_arg) const { + virtual Variant::Type _gen_argument_type(int p_arg) const { + return _gen_argument_type_info(p_arg).type; + } + +#else - return "Variant"; + virtual Variant::Type _gen_argument_type(int p_arg) const { + return Variant::NIL; } +#endif virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Variant::CallError &r_error) { T *instance = static_cast<T *>(p_object); @@ -341,7 +354,8 @@ public: set_argument_names(names); } - set_argument_types(at); + argument_types = at; + arguments = p_info; #endif } diff --git a/core/object.cpp b/core/object.cpp index a43a9c85b1..928e9bb978 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -65,6 +65,7 @@ PropertyInfo::operator Dictionary() const { Dictionary d; d["name"] = name; + d["class_name"] = class_name; d["type"] = type; d["hint"] = hint; d["hint_string"] = hint_string; @@ -82,6 +83,9 @@ PropertyInfo PropertyInfo::from_dict(const Dictionary &p_dict) { if (p_dict.has("name")) pi.name = p_dict["name"]; + if (p_dict.has("class_name")) + pi.class_name = p_dict["class_name"]; + if (p_dict.has("hint")) pi.hint = PropertyHint(int(p_dict["hint"])); diff --git a/core/object.h b/core/object.h index 8a858b5b00..43d77ed49d 100644 --- a/core/object.h +++ b/core/object.h @@ -107,6 +107,8 @@ enum PropertyUsageFlags { PROPERTY_USAGE_ANIMATE_AS_TRIGGER = 32768, PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED = 65536, PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 << 17, + PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 18, + PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 19, PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK, PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED, @@ -126,6 +128,7 @@ struct PropertyInfo { Variant::Type type; String name; + StringName class_name; //for classes PropertyHint hint; String hint_string; uint32_t usage; @@ -145,13 +148,27 @@ struct PropertyInfo { hint(PROPERTY_HINT_NONE), usage(PROPERTY_USAGE_DEFAULT) { } - PropertyInfo(Variant::Type p_type, const String p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT) + PropertyInfo(Variant::Type p_type, const String p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = StringName()) : type(p_type), name(p_name), hint(p_hint), hint_string(p_hint_string), usage(p_usage) { + + if (hint == PROPERTY_HINT_RESOURCE_TYPE) { + class_name = hint_string; + } else { + class_name = p_class_name; + } + } + PropertyInfo(const StringName &p_class_name) + : type(Variant::OBJECT), + hint(PROPERTY_HINT_NONE), + usage(PROPERTY_USAGE_DEFAULT) { + + class_name = p_class_name; } + bool operator<(const PropertyInfo &p_info) const { return name < p_info.name; } diff --git a/core/reference.h b/core/reference.h index 69250a4701..764c924cdb 100644 --- a/core/reference.h +++ b/core/reference.h @@ -382,8 +382,8 @@ template <class T> struct GetTypeInfo<Ref<T> > { enum { VARIANT_TYPE = Variant::OBJECT }; - static inline StringName get_class_name() { - return T::get_class_static(); + static inline PropertyInfo get_class_info() { + return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static()); } }; @@ -391,8 +391,8 @@ template <class T> struct GetTypeInfo<const Ref<T> &> { enum { VARIANT_TYPE = Variant::OBJECT }; - static inline StringName get_class_name() { - return T::get_class_static(); + static inline PropertyInfo get_class_info() { + return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static()); } }; diff --git a/core/script_language.h b/core/script_language.h index 7aba3ec0f1..5baf2e6f80 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -207,7 +207,7 @@ public: virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const = 0; virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; } - virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint) { return ERR_UNAVAILABLE; } + virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; } struct LookupResult { enum Type { diff --git a/core/type_info.h b/core/type_info.h index 0603126996..a7d3fa20c8 100644 --- a/core/type_info.h +++ b/core/type_info.h @@ -41,9 +41,9 @@ template <class T, typename = void> struct GetTypeInfo { enum { VARIANT_TYPE = Variant::NIL }; - static inline StringName get_class_name() { + static inline PropertyInfo get_class_info() { ERR_PRINT("GetTypeInfo fallback. Bug!"); - return StringName(); // Not "Nil", this is an error + return PropertyInfo(); // Not "Nil", this is an error } }; @@ -51,15 +51,15 @@ struct GetTypeInfo { template <> \ struct GetTypeInfo<m_type> { \ enum { VARIANT_TYPE = m_var_type }; \ - static inline StringName get_class_name() { \ - return Variant::get_type_name((Variant::Type)VARIANT_TYPE); \ + static inline PropertyInfo get_class_info() { \ + return PropertyInfo((Variant::Type)VARIANT_TYPE,String()); \ } \ }; \ template <> \ struct GetTypeInfo<const m_type &> { \ enum { VARIANT_TYPE = m_var_type }; \ - static inline StringName get_class_name() { \ - return Variant::get_type_name((Variant::Type)VARIANT_TYPE); \ + static inline PropertyInfo get_class_info() { \ + return PropertyInfo((Variant::Type)VARIANT_TYPE,String()); \ } \ }; @@ -105,38 +105,54 @@ MAKE_TYPE_INFO(IP_Address, Variant::STRING) class BSP_Tree; MAKE_TYPE_INFO(BSP_Tree, Variant::DICTIONARY) -#define MAKE_TYPE_INFO_WITH_NAME(m_type, m_var_type, m_class_name) \ - template <> \ - struct GetTypeInfo<m_type> { \ - enum { VARIANT_TYPE = m_var_type }; \ - static inline StringName get_class_name() { \ - return m_class_name; \ - } \ - }; \ - template <> \ - struct GetTypeInfo<const m_type &> { \ - enum { VARIANT_TYPE = m_var_type }; \ - static inline StringName get_class_name() { \ - return m_class_name; \ - } \ - }; +//for RefPtr +template <> +struct GetTypeInfo<RefPtr> { + enum { VARIANT_TYPE = Variant::OBJECT }; + static inline PropertyInfo get_class_info() { + return PropertyInfo(Variant::OBJECT,String(),PROPERTY_HINT_RESOURCE_TYPE,"Reference"); + } +}; +template <> +struct GetTypeInfo<const RefPtr &> { + enum { VARIANT_TYPE = Variant::OBJECT }; + static inline PropertyInfo get_class_info() { + return PropertyInfo(Variant::OBJECT,String(),PROPERTY_HINT_RESOURCE_TYPE,"Reference"); + } +}; + + +//for variant +template<> +struct GetTypeInfo<Variant> { + enum { VARIANT_TYPE = Variant::NIL }; + static inline PropertyInfo get_class_info() { + return PropertyInfo(Variant::NIL,String(),PROPERTY_HINT_NONE,String(),PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_NIL_IS_VARIANT); + } +}; + +template<> +struct GetTypeInfo<const Variant&> { + enum { VARIANT_TYPE = Variant::NIL }; + static inline PropertyInfo get_class_info() { + return PropertyInfo(Variant::NIL,String(),PROPERTY_HINT_NONE,String(),PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_NIL_IS_VARIANT); + } +}; -MAKE_TYPE_INFO_WITH_NAME(RefPtr, Variant::OBJECT, "Reference") -MAKE_TYPE_INFO_WITH_NAME(Variant, Variant::NIL, "Variant") #define MAKE_TEMPLATE_TYPE_INFO(m_template, m_type, m_var_type) \ template <> \ struct GetTypeInfo<m_template<m_type> > { \ enum { VARIANT_TYPE = m_var_type }; \ - static inline StringName get_class_name() { \ - return Variant::get_type_name((Variant::Type)VARIANT_TYPE); \ + static inline PropertyInfo get_class_info() { \ + return PropertyInfo((Variant::Type)VARIANT_TYPE,String()); \ } \ }; \ template <> \ struct GetTypeInfo<const m_template<m_type> &> { \ enum { VARIANT_TYPE = m_var_type }; \ - static inline StringName get_class_name() { \ - return Variant::get_type_name((Variant::Type)VARIANT_TYPE); \ + static inline PropertyInfo get_class_info() { \ + return PropertyInfo((Variant::Type)VARIANT_TYPE,String()); \ } \ }; @@ -159,17 +175,18 @@ template <typename T> struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type> { enum { VARIANT_TYPE = Variant::OBJECT }; - static inline StringName get_class_name() { - return T::get_class_static(); + static inline PropertyInfo get_class_info() { + return PropertyInfo(StringName(T::get_class_static())); } + }; template <typename T> struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>::type> { enum { VARIANT_TYPE = Variant::OBJECT }; - static inline StringName get_class_name() { - return T::get_class_static(); + static inline PropertyInfo get_class_info() { + return PropertyInfo(StringName(T::get_class_static())); } }; @@ -177,7 +194,9 @@ struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>: template <> \ struct GetTypeInfo<m_impl> { \ enum { VARIANT_TYPE = Variant::INT }; \ - static inline StringName get_class_name() { return "enum." #m_enum; } \ + static inline PropertyInfo get_class_info() { \ + return PropertyInfo(Variant::INT,String(),PROPERTY_HINT_NONE,String(),PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_CLASS_IS_ENUM,String(#m_enum).replace("::",".")); \ + } \ }; #define MAKE_ENUM_TYPE_INFO(m_enum) \ @@ -190,7 +209,7 @@ template <typename T> inline StringName __constant_get_enum_name(T param, const String &p_constant) { if (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL) ERR_PRINTS("Missing VARIANT_ENUM_CAST for constant's enum: " + p_constant); - return GetTypeInfo<T>::get_class_name(); + return GetTypeInfo<T>::get_class_info().class_name; } #else diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 4575bfcb08..d49b240c80 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1036,8 +1036,9 @@ void CodeTextEditor::_complete_request() { List<String> entries; String ctext = text_editor->get_text_for_completion(); _code_complete_script(ctext, &entries); + bool forced = false; if (code_complete_func) { - code_complete_func(code_complete_ud, ctext, &entries); + code_complete_func(code_complete_ud, ctext, &entries, forced); } // print_line("COMPLETE: "+p_request); if (entries.size() == 0) @@ -1050,7 +1051,7 @@ void CodeTextEditor::_complete_request() { strs[i++] = E->get(); } - text_editor->code_complete(strs); + text_editor->code_complete(strs, forced); } void CodeTextEditor::_font_resize_timeout() { @@ -1267,6 +1268,7 @@ CodeTextEditor::CodeTextEditor() { cs.push_back("."); cs.push_back(","); cs.push_back("("); + cs.push_back("="); cs.push_back("$"); text_editor->set_completion(true, cs); idle->connect("timeout", this, "_text_changed_idle_timeout"); diff --git a/editor/code_editor.h b/editor/code_editor.h index 8d48c56503..e56d7f7fab 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -186,7 +186,7 @@ public: FindReplaceDialog(); }; -typedef void (*CodeTextEditorCodeCompleteFunc)(void *p_ud, const String &p_code, List<String> *r_options); +typedef void (*CodeTextEditorCodeCompleteFunc)(void *p_ud, const String &p_code, List<String> *r_options, bool &r_forced); class CodeTextEditor : public VBoxContainer { diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp index 69d7475f4c..d46649f052 100644 --- a/editor/doc/doc_data.cpp +++ b/editor/doc/doc_data.cpp @@ -196,10 +196,40 @@ void DocData::generate(bool p_basic_types) { prop.name = E->get().name; prop.setter = setter; prop.getter = getter; - if (E->get().type == Variant::OBJECT && E->get().hint == PROPERTY_HINT_RESOURCE_TYPE) - prop.type = E->get().hint_string; - else - prop.type = Variant::get_type_name(E->get().type); + + bool found_type = false; + if (getter != StringName()) { + MethodBind *mb = ClassDB::get_method(name, getter); + if (mb) { + PropertyInfo retinfo = mb->get_return_info(); + + found_type = true; + if (retinfo.type == Variant::INT && retinfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + prop.enumeration = retinfo.class_name; + prop.type = "int"; + } else if (retinfo.class_name != StringName()) { + prop.type = retinfo.class_name; + } else if (retinfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { + + prop.type = retinfo.hint_string; + } else if (retinfo.type == Variant::NIL && retinfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) { + + prop.type = "Variant"; + } else if (retinfo.type == Variant::NIL) { + prop.type = "void"; + } else { + prop.type = Variant::get_type_name(retinfo.type); + } + } + } + + if (!found_type) { + + if (E->get().type == Variant::OBJECT && E->get().hint == PROPERTY_HINT_RESOURCE_TYPE) + prop.type = E->get().hint_string; + else + prop.type = Variant::get_type_name(E->get().type); + } c.properties.push_back(prop); } @@ -217,8 +247,6 @@ void DocData::generate(bool p_basic_types) { method.name = E->get().name; - MethodBind *m = ClassDB::get_method(name, E->get().name); - if (E->get().flags & METHOD_FLAG_VIRTUAL) method.qualifiers = "virtual"; if (E->get().flags & METHOD_FLAG_CONST) { @@ -234,122 +262,59 @@ void DocData::generate(bool p_basic_types) { for (int i = -1; i < E->get().arguments.size(); i++) { - PropertyInfo arginfo; - if (i == -1) { - arginfo = E->get().return_val; #ifdef DEBUG_METHODS_ENABLED - if (m && m->get_return_type() != StringName()) - method.return_type = m->get_return_type(); - else if (method.name.find(":") != -1) { - method.return_type = method.name.get_slice(":", 1); - method.name = method.name.get_slice(":", 0); - } else if (arginfo.type != Variant::NIL) // { + PropertyInfo retinfo = E->get().return_val; + + if (retinfo.type == Variant::INT && retinfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + method.return_enum = retinfo.class_name; + method.return_type = "int"; + } else if (retinfo.class_name != StringName()) { + method.return_type = retinfo.class_name; + } else if (retinfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { + + method.return_type = retinfo.hint_string; + } else if (retinfo.type == Variant::NIL && retinfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) { + + method.return_type = "Variant"; + } else if (retinfo.type == Variant::NIL) { + method.return_type = "void"; + } else { + method.return_type = Variant::get_type_name(retinfo.type); + } #endif - method.return_type = (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) ? arginfo.hint_string : Variant::get_type_name(arginfo.type); - //} } else { ArgumentDoc argument; - arginfo = E->get().arguments[i]; - - String type_name; - - if (arginfo.name.find(":") != -1) { - type_name = arginfo.name.get_slice(":", 1); - arginfo.name = arginfo.name.get_slice(":", 0); + PropertyInfo arginfo = E->get().arguments[i]; + if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + argument.enumeration = arginfo.class_name; + argument.type = "int"; + } else if (arginfo.class_name != StringName()) { + argument.type = arginfo.class_name; } else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { - type_name = arginfo.hint_string; - } else if (arginfo.type == Variant::NIL) - type_name = "Variant"; - else - type_name = Variant::get_type_name(arginfo.type); - if (arginfo.type == Variant::OBJECT) { + argument.type = arginfo.hint_string; + } else if (arginfo.type == Variant::NIL && arginfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) { - //print_line("validate: "+cname+"::"+method.name); - } - - if (m && m->has_default_argument(i)) { - Variant default_arg = m->get_default_argument(i); - String default_arg_text = m->get_default_argument(i); - - switch (default_arg.get_type()) { - - case Variant::NIL: - default_arg_text = "NULL"; - break; - // atomic types - case Variant::BOOL: - if (bool(default_arg)) - default_arg_text = "true"; - else - default_arg_text = "false"; - break; - case Variant::INT: - case Variant::REAL: - //keep it - break; - case Variant::STRING: - case Variant::NODE_PATH: - default_arg_text = "\"" + default_arg_text + "\""; - break; - case Variant::TRANSFORM: - if (default_arg.operator Transform() == Transform()) { - default_arg_text = ""; - } - - default_arg_text = Variant::get_type_name(default_arg.get_type()) + "(" + default_arg_text + ")"; - break; - - case Variant::RECT3: - case Variant::COLOR: - case Variant::PLANE: - case Variant::POOL_BYTE_ARRAY: - case Variant::POOL_INT_ARRAY: - case Variant::POOL_REAL_ARRAY: - case Variant::POOL_STRING_ARRAY: - case Variant::POOL_VECTOR2_ARRAY: - case Variant::POOL_VECTOR3_ARRAY: - case Variant::POOL_COLOR_ARRAY: - default_arg_text = Variant::get_type_name(default_arg.get_type()) + "(" + default_arg_text + ")"; - break; - case Variant::VECTOR2: - case Variant::RECT2: - case Variant::VECTOR3: - case Variant::QUAT: - case Variant::BASIS: - default_arg_text = Variant::get_type_name(default_arg.get_type()) + default_arg_text; - break; - case Variant::OBJECT: - if (default_arg.is_zero()) { - default_arg_text = "NULL"; - break; - } - case Variant::DICTIONARY: // 20 - case Variant::ARRAY: - case Variant::_RID: - - default: {} - } - - argument.type = type_name; - argument.name = arginfo.name; - argument.default_value = default_arg_text; + argument.type = "Variant"; + } else if (arginfo.type == Variant::NIL) { + method.return_type = "void"; } else { - - argument.type = type_name; - argument.name = arginfo.name; + argument.type = Variant::get_type_name(arginfo.type); } - if (arginfo.type == Variant::OBJECT) { + argument.name = E->get().arguments[i].name; + int darg_idx = i - (E->get().arguments.size() - E->get().default_arguments.size()); - //print_line("validate: "+cname+"::"+method.name); + if (darg_idx >= 0) { + Variant default_arg = E->get().default_arguments[darg_idx]; + argument.default_value = default_arg.get_construct_string(); } method.arguments.push_back(argument); @@ -404,6 +369,7 @@ void DocData::generate(bool p_basic_types) { ConstantDoc constant; constant.name = E->get(); constant.value = itos(ClassDB::get_integer_constant(name, E->get())); + constant.enumeration = ClassDB::get_integer_constant_enum(name, E->get()); c.constants.push_back(constant); } @@ -565,6 +531,7 @@ void DocData::generate(bool p_basic_types) { ConstantDoc cd; cd.name = GlobalConstants::get_global_constant_name(i); cd.value = itos(GlobalConstants::get_global_constant_value(i)); + cd.enumeration = GlobalConstants::get_global_constant_enum(i); c.constants.push_back(cd); } @@ -680,6 +647,9 @@ static Error _parse_methods(Ref<XMLParser> &parser, Vector<DocData::MethodDoc> & argument.name = parser->get_attribute_value("name"); ERR_FAIL_COND_V(!parser->has_attribute("type"), ERR_FILE_CORRUPT); argument.type = parser->get_attribute_value("type"); + if (parser->has_attribute("enum")) { + argument.enumeration = parser->get_attribute_value("enum"); + } method.arguments.push_back(argument); @@ -803,7 +773,8 @@ Error DocData::_load(Ref<XMLParser> parser) { prop.getter = parser->get_attribute_value("getter"); if (parser->has_attribute("brief")) prop.brief_description = parser->get_attribute_value("brief").xml_unescape(); - + if (parser->has_attribute("enum")) + prop.enumeration = parser->get_attribute_value("enum"); parser->read(); if (parser->get_node_type() == XMLParser::NODE_TEXT) prop.description = parser->get_node_data().strip_edges(); @@ -861,6 +832,9 @@ Error DocData::_load(Ref<XMLParser> parser) { constant.name = parser->get_attribute_value("name"); ERR_FAIL_COND_V(!parser->has_attribute("value"), ERR_FILE_CORRUPT); constant.value = parser->get_attribute_value("value"); + if (parser->has_attribute("enum")) { + constant.enumeration = parser->get_attribute_value("enum"); + } parser->read(); if (parser->get_node_type() == XMLParser::NODE_TEXT) constant.description = parser->get_node_data().strip_edges(); @@ -955,10 +929,16 @@ Error DocData::save(const String &p_path) { for (int j = 0; j < m.arguments.size(); j++) { ArgumentDoc &a = m.arguments[j]; + + String enum_text; + if (a.enumeration != String()) { + enum_text = "enum=\"" + a.enumeration + "\""; + } + if (a.default_value != "") - _write_string(f, 3, "<argument index=\"" + itos(j) + "\" name=\"" + a.name.xml_escape() + "\" type=\"" + a.type.xml_escape() + "\" default=\"" + a.default_value.xml_escape(true) + "\">"); + _write_string(f, 3, "<argument index=\"" + itos(j) + "\" name=\"" + a.name.xml_escape() + "\" type=\"" + a.type.xml_escape() + "\" " + enum_text + " default=\"" + a.default_value.xml_escape(true) + "\">"); else - _write_string(f, 3, "<argument index=\"" + itos(j) + "\" name=\"" + a.name.xml_escape() + "\" type=\"" + a.type.xml_escape() + "\">"); + _write_string(f, 3, "<argument index=\"" + itos(j) + "\" name=\"" + a.name.xml_escape() + "\" type=\"" + a.type.xml_escape() + "\" " + enum_text + ">"); _write_string(f, 3, "</argument>"); } @@ -980,8 +960,12 @@ Error DocData::save(const String &p_path) { for (int i = 0; i < c.properties.size(); i++) { + String enum_text; + if (c.properties[i].enumeration != String()) { + enum_text = "enum=\"" + c.properties[i].enumeration + "\""; + } PropertyDoc &p = c.properties[i]; - _write_string(f, 2, "<member name=\"" + p.name + "\" type=\"" + p.type + "\" setter=\"" + p.setter + "\" getter=\"" + p.getter + "\" brief=\"" + p.brief_description.xml_escape(true) + "\">"); + _write_string(f, 2, "<member name=\"" + p.name + "\" type=\"" + p.type + "\" setter=\"" + p.setter + "\" getter=\"" + p.getter + "\" brief=\"" + p.brief_description.xml_escape(true) + "\" " + enum_text + " >"); if (p.description != "") _write_string(f, 3, p.description.xml_escape()); _write_string(f, 2, "</member>"); @@ -1021,7 +1005,11 @@ Error DocData::save(const String &p_path) { for (int i = 0; i < c.constants.size(); i++) { ConstantDoc &k = c.constants[i]; - _write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"" + k.value + "\">"); + if (k.enumeration != String()) { + _write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"" + k.value + "\">"); + } else { + _write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"" + k.value + "\" enum=\"" + k.enumeration + "\">"); + } if (k.description != "") _write_string(f, 3, k.description.xml_escape()); _write_string(f, 2, "</constant>"); diff --git a/editor/doc/doc_data.h b/editor/doc/doc_data.h index 41dfae428a..40141dd935 100644 --- a/editor/doc/doc_data.h +++ b/editor/doc/doc_data.h @@ -40,6 +40,7 @@ public: String name; String type; + String enumeration; String default_value; }; @@ -47,6 +48,7 @@ public: String name; String return_type; + String return_enum; String qualifiers; String description; Vector<ArgumentDoc> arguments; @@ -59,6 +61,7 @@ public: String name; String value; + String enumeration; String description; }; @@ -66,6 +69,7 @@ public: String name; String type; + String enumeration; String brief_description; String description; String setter, getter; diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 89d70ee926..86f31d7589 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -582,7 +582,18 @@ void EditorHelp::_class_list_select(const String &p_select) { void EditorHelp::_class_desc_select(const String &p_select) { //print_line("LINK: "+p_select); - if (p_select.begins_with("#")) { + if (p_select.begins_with("$")) { //enum + //_goto_desc(p_select.substr(1,p_select.length())); + String select = p_select.substr(1, p_select.length()); + String class_name; + if (select.find(".") != -1) { + class_name = select.get_slice(".", 0); + } else { + class_name = "@Global Scope"; + } + emit_signal("go_to_help", "class_enum:" + class_name + ":" + select); + return; + } else if (p_select.begins_with("#")) { //_goto_desc(p_select.substr(1,p_select.length())); emit_signal("go_to_help", "class_name:" + p_select.substr(1, p_select.length())); return; @@ -614,16 +625,28 @@ void EditorHelp::_class_desc_input(const Ref<InputEvent> &p_input) { set_focused(); } -void EditorHelp::_add_type(const String &p_type) { +void EditorHelp::_add_type(const String &p_type, const String &p_enum) { String t = p_type; if (t == "") t = "void"; - bool can_ref = (t != "int" && t != "real" && t != "bool" && t != "void"); + bool can_ref = (t != "int" && t != "real" && t != "bool" && t != "void") || p_enum != String(); + if (p_enum != String()) { + if (p_enum.get_slice_count(".") > 1) { + t = p_enum.get_slice(".", 1); + } else { + t = p_enum.get_slice(".", 0); + } + } class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/base_type_color")); - if (can_ref) - class_desc->push_meta("#" + t); //class + if (can_ref) { + if (p_enum == "") { + class_desc->push_meta("#" + t); //class + } else { + class_desc->push_meta("$" + p_enum); //class + } + } class_desc->add_text(t); if (can_ref) class_desc->pop(); @@ -782,7 +805,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { class_desc->push_cell(); class_desc->push_align(RichTextLabel::ALIGN_RIGHT); class_desc->push_font(doc_code_font); - _add_type(cd.properties[i].type); + _add_type(cd.properties[i].type, cd.properties[i].enumeration); class_desc->add_text(" "); class_desc->pop(); class_desc->pop(); @@ -875,7 +898,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { method_line[methods[i].name] = class_desc->get_line_count() - 2; //gets overridden if description class_desc->push_align(RichTextLabel::ALIGN_RIGHT); class_desc->push_font(doc_code_font); - _add_type(methods[i].return_type); + _add_type(methods[i].return_type, methods[i].return_enum); //class_desc->add_text(" "); class_desc->pop(); //align class_desc->pop(); //font @@ -899,7 +922,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color")); if (j > 0) class_desc->add_text(", "); - _add_type(methods[i].arguments[j].type); + _add_type(methods[i].arguments[j].type, methods[i].arguments[j].enumeration); class_desc->add_text(" "); _add_text(methods[i].arguments[j].name); if (methods[i].arguments[j].default_value != "") { @@ -1048,44 +1071,133 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { if (cd.constants.size()) { - class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color")); - class_desc->push_font(doc_title_font); - class_desc->add_text(TTR("Constants:")); - class_desc->pop(); - class_desc->pop(); - class_desc->push_indent(1); - - class_desc->add_newline(); - //class_desc->add_newline(); + Map<String, Vector<DocData::ConstantDoc> > enums; + Vector<DocData::ConstantDoc> constants; for (int i = 0; i < cd.constants.size(); i++) { - constant_line[cd.constants[i].name] = class_desc->get_line_count() - 2; - class_desc->push_font(doc_code_font); - class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/base_type_color")); - _add_text(cd.constants[i].name); + if (cd.constants[i].enumeration != String()) { + if (!enums.has(cd.constants[i].enumeration)) { + enums[cd.constants[i].enumeration] = Vector<DocData::ConstantDoc>(); + } + + enums[cd.constants[i].enumeration].push_back(cd.constants[i]); + } else { + + constants.push_back(cd.constants[i]); + } + } + + if (enums.size()) { + + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color")); + class_desc->push_font(doc_title_font); + class_desc->add_text(TTR("Enumerations:")); class_desc->pop(); - class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color")); - class_desc->add_text(" = "); class_desc->pop(); + class_desc->push_indent(1); + + class_desc->add_newline(); + //class_desc->add_newline(); + + for (Map<String, Vector<DocData::ConstantDoc> >::Element *E = enums.front(); E; E = E->next()) { + + enum_line[E->key()] = class_desc->get_line_count() - 2; + + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color")); + class_desc->add_text(TTR("enum ")); + class_desc->pop(); + class_desc->push_font(doc_code_font); + String e = E->key(); + if (e.get_slice_count(".")) { + e = e.get_slice(".", 1); + } + + class_desc->add_text(e); + class_desc->pop(); + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color")); + class_desc->add_text(":"); + class_desc->pop(); + class_desc->add_newline(); + + class_desc->push_indent(1); + Vector<DocData::ConstantDoc> enum_list = E->get(); + + for (int i = 0; i < enum_list.size(); i++) { + + class_desc->push_font(doc_code_font); + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/base_type_color")); + _add_text(enum_list[i].name); + class_desc->pop(); + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color")); + class_desc->add_text(" = "); + class_desc->pop(); + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color")); + _add_text(enum_list[i].value); + class_desc->pop(); + class_desc->pop(); + if (enum_list[i].description != "") { + class_desc->push_font(doc_font); + class_desc->add_text(" "); + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color")); + _add_text(enum_list[i].description); + class_desc->pop(); + class_desc->pop(); + } + + class_desc->add_newline(); + } + + class_desc->pop(); + + class_desc->add_newline(); + } + + class_desc->pop(); + class_desc->add_newline(); + } + + if (constants.size()) { + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color")); - _add_text(cd.constants[i].value); + class_desc->push_font(doc_title_font); + class_desc->add_text(TTR("Constants:")); class_desc->pop(); class_desc->pop(); - if (cd.constants[i].description != "") { - class_desc->push_font(doc_font); - class_desc->add_text(" "); - class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color")); - _add_text(cd.constants[i].description); + class_desc->push_indent(1); + + class_desc->add_newline(); + //class_desc->add_newline(); + + for (int i = 0; i < constants.size(); i++) { + + constant_line[constants[i].name] = class_desc->get_line_count() - 2; + class_desc->push_font(doc_code_font); + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/base_type_color")); + _add_text(constants[i].name); + class_desc->pop(); + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color")); + class_desc->add_text(" = "); + class_desc->pop(); + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color")); + _add_text(constants[i].value); class_desc->pop(); class_desc->pop(); + if (constants[i].description != "") { + class_desc->push_font(doc_font); + class_desc->add_text(" "); + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color")); + _add_text(constants[i].description); + class_desc->pop(); + class_desc->pop(); + } + + class_desc->add_newline(); } + class_desc->pop(); class_desc->add_newline(); } - - class_desc->pop(); - class_desc->add_newline(); } if (cd.description != "") { @@ -1126,7 +1238,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { method_line[cd.properties[i].name] = class_desc->get_line_count() - 2; class_desc->push_font(doc_code_font); - _add_type(cd.properties[i].type); + _add_type(cd.properties[i].type, cd.properties[i].enumeration); class_desc->add_text(" "); class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color")); @@ -1204,7 +1316,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { method_line[methods[i].name] = class_desc->get_line_count() - 2; class_desc->push_font(doc_code_font); - _add_type(methods[i].return_type); + _add_type(methods[i].return_type, methods[i].return_enum); class_desc->add_text(" "); class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color")); @@ -1217,7 +1329,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color")); if (j > 0) class_desc->add_text(", "); - _add_type(methods[i].arguments[j].type); + _add_type(methods[i].arguments[j].type, methods[i].arguments[j].enumeration); class_desc->add_text(" "); _add_text(methods[i].arguments[j].name); if (methods[i].arguments[j].default_value != "") { @@ -1295,6 +1407,11 @@ void EditorHelp::_help_callback(const String &p_topic) { if (property_line.has(name)) line = property_line[name]; + } else if (what == "class_enum") { + + print_line("go to enum:"); + if (enum_line.has(name)) + line = enum_line[name]; } else if (what == "class_theme_item") { if (theme_property_line.has(name)) @@ -1743,8 +1860,20 @@ void EditorHelpBit::_go_to_help(String p_what) { void EditorHelpBit::_meta_clicked(String p_select) { + print_line("got meta " + p_select); //print_line("LINK: "+p_select); - if (p_select.begins_with("#")) { + if (p_select.begins_with("$")) { //enum + //_goto_desc(p_select.substr(1,p_select.length())); + String select = p_select.substr(1, p_select.length()); + String class_name; + if (select.find(".") != -1) { + class_name = select.get_slice(".", 0); + } else { + class_name = "@Global"; + } + _go_to_help("class_enum:" + class_name + ":" + select); + return; + } else if (p_select.begins_with("#")) { //_goto_desc(p_select.substr(1,p_select.length())); _go_to_help("class_name:" + p_select.substr(1, p_select.length())); return; diff --git a/editor/editor_help.h b/editor/editor_help.h index 6d9be3db6f..db97ab9b28 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -123,6 +123,7 @@ class EditorHelp : public VBoxContainer { Map<String, int> property_line; Map<String, int> theme_property_line; Map<String, int> constant_line; + Map<String, int> enum_line; int description_line; RichTextLabel *class_desc; @@ -141,7 +142,7 @@ class EditorHelp : public VBoxContainer { bool scroll_locked; //void _button_pressed(int p_idx); - void _add_type(const String &p_type); + void _add_type(const String &p_type, const String &p_enum = String()); void _class_list_select(const String &p_select); void _class_desc_select(const String &p_select); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 798f57f8c3..b6f17b7121 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -1287,7 +1287,6 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p Ref<EditorScenePostImport> post_import_script; if (post_import_script_path != "") { - post_import_script_path = post_import_script_path; // FIXME: is there a good reason for this? Ref<Script> scr = ResourceLoader::load(post_import_script_path); if (!scr.is_valid()) { EditorNode::add_io_error(TTR("Couldn't load post-import script:") + " " + post_import_script_path); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index e69fa6da88..e86ff8cac2 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -602,13 +602,13 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo } } -void ScriptTextEditor::_code_complete_scripts(void *p_ud, const String &p_code, List<String> *r_options) { +void ScriptTextEditor::_code_complete_scripts(void *p_ud, const String &p_code, List<String> *r_options, bool &r_force) { ScriptTextEditor *ste = (ScriptTextEditor *)p_ud; - ste->_code_complete_script(p_code, r_options); + ste->_code_complete_script(p_code, r_options, r_force); } -void ScriptTextEditor::_code_complete_script(const String &p_code, List<String> *r_options) { +void ScriptTextEditor::_code_complete_script(const String &p_code, List<String> *r_options, bool &r_force) { if (color_panel->is_visible_in_tree()) return; Node *base = get_tree()->get_edited_scene_root(); @@ -616,7 +616,7 @@ void ScriptTextEditor::_code_complete_script(const String &p_code, List<String> base = _find_node_for_script(base, base, script); } String hint; - Error err = script->get_language()->complete_code(p_code, script->get_path().get_base_dir(), base, r_options, hint); + Error err = script->get_language()->complete_code(p_code, script->get_path().get_base_dir(), base, r_options, r_force, hint); if (hint != "") { code_editor->get_text_edit()->set_code_hint(hint); } diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index c505976223..561fa26c76 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -94,12 +94,12 @@ class ScriptTextEditor : public ScriptEditorBase { }; protected: - static void _code_complete_scripts(void *p_ud, const String &p_code, List<String> *r_options); + static void _code_complete_scripts(void *p_ud, const String &p_code, List<String> *r_options, bool &r_force); void _breakpoint_toggled(int p_row); //no longer virtual void _validate_script(); - void _code_complete_script(const String &p_code, List<String> *r_options); + void _code_complete_script(const String &p_code, List<String> *r_options, bool &r_force); void _load_theme_settings(); void _notification(int p_what); diff --git a/modules/gdnative/config.py b/modules/gdnative/config.py index 9f57b9bb74..4f89ca0d4c 100644 --- a/modules/gdnative/config.py +++ b/modules/gdnative/config.py @@ -1,7 +1,7 @@ def can_build(platform): - return True + return False def configure(env): diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index 3fa0a38024..d6969c142d 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -30,6 +30,7 @@ #include "editor/editor_settings.h" #include "gd_compiler.h" #include "gd_script.h" +#include "global_constants.h" #include "os/file_access.h" #include "project_settings.h" #ifdef TOOLS_ENABLED @@ -355,6 +356,7 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na struct GDCompletionIdentifier { + String enumeration; StringName obj_type; Ref<GDScript> script; Variant::Type type; @@ -608,7 +610,7 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser: #ifdef TOOLS_ENABLED MethodBind *mb = ClassDB::get_method(base.obj_type, id); - PropertyInfo pi = mb->get_argument_info(-1); + PropertyInfo pi = mb->get_return_info(); //try calling the function if constant and all args are constant, should not crash.. Object *baseptr = base.value; @@ -809,6 +811,32 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser: if (p1.value.get_type() == Variant::OBJECT) { //?? + if (p1.obj_type != StringName() && p2.type == Variant::STRING) { + StringName index = p2.value; + bool valid; + Variant::Type t = ClassDB::get_property_type(p1.obj_type, index, &valid); + if (t != Variant::NIL && valid) { + r_type.type = t; + if (t == Variant::INT) { +//check for enum! +#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED) + + StringName getter = ClassDB::get_property_getter(p1.obj_type, index); + if (getter != StringName()) { + MethodBind *mb = ClassDB::get_method(p1.obj_type, getter); + if (mb) { + PropertyInfo rt = mb->get_return_info(); + if (rt.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + r_type.enumeration = rt.class_name; + } + } + } +#endif + } + + return true; + } + } } else if (p1.value.get_type() != Variant::NIL) { bool valid; @@ -908,6 +936,22 @@ static bool _guess_identifier_type_in_block(GDCompletionContext &context, int p_ Variant::Type t = ClassDB::get_property_type(gdi.obj_type, p_identifier, &valid); if (t != Variant::NIL && valid) { r_type.type = t; + if (t == Variant::INT) { +//check for enum! +#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED) + + StringName getter = ClassDB::get_property_getter(gdi.obj_type, p_identifier); + if (getter != StringName()) { + MethodBind *mb = ClassDB::get_method(gdi.obj_type, getter); + if (mb) { + PropertyInfo rt = mb->get_return_info(); + if (rt.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + r_type.enumeration = rt.class_name; + } + } + } +#endif + } return true; } } @@ -1041,11 +1085,11 @@ static bool _guess_identifier_type(GDCompletionContext &context, int p_line, con PropertyInfo arg = E->get().arguments[argindex]; - int scp = arg.name.find(":"); + int scp = String(arg.name).find(":"); if (scp != -1) { r_type.type = Variant::OBJECT; - r_type.obj_type = arg.name.substr(scp + 1, arg.name.length()); + r_type.obj_type = String(arg.name).substr(scp + 1, String(arg.name).length()); return true; } else { @@ -1271,7 +1315,7 @@ static void _find_identifiers_in_class(GDCompletionContext &context, bool p_stat for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { if (E->get().usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_CATEGORY)) continue; - if (E->get().name.find("/") != -1) + if (String(E->get().name).find("/") != -1) continue; result.insert(E->get().name); } @@ -1436,7 +1480,7 @@ void get_directory_contents(EditorFileSystemDirectory *p_dir, Set<String> &r_lis } } -static void _find_type_arguments(GDCompletionContext &context, const GDParser::Node *p_node, int p_line, const StringName &p_method, const GDCompletionIdentifier &id, int p_argidx, Set<String> &result, String &arghint) { +static void _find_type_arguments(GDCompletionContext &context, const GDParser::Node *p_node, int p_line, const StringName &p_method, const GDCompletionIdentifier &id, int p_argidx, Set<String> &result, bool &r_forced, String &arghint) { //print_line("find type arguments?"); if (id.type == Variant::OBJECT && id.obj_type != StringName()) { @@ -1642,8 +1686,43 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N } } else { - //regular method +//regular method + +#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED) + if (p_argidx < m->get_argument_count()) { + PropertyInfo pi = m->get_argument_info(p_argidx); + + if (pi.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + String enumeration = pi.class_name; + if (enumeration.find(".") != -1) { + //class constant + List<StringName> constants; + String cls = enumeration.get_slice(".", 0); + String enm = enumeration.get_slice(".", 1); + + ClassDB::get_enum_constants(cls, enm, &constants); + //constants.sort_custom<StringName::AlphCompare>(); + for (List<StringName>::Element *E = constants.front(); E; E = E->next()) { + String add = cls + "." + E->get(); + result.insert(add); + r_forced = true; + } + } else { + //global constant + StringName current_enum = enumeration; + + for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) { + if (GlobalConstants::get_global_constant_enum(i) == current_enum) { + result.insert(GlobalConstants::get_global_constant_name(i)); + r_forced = true; + } + } + //global + } + } + } +#endif if (p_method.operator String() == "connect" || (p_method.operator String() == "emit_signal" && p_argidx == 0)) { if (p_argidx == 0) { @@ -1664,6 +1743,7 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N for (List<MethodInfo>::Element *E = sigs.front(); E; E = E->next()) { result.insert("\"" + E->get().name + "\""); + r_forced = true; } } else if (p_argidx == 2) { @@ -1671,6 +1751,7 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N if (context._class) { for (int i = 0; i < context._class->functions.size(); i++) { result.insert("\"" + context._class->functions[i]->name + "\""); + r_forced = true; } } } @@ -1696,6 +1777,7 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N //print_line("found "+s); String name = s.get_slice("/", 1); result.insert("\"/root/" + name + "\""); + r_forced = true; } } @@ -1707,11 +1789,12 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N for (List<String>::Element *E = options.front(); E; E = E->next()) { result.insert(E->get()); + r_forced = true; } } } - arghint = _get_visual_datatype(m->get_argument_info(-1), false) + " " + p_method.operator String() + String("("); + arghint = _get_visual_datatype(m->get_return_info(), false) + " " + p_method.operator String() + String("("); for (int i = 0; i < m->get_argument_count(); i++) { if (i > 0) @@ -1750,7 +1833,7 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N } } -static void _find_call_arguments(GDCompletionContext &context, const GDParser::Node *p_node, int p_line, int p_argidx, Set<String> &result, String &arghint) { +static void _find_call_arguments(GDCompletionContext &context, const GDParser::Node *p_node, int p_line, int p_argidx, Set<String> &result, bool &r_forced, String &arghint) { if (!p_node || p_node->type != GDParser::Node::TYPE_OPERATOR) { @@ -1905,7 +1988,7 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N if (!context._class->owner) ci.value = context.base; - _find_type_arguments(context, p_node, p_line, id->name, ci, p_argidx, result, arghint); + _find_type_arguments(context, p_node, p_line, id->name, ci, p_argidx, result, r_forced, arghint); //guess type.. /* List<MethodInfo> methods; @@ -1927,7 +2010,7 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N GDCompletionIdentifier ci; if (_guess_expression_type(context, op->arguments[0], p_line, ci)) { - _find_type_arguments(context, p_node, p_line, id->name, ci, p_argidx, result, arghint); + _find_type_arguments(context, p_node, p_line, id->name, ci, p_argidx, result, r_forced, arghint); return; } } @@ -2027,14 +2110,14 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N #endif } -Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint) { +Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) { GDParser p; p.parse(p_code, p_base_path, false, "", true); bool isfunction = false; Set<String> options; - + r_forced = false; GDCompletionContext context; context._class = p.get_completion_class(); context.block = p.get_completion_block(); @@ -2073,6 +2156,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base String opt = E->get().strip_edges(); if (opt.begins_with("\"") && opt.ends_with("\"")) { + r_forced = true; String idopt = opt.substr(1, opt.length() - 2); if (idopt.replace("/", "_").is_valid_identifier()) { options.insert(idopt); @@ -2111,7 +2195,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { if (E->get().usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_CATEGORY)) continue; - if (E->get().name.find("/") != -1) + if (String(E->get().name).find("/") != -1) continue; options.insert(E->get().name); } @@ -2245,7 +2329,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { if (E->get().usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_CATEGORY)) continue; - if (E->get().name.find("/") != -1) + if (String(E->get().name).find("/") != -1) continue; r_options->push_back(E->get().name); } @@ -2277,7 +2361,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base t.value.get_property_list(&pl); for (List<PropertyInfo>::Element *E = pl.front(); E; E = E->next()) { - if (E->get().name.find("/") == -1) + if (String(E->get().name).find("/") == -1) options.insert(E->get().name); } } @@ -2297,7 +2381,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base } break; case GDParser::COMPLETION_CALL_ARGUMENTS: { - _find_call_arguments(context, p.get_completion_node(), p.get_completion_line(), p.get_completion_argument_index(), options, r_call_hint); + _find_call_arguments(context, p.get_completion_node(), p.get_completion_line(), p.get_completion_argument_index(), options, r_forced, r_call_hint); } break; case GDParser::COMPLETION_VIRTUAL_FUNC: { @@ -2344,6 +2428,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base ClassDB::get_signal_list(t.obj_type, &sigs); for (List<MethodInfo>::Element *E = sigs.front(); E; E = E->next()) { options.insert("\"" + E->get().name + "\""); + r_forced = true; } } @@ -2353,6 +2438,42 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base if (EditorSettings::get_singleton()->get("text_editor/completion/complete_file_paths")) get_directory_contents(EditorFileSystem::get_singleton()->get_filesystem(), options); } break; + case GDParser::COMPLETION_ASSIGN: { +#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED) + + GDCompletionIdentifier ci; + if (_guess_expression_type(context, p.get_completion_node(), p.get_completion_line(), ci)) { + + String enumeration = ci.enumeration; + if (enumeration.find(".") != -1) { + //class constant + List<StringName> constants; + String cls = enumeration.get_slice(".", 0); + String enm = enumeration.get_slice(".", 1); + + ClassDB::get_enum_constants(cls, enm, &constants); + //constants.sort_custom<StringName::AlphCompare>(); + for (List<StringName>::Element *E = constants.front(); E; E = E->next()) { + String add = cls + "." + E->get(); + r_options->push_back(add); + r_forced = true; + } + } else { + + //global constant + StringName current_enum = enumeration; + + for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) { + if (GlobalConstants::get_global_constant_enum(i) == current_enum) { + r_options->push_back(GlobalConstants::get_global_constant_name(i)); + r_forced = true; + } + } + //global + } + } +#endif + } break; } for (Set<String>::Element *E = options.front(); E; E = E->next()) { diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index b349b6b9a8..de8daedb8b 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -1044,6 +1044,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool return NULL; \ } \ p_allow_assign = false; + switch (tokenizer->get_token()) { //see operator case GDTokenizer::TK_OP_IN: op = OperatorNode::OP_IN; break; @@ -1065,7 +1066,22 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool //case GDTokenizer::TK_OP_NEG: op=OperatorNode::OP_NEG ; break; case GDTokenizer::TK_OP_SHIFT_LEFT: op = OperatorNode::OP_SHIFT_LEFT; break; case GDTokenizer::TK_OP_SHIFT_RIGHT: op = OperatorNode::OP_SHIFT_RIGHT; break; - case GDTokenizer::TK_OP_ASSIGN: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN; break; + case GDTokenizer::TK_OP_ASSIGN: { + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN; + + if (tokenizer->get_token(1) == GDTokenizer::TK_CURSOR) { + //code complete assignment + completion_type = COMPLETION_ASSIGN; + completion_node = expr; + completion_class = current_class; + completion_function = current_function; + completion_line = tokenizer->get_token_line(); + completion_block = current_block; + completion_found = true; + tokenizer->advance(); + } + + } break; case GDTokenizer::TK_OP_ASSIGN_ADD: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_ADD; break; case GDTokenizer::TK_OP_ASSIGN_SUB: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SUB; break; case GDTokenizer::TK_OP_ASSIGN_MUL: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MUL; break; diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h index 3ad3466624..8ad494cd39 100644 --- a/modules/gdscript/gd_parser.h +++ b/modules/gdscript/gd_parser.h @@ -441,6 +441,7 @@ public: COMPLETION_INDEX, COMPLETION_VIRTUAL_FUNC, COMPLETION_YIELD, + COMPLETION_ASSIGN, }; private: diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h index 17e7b0bc03..441f87474e 100644 --- a/modules/gdscript/gd_script.h +++ b/modules/gdscript/gd_script.h @@ -390,7 +390,7 @@ public: virtual int find_function(const String &p_function, const String &p_code) const; virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const; virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return OK; } - virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint); + virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint); #ifdef TOOLS_ENABLED virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result); #endif diff --git a/modules/nativescript/config.py b/modules/nativescript/config.py index 9f57b9bb74..4f89ca0d4c 100644 --- a/modules/nativescript/config.py +++ b/modules/nativescript/config.py @@ -1,7 +1,7 @@ def can_build(platform): - return True + return False def configure(env): diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 245e7e04be..2c50b4e854 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -4319,6 +4319,7 @@ void TextEdit::_cancel_completion() { return; completion_active = false; + completion_forced = false; update(); } @@ -4386,13 +4387,19 @@ void TextEdit::_update_completion_candidates() { } } - if (cursor.column > 0 && l[cursor.column - 1] == '(' && !pre_keyword && !completion_strings[0].begins_with("\"")) { + if (cursor.column > 0 && l[cursor.column - 1] == '(' && !pre_keyword && !completion_forced) { cancel = true; } update(); - if (cancel || (!pre_keyword && s == "" && (cofs == 0 || !completion_prefixes.has(String::chr(l[cofs - 1]))))) { + bool prev_is_prefix = false; + if (cofs > 0 && completion_prefixes.has(String::chr(l[cofs - 1]))) + prev_is_prefix = true; + if (cofs > 1 && l[cofs - 1] == ' ' && completion_prefixes.has(String::chr(l[cofs - 2]))) //check with one space before prefix, to allow indent + prev_is_prefix = true; + + if (cancel || (!pre_keyword && s == "" && (cofs == 0 || !prev_is_prefix))) { //none to complete, cancel _cancel_completion(); return; @@ -4481,6 +4488,8 @@ void TextEdit::query_code_comple() { if (ofs > 0 && (inquote || _is_completable(l[ofs - 1]) || completion_prefixes.has(String::chr(l[ofs - 1])))) emit_signal("request_completion"); + else if (ofs > 1 && l[ofs - 1] == ' ' && completion_prefixes.has(String::chr(l[ofs - 2]))) //make it work with a space too, it's good enough + emit_signal("request_completion"); } void TextEdit::set_code_hint(const String &p_hint) { @@ -4492,12 +4501,13 @@ void TextEdit::set_code_hint(const String &p_hint) { update(); } -void TextEdit::code_complete(const Vector<String> &p_strings) { +void TextEdit::code_complete(const Vector<String> &p_strings, bool p_forced) { VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); raised_from_completion = true; completion_strings = p_strings; completion_active = true; + completion_forced = p_forced; completion_current = ""; completion_index = 0; _update_completion_candidates(); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 6321cad2da..7ab26322e7 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -205,6 +205,7 @@ class TextEdit : public Control { Vector<String> completion_strings; Vector<String> completion_options; bool completion_active; + bool completion_forced; String completion_current; String completion_base; int completion_index; @@ -522,7 +523,7 @@ public: void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata); void set_completion(bool p_enabled, const Vector<String> &p_prefixes); - void code_complete(const Vector<String> &p_strings); + void code_complete(const Vector<String> &p_strings, bool p_forced = false); void set_code_hint(const String &p_hint); void query_code_comple(); |