diff options
30 files changed, 325 insertions, 107 deletions
diff --git a/core/class_db.cpp b/core/class_db.cpp index c9527e3c8f..34bc83c89a 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -545,6 +545,11 @@ bool ClassDB::can_instance(const StringName &p_class) { ClassInfo *ti = classes.getptr(p_class); ERR_FAIL_COND_V(!ti, false); +#ifdef TOOLS_ENABLED + if (ti->api == API_EDITOR && !Engine::get_singleton()->is_editor_hint()) { + return false; + } +#endif return (!ti->disabled && ti->creation_func != NULL); } @@ -980,6 +985,13 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons type->property_setget[p_pinfo.name] = psg; } +void ClassDB::set_property_default_value(StringName p_class, const StringName &p_name, const Variant &p_default) { + if (!default_values.has(p_class)) { + default_values[p_class] = HashMap<StringName, Variant>(); + } + default_values[p_class][p_name] = p_default; +} + void ClassDB::get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator) { OBJTYPE_RLOCK; @@ -1383,27 +1395,47 @@ void ClassDB::get_extensions_for_type(const StringName &p_class, List<String> *p } HashMap<StringName, HashMap<StringName, Variant> > ClassDB::default_values; +Set<StringName> ClassDB::default_values_cached; Variant ClassDB::class_get_default_property_value(const StringName &p_class, const StringName &p_property) { - if (!default_values.has(p_class)) { + if (!default_values_cached.has(p_class)) { - default_values[p_class] = HashMap<StringName, Variant>(); + if (!default_values.has(p_class)) { + default_values[p_class] = HashMap<StringName, Variant>(); + } - if (ClassDB::can_instance(p_class)) { + Object *c = NULL; + bool cleanup_c = false; + + if (Engine::get_singleton()->has_singleton(p_class)) { + c = Engine::get_singleton()->get_singleton_object(p_class); + cleanup_c = false; + } else if (ClassDB::can_instance(p_class)) { + c = ClassDB::instance(p_class); + cleanup_c = true; + } + + if (c) { - Object *c = ClassDB::instance(p_class); List<PropertyInfo> plist; c->get_property_list(&plist); for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { if (E->get().usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR)) { - Variant v = c->get(E->get().name); - default_values[p_class][E->get().name] = v; + if (!default_values[p_class].has(E->get().name)) { + Variant v = c->get(E->get().name); + default_values[p_class][E->get().name] = v; + } } } - memdelete(c); + + if (cleanup_c) { + memdelete(c); + } } + + default_values_cached.insert(p_class); } if (!default_values.has(p_class)) { @@ -1424,6 +1456,12 @@ void ClassDB::init() { lock = RWLock::create(); } +void ClassDB::cleanup_defaults() { + + default_values.clear(); + default_values_cached.clear(); +} + void ClassDB::cleanup() { //OBJTYPE_LOCK; hah not here @@ -1443,7 +1481,6 @@ void ClassDB::cleanup() { classes.clear(); resource_base_extensions.clear(); compat_classes.clear(); - default_values.clear(); memdelete(lock); } diff --git a/core/class_db.h b/core/class_db.h index efa1a46866..8adbc9ba98 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -162,6 +162,7 @@ public: static void _add_class2(const StringName &p_class, const StringName &p_inherits); static HashMap<StringName, HashMap<StringName, Variant> > default_values; + static Set<StringName> default_values_cached; public: // DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!! @@ -329,6 +330,7 @@ public: static void add_property_group(StringName p_class, const String &p_name, const String &p_prefix = ""); static void add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1); + static void set_property_default_value(StringName p_class, const StringName &p_name, const Variant &p_default); static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = NULL); static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = NULL); static bool get_property(Object *p_object, const StringName &p_property, Variant &r_value); @@ -373,6 +375,7 @@ public: static void set_current_api(APIType p_api); static APIType get_current_api(); + static void cleanup_defaults(); static void cleanup(); }; diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 2779837190..33dc4dbde4 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -874,6 +874,7 @@ void MultiplayerAPI::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer"); + ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false); ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id"))); diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 7ce3824505..b61119d8df 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -216,6 +216,8 @@ int AStar::get_closest_point(const Vector3 &p_point) const { for (const Map<int, Point *>::Element *E = points.front(); E; E = E->next()) { + if (!E->get()->enabled) + continue; //Disabled points should not be considered real_t d = p_point.distance_squared_to(E->get()->pos); if (closest_id < 0 || d < closest_dist) { closest_dist = d; @@ -234,6 +236,10 @@ Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const { for (const Set<Segment>::Element *E = segments.front(); E; E = E->next()) { + if (!(E->get().from_point->enabled && E->get().to_point->enabled)) { + continue; + } + Vector3 segment[2] = { E->get().from_point->pos, E->get().to_point->pos, diff --git a/core/object.h b/core/object.h index 4394c1c3da..1e0b22c086 100644 --- a/core/object.h +++ b/core/object.h @@ -130,6 +130,7 @@ enum PropertyUsageFlags { #define ADD_SIGNAL(m_signal) ClassDB::add_signal(get_class_static(), m_signal) #define ADD_PROPERTY(m_property, m_setter, m_getter) ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter)) #define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter), m_index) +#define ADD_PROPERTY_DEFAULT(m_property, m_default) ClassDB::set_property_default_value(get_class_static(), m_property, m_default) #define ADD_GROUP(m_name, m_prefix) ClassDB::add_property_group(get_class_static(), m_name, m_prefix) struct PropertyInfo { diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 135df4e5bd..af863dd385 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -273,6 +273,7 @@ void unregister_core_types() { ResourceLoader::finalize(); + ClassDB::cleanup_defaults(); ObjectDB::cleanup(); unregister_variant_methods(); diff --git a/doc/classes/ConfigFile.xml b/doc/classes/ConfigFile.xml index 5b8f0c32d1..775ad4c922 100644 --- a/doc/classes/ConfigFile.xml +++ b/doc/classes/ConfigFile.xml @@ -97,6 +97,26 @@ Loads the config file specified as a parameter. The file's contents are parsed and loaded in the ConfigFile object which the method was called on. Returns one of the [constant OK], [constant FAILED] or [code]ERR_*[/code] constants listed in [@GlobalScope]. If the load was successful, the return value is [constant OK]. </description> </method> + <method name="load_encrypted"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="key" type="PoolByteArray"> + </argument> + <description> + </description> + </method> + <method name="load_encrypted_pass"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="pass" type="String"> + </argument> + <description> + </description> + </method> <method name="save"> <return type="int" enum="Error"> </return> @@ -106,6 +126,26 @@ Saves the contents of the ConfigFile object to the file specified as a parameter. The output file uses an INI-style structure. Returns one of the [constant OK], [constant FAILED] or [code]ERR_*[/code] constants listed in [@GlobalScope]. If the load was successful, the return value is [constant OK]. </description> </method> + <method name="save_encrypted"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="key" type="PoolByteArray"> + </argument> + <description> + </description> + </method> + <method name="save_encrypted_pass"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="pass" type="String"> + </argument> + <description> + </description> + </method> <method name="set_value"> <return type="void"> </return> diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index b39b8e9f48..f6cb4ca4d9 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -198,6 +198,17 @@ Signal sent at the end of a GraphNode movement. </description> </signal> + <signal name="connection_from_empty"> + <argument index="0" name="to" type="String"> + </argument> + <argument index="1" name="to_slot" type="int"> + </argument> + <argument index="2" name="release_position" type="Vector2"> + </argument> + <description> + Signal sent when user dragging connection from input port into empty space of the graph. + </description> + </signal> <signal name="connection_request"> <argument index="0" name="from" type="String"> </argument> @@ -211,17 +222,6 @@ Signal sent to the GraphEdit when the connection between the [code]from_slot[/code] slot of the [code]from[/code] GraphNode and the [code]to_slot[/code] slot of the [code]to[/code] GraphNode is attempted to be created. </description> </signal> - <signal name="connection_from_empty"> - <argument index="0" name="to" type="String"> - </argument> - <argument index="1" name="to_slot" type="int"> - </argument> - <argument index="2" name="release_position" type="Vector2"> - </argument> - <description> - Signal sent when user dragging connection from input port into empty space of the graph. - </description> - </signal> <signal name="connection_to_empty"> <argument index="0" name="from" type="String"> </argument> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 5956d7a364..d9df2a50c6 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -85,6 +85,7 @@ Called when the node is "ready", i.e. when both the node and its children have entered the scene tree. If the node has children, their [method _ready] callbacks get triggered first, and the parent node will receive the ready notification afterwards. Corresponds to the [constant NOTIFICATION_READY] notification in [method Object._notification]. See also the [code]onready[/code] keyword for variables. Usually used for initialization. For even earlier initialization, [method Object._init] may be used. See also [method _enter_tree]. + [b]Note:[/b] [method _ready] may be called only once for each node. After removing a node from the scene tree and adding again, [code]_ready[/code] will not be called for the second time. This can be bypassed with requesting another call with [method request_ready], which may be called anywhere before adding the node again. </description> </method> <method name="_unhandled_input" qualifiers="virtual"> @@ -595,7 +596,7 @@ <return type="void"> </return> <description> - Requests that [code]_ready[/code] be called again. + Requests that [code]_ready[/code] be called again. Note that the method won't be called immediately, but is scheduled for when the node is added to the scene tree again (see [method _ready]). [code]_ready[/code] is called only for the node which requested it, which means that you need to request ready for each child if you want them to call [code]_ready[/code] too (in which case, [code]_ready[/code] will be called in the same order as it would normally). </description> </method> <method name="rpc" qualifiers="vararg"> diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml index 8e2e2f1baa..3388af2dd0 100644 --- a/doc/classes/SpinBox.xml +++ b/doc/classes/SpinBox.xml @@ -5,6 +5,16 @@ </brief_description> <description> SpinBox is a numerical input text field. It allows entering integers and floats. + [b]Example:[/b] + [codeblock] + var spin_box = SpinBox.new() + add_child(spin_box) + var line_edit = spin_box.get_line_edit() + line_edit.context_menu_enabled = false + spin_box.align = LineEdit.ALIGN_RIGHT + [/codeblock] + The above code will create a [SpinBox], disable context menu on it and set the text alignment to right. + See [Range] class for more options over the [SpinBox]. </description> <tutorials> </tutorials> @@ -13,23 +23,29 @@ <return type="LineEdit"> </return> <description> + Returns the [LineEdit] instance from this [SpinBox]. You can use it to access properties and methods of [LineEdit]. </description> </method> </methods> <members> <member name="align" type="int" setter="set_align" getter="get_align" enum="LineEdit.Align"> + Sets the text alignment of the [SpinBox]. </member> <member name="editable" type="bool" setter="set_editable" getter="is_editable"> + If [code]true[/code], the [SpinBox] will be editable. Otherwise, it will be read only. </member> <member name="prefix" type="String" setter="set_prefix" getter="get_prefix"> + Adds the specified [code]prefix[/code] string before the numerical value of the [SpinBox]. </member> <member name="suffix" type="String" setter="set_suffix" getter="get_suffix"> + Adds the specified [code]prefix[/code] string after the numerical value of the [SpinBox]. </member> </members> <constants> </constants> <theme_items> <theme_item name="updown" type="Texture"> + Sets a custom [Texture] for up and down arrows of the [SpinBox]. </theme_item> </theme_items> </class> diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py index 454c71d3c7..763c29ab4e 100755 --- a/doc/tools/makerst.py +++ b/doc/tools/makerst.py @@ -37,12 +37,13 @@ class TypeName: class PropertyDef: - def __init__(self, name, type_name, setter, getter, text): # type: (str, TypeName, Optional[str], Optional[str], Optional[str]) -> None + def __init__(self, name, type_name, setter, getter, text, default_value): # type: (str, TypeName, Optional[str], Optional[str], Optional[str], Optional[str]) -> None self.name = name self.type_name = type_name self.setter = setter self.getter = getter self.text = text + self.default_value = default_value class ParameterDef: def __init__(self, name, type_name, default_value): # type: (str, TypeName, Optional[str]) -> None @@ -81,9 +82,10 @@ class EnumDef: class ThemeItemDef: - def __init__(self, name, type_name): # type: (str, TypeName) -> None + def __init__(self, name, type_name, default_value): # type: (str, TypeName, Optional[str]) -> None self.name = name self.type_name = type_name + self.default_value = default_value class ClassDef: @@ -144,8 +146,9 @@ class State: type_name = TypeName.from_element(property) setter = property.get("setter") or None # Use or None so '' gets turned into None. getter = property.get("getter") or None + default_value = property.get("default") or None - property_def = PropertyDef(property_name, type_name, setter, getter, property.text) + property_def = PropertyDef(property_name, type_name, setter, getter, property.text, default_value) class_def.properties[property_name] = property_def methods = class_root.find("methods") @@ -230,7 +233,8 @@ class State: assert theme_item.tag == "theme_item" theme_item_name = theme_item.attrib["name"] - theme_item_def = ThemeItemDef(theme_item_name, TypeName.from_element(theme_item)) + default_value = theme_item.get("default") or None + theme_item_def = ThemeItemDef(theme_item_name, TypeName.from_element(theme_item), default_value) if theme_item_name not in class_def.theme_items: class_def.theme_items[theme_item_name] = [] class_def.theme_items[theme_item_name].append(theme_item_def) @@ -400,8 +404,9 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S for property_def in class_def.properties.values(): type_rst = property_def.type_name.to_rst(state) ref = ":ref:`{0}<class_{1}_property_{0}>`".format(property_def.name, class_name) - ml.append((type_rst, ref)) - format_table(f, ml) + default = property_def.default_value + ml.append((type_rst, ref, default)) + format_table(f, ml, True) # Methods overview if len(class_def.methods) > 0: @@ -415,11 +420,11 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S # Theme properties if class_def.theme_items is not None and len(class_def.theme_items) > 0: f.write(make_heading('Theme Properties', '-')) - ml = [] + pl = [] for theme_item_list in class_def.theme_items.values(): for theme_item in theme_item_list: - ml.append((theme_item.type_name.to_rst(state), theme_item.name)) - format_table(f, ml) + pl.append((theme_item.type_name.to_rst(state), theme_item.name, theme_item.default_value)) + format_table(f, pl, True) # Signals if len(class_def.signals) > 0: @@ -488,14 +493,16 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S f.write(".. _class_{}_property_{}:\n\n".format(class_name, property_def.name)) f.write('- {} **{}**\n\n'.format(property_def.type_name.to_rst(state), property_def.name)) - setget = [] + info = [] + if property_def.default_value is not None: + info.append(("*Default*", property_def.default_value)) if property_def.setter is not None and not property_def.setter.startswith("_"): - setget.append(("*Setter*", property_def.setter + '(value)')) + info.append(("*Setter*", property_def.setter + '(value)')) if property_def.getter is not None and not property_def.getter.startswith("_"): - setget.append(('*Getter*', property_def.getter + '()')) + info.append(('*Getter*', property_def.getter + '()')) - if len(setget) > 0: - format_table(f, setget) + if len(info) > 0: + format_table(f, info) if property_def.text is not None and property_def.text.strip() != '': f.write(rstize_text(property_def.text.strip(), state)) @@ -873,33 +880,33 @@ def rstize_text(text, state): # type: (str, State) -> str return text -def format_table(f, pp): # type: (TextIO, Iterable[Tuple[str, ...]]) -> None - longest_t = 0 - longest_s = 0 - for s in pp: - sl = len(s[0]) - if sl > longest_s: - longest_s = sl - tl = len(s[1]) - if tl > longest_t: - longest_t = tl - - sep = "+" - for i in range(longest_s + 2): - sep += "-" - sep += "+" - for i in range(longest_t + 2): - sep += "-" +def format_table(f, data, remove_empty_columns=False): # type: (TextIO, Iterable[Tuple[str, ...]]) -> None + if len(data) == 0: + return + + column_sizes = [0] * len(data[0]) + for row in data: + for i, text in enumerate(row): + text_length = len(text or '') + if text_length > column_sizes[i]: + column_sizes[i] = text_length + + sep = "" + for size in column_sizes: + if size == 0 and remove_empty_columns: + continue + sep += "+" + "-" * (size + 2) sep += "+\n" f.write(sep) - for s in pp: - rt = s[0] - while len(rt) < longest_s: - rt += " " - st = s[1] - while len(st) < longest_t: - st += " " - f.write("| " + rt + " | " + st + " |\n") + + for row in data: + row_text = "|" + for i, text in enumerate(row): + if column_sizes[i] == 0 and remove_empty_columns: + continue + row_text += " " + (text or '').ljust(column_sizes[i]) + " |" + row_text += "\n" + f.write(row_text) f.write(sep) f.write('\n') diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 39ca9a823e..ce66f07a19 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -56,7 +56,6 @@ #endif // MINGW hack #endif #else // UNIX -#include <net/if.h> #include <netdb.h> #ifdef ANDROID_ENABLED // We could drop this file once we up our API level to 24, @@ -73,6 +72,7 @@ #ifdef __FreeBSD__ #include <netinet/in.h> #endif +#include <net/if.h> // Order is important on OpenBSD, leave as last #endif static IP_Address _sockaddr2ip(struct sockaddr *p_addr) { diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index c10443acde..16562e2c8f 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -55,10 +55,6 @@ #include <netinet/tcp.h> -#if defined(__APPLE__) -#define MSG_NOSIGNAL SO_NOSIGPIPE -#endif - // BSD calls this flag IPV6_JOIN_GROUP #if !defined(IPV6_ADD_MEMBERSHIP) && defined(IPV6_JOIN_GROUP) #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP @@ -87,10 +83,6 @@ #define SOCK_IOCTL ioctlsocket #define SOCK_CLOSE closesocket -// Windows doesn't have this flag -#ifndef MSG_NOSIGNAL -#define MSG_NOSIGNAL 0 -#endif // Workaround missing flag in MinGW #if defined(__MINGW32__) && !defined(SIO_UDP_NETRESET) #define SIO_UDP_NETRESET _WSAIOW(IOC_VENDOR, 15) @@ -342,6 +334,13 @@ Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) { } } #endif +#if defined(SO_NOSIGPIPE) + // Disable SIGPIPE (should only be relevant to stream sockets, but seems to affect UDP too on iOS) + int par = 1; + if (setsockopt(_sock, SOL_SOCKET, SO_NOSIGPIPE, SOCK_CBUF(&par), sizeof(int)) != 0) { + print_verbose("Unable to turn off SIGPIPE on socket"); + } +#endif return OK; } @@ -546,8 +545,10 @@ Error NetSocketPosix::send(const uint8_t *p_buffer, int p_len, int &r_sent) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); int flags = 0; +#ifdef MSG_NOSIGNAL if (_is_stream) flags = MSG_NOSIGNAL; +#endif r_sent = ::send(_sock, SOCK_CBUF(p_buffer), p_len, flags); if (r_sent < 0) { diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp index 041f81d063..468819151f 100644 --- a/editor/doc/doc_data.cpp +++ b/editor/doc/doc_data.cpp @@ -248,6 +248,21 @@ void DocData::generate(bool p_basic_types) { prop.setter = setter; prop.getter = getter; + if (ClassDB::can_instance(name)) { // Cannot get default value of classes that can't be instanced + Variant default_value = ClassDB::class_get_default_property_value(name, E->get().name); + prop.default_value = default_value.get_construct_string(); + } else { + List<StringName> inheriting_classes; + ClassDB::get_direct_inheriters_from_class(name, &inheriting_classes); + for (List<StringName>::Element *E2 = inheriting_classes.front(); E2; E2 = E2->next()) { + if (ClassDB::can_instance(E2->get())) { + Variant default_value = ClassDB::class_get_default_property_value(E2->get(), E->get().name); + prop.default_value = default_value.get_construct_string(); + break; + } + } + } + bool found_type = false; if (getter != StringName()) { MethodBind *mb = ClassDB::get_method(name, getter); @@ -412,6 +427,7 @@ void DocData::generate(bool p_basic_types) { PropertyDoc pd; pd.name = E->get(); pd.type = "int"; + pd.default_value = itos(Theme::get_default()->get_constant(E->get(), cname)); c.theme_properties.push_back(pd); } @@ -422,6 +438,7 @@ void DocData::generate(bool p_basic_types) { PropertyDoc pd; pd.name = E->get(); pd.type = "Color"; + pd.default_value = Variant(Theme::get_default()->get_color(E->get(), cname)).get_construct_string(); c.theme_properties.push_back(pd); } @@ -530,6 +547,7 @@ void DocData::generate(bool p_basic_types) { PropertyDoc property; property.name = pi.name; property.type = Variant::get_type_name(pi.type); + property.default_value = v.get(pi.name).get_construct_string(); c.properties.push_back(property); } @@ -1063,12 +1081,15 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri for (int i = 0; i < c.properties.size(); i++) { - String enum_text; + String additional_attributes; if (c.properties[i].enumeration != String()) { - enum_text = " enum=\"" + c.properties[i].enumeration + "\""; + additional_attributes += " enum=\"" + c.properties[i].enumeration + "\""; + } + if (c.properties[i].default_value != String()) { + additional_attributes += " default=\"" + c.properties[i].default_value.xml_escape(true) + "\""; } const PropertyDoc &p = c.properties[i]; - _write_string(f, 2, "<member name=\"" + p.name + "\" type=\"" + p.type + "\" setter=\"" + p.setter + "\" getter=\"" + p.getter + "\"" + enum_text + ">"); + _write_string(f, 2, "<member name=\"" + p.name + "\" type=\"" + p.type + "\" setter=\"" + p.setter + "\" getter=\"" + p.getter + "\"" + additional_attributes + ">"); _write_string(f, 3, p.description.strip_edges().xml_escape()); _write_string(f, 2, "</member>"); } @@ -1125,8 +1146,14 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri for (int i = 0; i < c.theme_properties.size(); i++) { const PropertyDoc &p = c.theme_properties[i]; - _write_string(f, 2, "<theme_item name=\"" + p.name + "\" type=\"" + p.type + "\">"); + + if (p.default_value != "") + _write_string(f, 2, "<theme_item name=\"" + p.name + "\" type=\"" + p.type + "\" default=\"" + p.default_value.xml_escape(true) + "\">"); + else + _write_string(f, 2, "<theme_item name=\"" + p.name + "\" type=\"" + p.type + "\">"); + _write_string(f, 3, p.description.strip_edges().xml_escape()); + _write_string(f, 2, "</theme_item>"); } _write_string(f, 1, "</theme_items>"); diff --git a/editor/doc/doc_data.h b/editor/doc/doc_data.h index d3844adb7e..3d5867dcca 100644 --- a/editor/doc/doc_data.h +++ b/editor/doc/doc_data.h @@ -73,6 +73,7 @@ public: String enumeration; String description; String setter, getter; + String default_value; bool operator<(const PropertyDoc &p_prop) const { return name < p_prop.name; } diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 9918b655fb..ff50940842 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -48,9 +48,9 @@ void EditorHelp::_init_colors() { text_color = get_color("default_color", "RichTextLabel"); headline_color = get_color("headline_color", "EditorHelp"); base_type_color = title_color.linear_interpolate(text_color, 0.5); - comment_color = text_color * Color(1, 1, 1, 0.6); + comment_color = text_color * Color(1, 1, 1, 0.4); symbol_color = comment_color; - value_color = text_color * Color(1, 1, 1, 0.4); + value_color = text_color * Color(1, 1, 1, 0.6); qualifier_color = text_color * Color(1, 1, 1, 0.8); type_color = get_color("accent_color", "Editor").linear_interpolate(text_color, 0.5); class_desc->add_color_override("selection_color", get_color("accent_color", "Editor") * Color(1, 1, 1, 0.4)); @@ -258,9 +258,11 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview if (p_method.arguments[j].default_value != "") { class_desc->push_color(symbol_color); - class_desc->add_text("="); + class_desc->add_text(" = "); class_desc->pop(); + class_desc->push_color(value_color); _add_text(_fix_constant(p_method.arguments[j].default_value)); + class_desc->pop(); } class_desc->pop(); @@ -471,23 +473,37 @@ void EditorHelp::_update_doc() { if (cd.properties[i].description != "") { describe = true; } + class_desc->push_cell(); + class_desc->push_font(doc_code_font); + class_desc->push_color(headline_color); + if (describe) { class_desc->push_meta("@member " + cd.properties[i].name); } - class_desc->push_font(doc_code_font); - class_desc->push_color(headline_color); _add_text(cd.properties[i].name); - class_desc->pop(); - class_desc->pop(); - if (describe) { class_desc->pop(); property_descr = true; } + if (cd.properties[i].default_value != "") { + class_desc->push_color(symbol_color); + class_desc->add_text(" [default: "); + class_desc->pop(); + class_desc->push_color(value_color); + _add_text(_fix_constant(cd.properties[i].default_value)); + class_desc->pop(); + class_desc->push_color(symbol_color); + class_desc->add_text("]"); + class_desc->pop(); + } + + class_desc->pop(); + class_desc->pop(); + class_desc->pop(); } @@ -613,6 +629,19 @@ void EditorHelp::_update_doc() { class_desc->push_color(headline_color); _add_text(cd.theme_properties[i].name); class_desc->pop(); + + if (cd.theme_properties[i].default_value != "") { + class_desc->push_color(symbol_color); + class_desc->add_text(" [default: "); + class_desc->pop(); + class_desc->push_color(value_color); + _add_text(_fix_constant(cd.theme_properties[i].default_value)); + class_desc->pop(); + class_desc->push_color(symbol_color); + class_desc->add_text("]"); + class_desc->pop(); + } + class_desc->pop(); if (cd.theme_properties[i].description != "") { @@ -671,7 +700,7 @@ void EditorHelp::_update_doc() { if (cd.signals[i].arguments[j].default_value != "") { class_desc->push_color(symbol_color); - class_desc->add_text("="); + class_desc->add_text(" = "); class_desc->pop(); _add_text(cd.signals[i].arguments[j].default_value); } @@ -777,7 +806,7 @@ void EditorHelp::_update_doc() { class_desc->add_text(" = "); class_desc->pop(); class_desc->push_color(value_color); - _add_text(enum_list[i].value); + _add_text(_fix_constant(enum_list[i].value)); class_desc->pop(); class_desc->pop(); if (enum_list[i].description != "") { @@ -843,7 +872,7 @@ void EditorHelp::_update_doc() { class_desc->add_text(" = "); class_desc->pop(); class_desc->push_color(value_color); - _add_text(constants[i].value); + _add_text(_fix_constant(constants[i].value)); class_desc->pop(); class_desc->pop(); @@ -963,6 +992,21 @@ void EditorHelp::_update_doc() { class_desc->push_color(headline_color); _add_text(cd.properties[i].name); class_desc->pop(); // color + + if (cd.properties[i].default_value != "") { + class_desc->push_color(symbol_color); + class_desc->add_text(" [default: "); + class_desc->pop(); // color + + class_desc->push_color(value_color); + _add_text(_fix_constant(cd.properties[i].default_value)); + class_desc->pop(); // color + + class_desc->push_color(symbol_color); + class_desc->add_text("]"); + class_desc->pop(); // color + } + class_desc->pop(); // font class_desc->pop(); // cell diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 8e4ec47435..c8bcce6e55 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -2808,6 +2808,7 @@ EditorPropertyResource::EditorPropertyResource() { assign->set_drag_forwarding(this); assign->connect("draw", this, "_button_draw"); hbc->add_child(assign); + add_focusable(assign); preview = memnew(TextureRect); preview->set_expand(true); @@ -2828,6 +2829,7 @@ EditorPropertyResource::EditorPropertyResource() { edit->connect("pressed", this, "_update_menu"); hbc->add_child(edit); edit->connect("gui_input", this, "_button_input"); + add_focusable(edit); file = NULL; scene_tree = NULL; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 8521c0c723..a36163f661 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -1473,6 +1473,10 @@ void EditorSettings::get_shortcut_list(List<String> *r_shortcuts) { Ref<ShortCut> ED_GET_SHORTCUT(const String &p_path) { + if (!EditorSettings::get_singleton()) { + return NULL; + } + Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); if (!sc.is_valid()) { ERR_EXPLAIN("Used ED_GET_SHORTCUT with invalid shortcut: " + p_path); @@ -1508,6 +1512,15 @@ Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p ie->set_metakey(bool(p_keycode & KEY_MASK_META)); } + if (!EditorSettings::get_singleton()) { + Ref<ShortCut> sc; + sc.instance(); + sc->set_name(p_name); + sc->set_shortcut(ie); + sc->set_meta("original", ie); + return sc; + } + Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); if (sc.is_valid()) { diff --git a/main/main.cpp b/main/main.cpp index 9183dab58c..77c4e5a385 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1375,6 +1375,8 @@ bool Main::start() { #ifdef TOOLS_ENABLED if (doc_tool != "") { + Engine::get_singleton()->set_editor_hint(true); // Needed to instance editor-only classes for their default values + { DirAccessRef da = DirAccess::open(doc_tool); if (!da) { diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index dcb4b7fd75..a5a356ced2 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -882,7 +882,9 @@ NetworkedMultiplayerENet::NetworkedMultiplayerENet() { NetworkedMultiplayerENet::~NetworkedMultiplayerENet() { - close_connection(); + if (active) { + close_connection(); + } } // Sets IP for ENet to bind when using create_server or create_client diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.cpp b/modules/gdnative/arvr/arvr_interface_gdnative.cpp index da01f573ce..64e2c362b2 100644 --- a/modules/gdnative/arvr/arvr_interface_gdnative.cpp +++ b/modules/gdnative/arvr/arvr_interface_gdnative.cpp @@ -33,9 +33,13 @@ #include "servers/arvr/arvr_positional_tracker.h" #include "servers/visual/visual_server_globals.h" +void ARVRInterfaceGDNative::_bind_methods() { + ADD_PROPERTY_DEFAULT("interface_is_initialized", false); + ADD_PROPERTY_DEFAULT("ar_is_anchor_detection_enabled", false); +} + ARVRInterfaceGDNative::ARVRInterfaceGDNative() { - // testing - printf("Construct gdnative interface\n"); + print_verbose("Construct gdnative interface\n"); // we won't have our data pointer until our library gets set data = NULL; @@ -44,9 +48,9 @@ ARVRInterfaceGDNative::ARVRInterfaceGDNative() { } ARVRInterfaceGDNative::~ARVRInterfaceGDNative() { - printf("Destruct gdnative interface\n"); + print_verbose("Destruct gdnative interface\n"); - if (is_initialized()) { + if (interface != NULL && is_initialized()) { uninitialize(); }; @@ -99,13 +103,10 @@ int ARVRInterfaceGDNative::get_capabilities() const { } bool ARVRInterfaceGDNative::get_anchor_detection_is_enabled() const { - bool enabled; ERR_FAIL_COND_V(interface == NULL, false); - enabled = interface->get_anchor_detection_is_enabled(data); - - return enabled; + return interface->get_anchor_detection_is_enabled(data); } void ARVRInterfaceGDNative::set_anchor_detection_is_enabled(bool p_enable) { @@ -137,21 +138,16 @@ bool ARVRInterfaceGDNative::is_stereo() { } bool ARVRInterfaceGDNative::is_initialized() const { - bool initialized; ERR_FAIL_COND_V(interface == NULL, false); - initialized = interface->is_initialized(data); - - return initialized; + return interface->is_initialized(data); } bool ARVRInterfaceGDNative::initialize() { - bool initialized; - ERR_FAIL_COND_V(interface == NULL, false); - initialized = interface->initialize(data); + bool initialized = interface->initialize(data); if (initialized) { // if we successfully initialize our interface and we don't have a primary interface yet, this becomes our primary interface diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.h b/modules/gdnative/arvr/arvr_interface_gdnative.h index 651e5c8715..ab7090876a 100644 --- a/modules/gdnative/arvr/arvr_interface_gdnative.h +++ b/modules/gdnative/arvr/arvr_interface_gdnative.h @@ -49,6 +49,8 @@ protected: const godot_arvr_interface_gdnative *interface; void *data; + static void _bind_methods(); + public: /** general interface information **/ ARVRInterfaceGDNative(); diff --git a/modules/gdnative/net/multiplayer_peer_gdnative.cpp b/modules/gdnative/net/multiplayer_peer_gdnative.cpp index bdeba149d2..d2c95efa77 100644 --- a/modules/gdnative/net/multiplayer_peer_gdnative.cpp +++ b/modules/gdnative/net/multiplayer_peer_gdnative.cpp @@ -113,6 +113,8 @@ NetworkedMultiplayerPeer::ConnectionStatus MultiplayerPeerGDNative::get_connecti } void MultiplayerPeerGDNative::_bind_methods() { + ADD_PROPERTY_DEFAULT("transfer_mode", TRANSFER_MODE_UNRELIABLE); + ADD_PROPERTY_DEFAULT("refuse_new_connections", true); } extern "C" { diff --git a/modules/webrtc/webrtc_data_channel_gdnative.cpp b/modules/webrtc/webrtc_data_channel_gdnative.cpp index 4f33491af2..6362634626 100644 --- a/modules/webrtc/webrtc_data_channel_gdnative.cpp +++ b/modules/webrtc/webrtc_data_channel_gdnative.cpp @@ -35,6 +35,7 @@ #include "modules/gdnative/nativescript/nativescript.h" void WebRTCDataChannelGDNative::_bind_methods() { + ADD_PROPERTY_DEFAULT("write_mode", WRITE_MODE_BINARY); } WebRTCDataChannelGDNative::WebRTCDataChannelGDNative() { diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 2bd9e5e2a2..95acf13fad 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1541,7 +1541,7 @@ Vector2 KinematicCollision2D::get_remainder() const { return collision.remainder; } Object *KinematicCollision2D::get_local_shape() const { - ERR_FAIL_COND_V(!owner, NULL); + if (!owner) return NULL; uint32_t ownerid = owner->shape_find_owner(collision.local_shape); return owner->shape_owner_get_owner(ownerid); } diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp index 95eec41fb2..dfa8fce9be 100644 --- a/scene/3d/arvr_nodes.cpp +++ b/scene/3d/arvr_nodes.cpp @@ -264,6 +264,7 @@ void ARVRController::_bind_methods() { ClassDB::bind_method(D_METHOD("get_rumble"), &ARVRController::get_rumble); ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &ARVRController::set_rumble); ADD_PROPERTY(PropertyInfo(Variant::REAL, "rumble", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_rumble", "get_rumble"); + ADD_PROPERTY_DEFAULT("rumble", 0.0); ClassDB::bind_method(D_METHOD("get_mesh"), &ARVRController::get_mesh); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 3624e04434..d3aad7000d 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -1470,7 +1470,7 @@ Vector3 KinematicCollision::get_remainder() const { return collision.remainder; } Object *KinematicCollision::get_local_shape() const { - ERR_FAIL_COND_V(!owner, NULL); + if (!owner) return NULL; uint32_t ownerid = owner->shape_find_owner(collision.local_shape); return owner->shape_owner_get_owner(ownerid); } diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 58a0762469..b197971b61 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -173,7 +173,7 @@ void ColorPicker::_value_changed(double) { color.set_hsv(scroll[0]->get_value() / 360.0, scroll[1]->get_value() / 100.0, scroll[2]->get_value() / 100.0, - scroll[3]->get_value() / 100.0); + scroll[3]->get_value() / 255.0); } else { for (int i = 0; i < 4; i++) { color.components[i] = scroll[i]->get_value() / (raw_mode_enabled ? 1.0 : 255.0); @@ -209,17 +209,17 @@ void ColorPicker::_update_color(bool p_update_sliders) { if (hsv_mode_enabled) { for (int i = 0; i < 4; i++) { - scroll[i]->set_step(0.1); + scroll[i]->set_step(1.0); } - scroll[0]->set_max(360); + scroll[0]->set_max(359); scroll[0]->set_value(h * 360.0); scroll[1]->set_max(100); scroll[1]->set_value(s * 100.0); scroll[2]->set_max(100); scroll[2]->set_value(v * 100.0); - scroll[3]->set_max(100); - scroll[3]->set_value(color.components[3] * 100.0); + scroll[3]->set_max(255); + scroll[3]->set_value(color.components[3] * 255.0); } else { for (int i = 0; i < 4; i++) { if (raw_mode_enabled) { diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 7f0cebd492..0e7cec57a4 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -614,6 +614,7 @@ void SceneTree::finish() { root->_set_tree(NULL); root->_propagate_after_exit_tree(); memdelete(root); //delete root + root = NULL; } } @@ -1889,6 +1890,7 @@ void SceneTree::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_navigation_hint"), "set_debug_navigation_hint", "is_debugging_navigation_hint"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections"); + ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_font_oversampling"), "set_use_font_oversampling", "is_using_font_oversampling"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_edited_scene_root", "get_edited_scene_root"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_current_scene", "get_current_scene"); @@ -1962,7 +1964,7 @@ bool SceneTree::is_using_font_oversampling() const { SceneTree::SceneTree() { - singleton = this; + if (singleton == NULL) singleton = this; _quit = false; accept_quit = true; quit_on_go_back = true; @@ -2107,4 +2109,11 @@ SceneTree::SceneTree() { } SceneTree::~SceneTree() { + if (root) { + root->_set_tree(NULL); + root->_propagate_after_exit_tree(); + memdelete(root); + } + + if (singleton == this) singleton = NULL; } diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp index 51dd91fff5..de853f0c30 100644 --- a/scene/resources/concave_polygon_shape_2d.cpp +++ b/scene/resources/concave_polygon_shape_2d.cpp @@ -104,4 +104,6 @@ void ConcavePolygonShape2D::_bind_methods() { ConcavePolygonShape2D::ConcavePolygonShape2D() : Shape2D(Physics2DServer::get_singleton()->concave_polygon_shape_create()) { + PoolVector<Vector2> empty; + set_segments(empty); } |