diff options
43 files changed, 499 insertions, 207 deletions
diff --git a/.travis.yml b/.travis.yml index 49d1059360..8a6f80002b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,6 +71,10 @@ matrix: env: PLATFORM=android TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-clang EXTRA_ARGS="warnings=extra werror=yes" os: linux compiler: clang + addons: + apt: + packages: + - openjdk-8-jdk - name: macOS editor (debug, Clang) stage: build @@ -116,14 +120,14 @@ before_install: install: - pip install --user scons; - if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$PLATFORM" = "android" ]; then + export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64; + export PATH=/usr/lib/jvm/java-8-openjdk-amd64/jre/bin:${PATH}; + java -version; misc/travis/android-tools-linux.sh; fi - if [ "$TRAVIS_OS_NAME" = "osx" ]; then export PATH=${PATH}:/Users/travis/Library/Python/2.7/bin; fi - - if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$PLATFORM" = "android" ]; then - misc/travis/android-tools-osx.sh; - fi before_script: - if [ "$PLATFORM" = "android" ]; then diff --git a/core/SCsub b/core/SCsub index ed9a0a231d..b12c6a9e27 100644 --- a/core/SCsub +++ b/core/SCsub @@ -80,6 +80,8 @@ if env['builtin_zlib']: env_thirdparty.Prepend(CPPPATH=[thirdparty_zlib_dir]) # Needs to be available in main env too env.Prepend(CPPPATH=[thirdparty_zlib_dir]) + if (env['target'] == 'debug'): + env_thirdparty.Append(CPPDEFINES=['ZLIB_DEBUG']) env_thirdparty.add_source_files(env.core_sources, thirdparty_zlib_sources) diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 0ba84d0c8f..1426dbbd4d 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -602,7 +602,16 @@ void MultiplayerAPI::_add_peer(int p_id) { void MultiplayerAPI::_del_peer(int p_id) { connected_peers.erase(p_id); - path_get_cache.erase(p_id); // I no longer need your cache, sorry. + // Cleanup get cache. + path_get_cache.erase(p_id); + // Cleanup sent cache. + // Some refactoring is needed to make this faster and do paths GC. + List<NodePath> keys; + path_send_cache.get_key_list(&keys); + for (List<NodePath>::Element *E = keys.front(); E; E = E->next()) { + PathSentCache *psc = path_send_cache.getptr(E->get()); + psc->confirmed_peers.erase(p_id); + } emit_signal("network_peer_disconnected", p_id); } diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index 87b8f5c83d..a920001de4 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -22,6 +22,28 @@ Called (if exists) to draw the canvas item. </description> </method> + <method name="draw_arc"> + <return type="void"> + </return> + <argument index="0" name="center" type="Vector2"> + </argument> + <argument index="1" name="radius" type="float"> + </argument> + <argument index="2" name="start_angle" type="float"> + </argument> + <argument index="3" name="end_angle" type="float"> + </argument> + <argument index="4" name="point_count" type="int"> + </argument> + <argument index="5" name="color" type="Color"> + </argument> + <argument index="6" name="width" type="float" default="1.0"> + </argument> + <argument index="7" name="antialiased" type="bool" default="false"> + </argument> + <description> + </description> + </method> <method name="draw_char"> <return type="float"> </return> diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml new file mode 100644 index 0000000000..bf01ebfe82 --- /dev/null +++ b/doc/classes/EditorSpinSlider.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="EditorSpinSlider" inherits="Range" category="Core" version="3.2"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <members> + <member name="flat" type="bool" setter="set_flat" getter="is_flat" default="false"> + </member> + <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" override="true" enum="Control.FocusMode" default="2" /> + <member name="label" type="String" setter="set_label" getter="get_label" default=""""> + </member> + <member name="read_only" type="bool" setter="set_read_only" getter="is_read_only" default="false"> + </member> + </members> + <constants> + </constants> +</class> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 13a2fc2602..b6eeed4a21 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -217,7 +217,7 @@ Returns the path to the current engine executable. </description> </method> - <method name="get_granted_permissions"> + <method name="get_granted_permissions" qualifiers="const"> <return type="PoolStringArray"> </return> <description> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 9657982016..fa735b8918 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -6,6 +6,7 @@ <description> Contains global variables accessible from everywhere. Use [method get_setting], [method set_setting] or [method has_setting] to access them. Variables stored in [code]project.godot[/code] are also loaded into ProjectSettings, making this object very useful for reading custom game configuration options. When naming a Project Settings property, use the full path to the setting including the category. For example, [code]"application/config/name"[/code] for the project name. Category and property names can be viewed in the Project Settings dialog. + [b]Overriding:[/b] Any project setting can be overridden by creating a file named [code]override.cfg[/code] in the project's root directory. This can also be used in exported projects by placing this file in the same directory as the project binary. </description> <tutorials> </tutorials> @@ -201,6 +202,7 @@ </member> <member name="application/config/project_settings_override" type="String" setter="" getter="" default=""""> Specifies a file to override project settings. For example: [code]user://custom_settings.cfg[/code]. + [b]Note:[/b] Regardless of this setting's value, [code]res://override.cfg[/code] will still be read to override the project settings (see this class' description at the top). </member> <member name="application/config/use_custom_user_dir" type="bool" setter="" getter="" default="false"> If [code]true[/code], the project will save user data to its own user directory (see [member application/config/custom_user_dir_name]). This setting is only effective on desktop platforms. A name must be set in the [member application/config/custom_user_dir_name] setting for this to take effect. If [code]false[/code], the project will save user data to [code](OS user data directory)/Godot/app_userdata/(project name)[/code]. diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 01c8ee4779..2962391b99 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -133,6 +133,18 @@ Adds an [code][align][/code] tag based on the given [code]align[/code] value. See [enum Align] for possible values. </description> </method> + <method name="push_bold"> + <return type="void"> + </return> + <description> + </description> + </method> + <method name="push_bold_italics"> + <return type="void"> + </return> + <description> + </description> + </method> <method name="push_cell"> <return type="void"> </return> @@ -167,6 +179,12 @@ Adds an [code][indent][/code] tag to the tag stack. Multiplies "level" by current tab_size to determine new margin length. </description> </method> + <method name="push_italics"> + <return type="void"> + </return> + <description> + </description> + </method> <method name="push_list"> <return type="void"> </return> @@ -185,6 +203,18 @@ Adds a [code][meta][/code] tag to the tag stack. Similar to the BBCode [code][url=something]{text}[/url][/code], but supports non-[String] metadata types. </description> </method> + <method name="push_mono"> + <return type="void"> + </return> + <description> + </description> + </method> + <method name="push_normal"> + <return type="void"> + </return> + <description> + </description> + </method> <method name="push_strikethrough"> <return type="void"> </return> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 27eab85301..0dd2d75cd5 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -530,7 +530,7 @@ </constant> </constants> <theme_items> - <theme_item name="background_color" type="Color" default="Color( 0, 0, 0, 1 )"> + <theme_item name="background_color" type="Color" default="Color( 0, 0, 0, 0 )"> Sets the background [Color] of this [TextEdit]. [member syntax_highlighting] has to be enabled. </theme_item> <theme_item name="bookmark_color" type="Color" default="Color( 0.08, 0.49, 0.98, 1 )"> diff --git a/doc/classes/VideoPlayer.xml b/doc/classes/VideoPlayer.xml index 2215f26c23..804489f7f1 100644 --- a/doc/classes/VideoPlayer.xml +++ b/doc/classes/VideoPlayer.xml @@ -16,7 +16,7 @@ Returns the video stream's name. </description> </method> - <method name="get_video_texture"> + <method name="get_video_texture" qualifiers="const"> <return type="Texture"> </return> <description> diff --git a/doc/classes/VisualShaderNodeCubeMap.xml b/doc/classes/VisualShaderNodeCubeMap.xml index 36465a6b4d..29ebe95086 100644 --- a/doc/classes/VisualShaderNodeCubeMap.xml +++ b/doc/classes/VisualShaderNodeCubeMap.xml @@ -12,10 +12,16 @@ <member name="cube_map" type="CubeMap" setter="set_cube_map" getter="get_cube_map"> </member> <member name="default_input_values" type="Array" setter="_set_default_input_values" getter="_get_default_input_values" override="true" default="[ ]" /> + <member name="source" type="int" setter="set_source" getter="get_source" enum="VisualShaderNodeCubeMap.Source" default="0"> + </member> <member name="texture_type" type="int" setter="set_texture_type" getter="get_texture_type" enum="VisualShaderNodeCubeMap.TextureType" default="0"> </member> </members> <constants> + <constant name="SOURCE_TEXTURE" value="0" enum="Source"> + </constant> + <constant name="SOURCE_PORT" value="1" enum="Source"> + </constant> <constant name="TYPE_DATA" value="0" enum="TextureType"> </constant> <constant name="TYPE_COLOR" value="1" enum="TextureType"> diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py index 1b27e4a35a..ef38299680 100755 --- a/doc/tools/makerst.py +++ b/doc/tools/makerst.py @@ -435,21 +435,30 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S # Signals if len(class_def.signals) > 0: f.write(make_heading('Signals', '-')) + index = 0 + for signal in class_def.signals.values(): - #f.write(".. _class_{}_{}:\n\n".format(class_name, signal.name)) + if index != 0: + f.write('----\n\n') + f.write(".. _class_{}_signal_{}:\n\n".format(class_name, signal.name)) _, signature = make_method_signature(class_def, signal, False, state) f.write("- {}\n\n".format(signature)) - if signal.description is None or signal.description.strip() == '': - continue - f.write(rstize_text(signal.description.strip(), state)) - f.write("\n\n") + if signal.description is not None and signal.description.strip() != '': + f.write(rstize_text(signal.description.strip(), state) + '\n\n') + + index += 1 # Enums if len(class_def.enums) > 0: f.write(make_heading('Enumerations', '-')) + index = 0 + for e in class_def.enums.values(): + if index != 0: + f.write('----\n\n') + f.write(".. _enum_{}_{}:\n\n".format(class_name, e.name)) # Sphinx seems to divide the bullet list into individual <ul> tags if we weave the labels into it. # As such I'll put them all above the list. Won't be perfect but better than making the list visually broken. @@ -463,8 +472,11 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S f.write("- **{}** = **{}**".format(value.name, value.value)) if value.text is not None and value.text.strip() != '': f.write(' --- ' + rstize_text(value.text.strip(), state)) + f.write('\n\n') + index += 1 + # Constants if len(class_def.constants) > 0: f.write(make_heading('Constants', '-')) @@ -477,6 +489,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S f.write("- **{}** = **{}**".format(constant.name, constant.value)) if constant.text is not None and constant.text.strip() != '': f.write(' --- ' + rstize_text(constant.text.strip(), state)) + f.write('\n\n') # Class description @@ -494,11 +507,15 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S # Property descriptions if any(not p.overridden for p in class_def.properties.values()) > 0: f.write(make_heading('Property Descriptions', '-')) + index = 0 + for property_def in class_def.properties.values(): if property_def.overridden: continue - #f.write(".. _class_{}_{}:\n\n".format(class_name, property_def.name)) + if index != 0: + f.write('----\n\n') + 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)) @@ -514,24 +531,30 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S 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)) - f.write('\n\n') + f.write(rstize_text(property_def.text.strip(), state) + '\n\n') + + index += 1 # Method descriptions if len(class_def.methods) > 0: f.write(make_heading('Method Descriptions', '-')) + index = 0 + for method_list in class_def.methods.values(): for i, m in enumerate(method_list): + if index != 0: + f.write('----\n\n') + if i == 0: - #f.write(".. _class_{}_{}:\n\n".format(class_name, m.name)) f.write(".. _class_{}_method_{}:\n\n".format(class_name, m.name)) + ret_type, signature = make_method_signature(class_def, m, False, state) f.write("- {} {}\n\n".format(ret_type, signature)) - if m.description is None or m.description.strip() == '': - continue - f.write(rstize_text(m.description.strip(), state)) - f.write("\n\n") + if m.description is not None and m.description.strip() != '': + f.write(rstize_text(m.description.strip(), state) + '\n\n') + + index += 1 def make_class_list(class_list, columns): # type: (List[str], int) -> None @@ -897,7 +920,7 @@ def rstize_text(text, state): # type: (str, State) -> str 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): @@ -912,7 +935,7 @@ def format_table(f, data, remove_empty_columns=False): # type: (TextIO, Iterabl sep += "+" + "-" * (size + 2) sep += "+\n" f.write(sep) - + for row in data: row_text = "|" for i, text in enumerate(row): diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index da46b393c6..5f99a40c79 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -70,6 +70,7 @@ #define SOCK_CBUF(x) x #define SOCK_IOCTL ioctl #define SOCK_CLOSE ::close +#define SOCK_CONNECT(p_sock, p_addr, p_addr_len) ::connect(p_sock, p_addr, p_addr_len) /* Windows */ #elif defined(WINDOWS_ENABLED) @@ -83,6 +84,9 @@ #define SOCK_CBUF(x) (const char *)(x) #define SOCK_IOCTL ioctlsocket #define SOCK_CLOSE closesocket +// connect is broken on windows under certain conditions, reasons unknown: +// See https://github.com/godotengine/webrtc-native/issues/6 +#define SOCK_CONNECT(p_sock, p_addr, p_addr_len) ::WSAConnect(p_sock, p_addr, p_addr_len, NULL, NULL, NULL, NULL) // Workaround missing flag in MinGW #if defined(__MINGW32__) && !defined(SIO_UDP_NETRESET) @@ -409,7 +413,7 @@ Error NetSocketPosix::connect_to_host(IP_Address p_host, uint16_t p_port) { struct sockaddr_storage addr; size_t addr_size = _set_addr_storage(&addr, p_host, p_port, _ip_type); - if (::connect(_sock, (struct sockaddr *)&addr, addr_size) != 0) { + if (SOCK_CONNECT(_sock, (struct sockaddr *)&addr, addr_size) != 0) { NetError err = _get_socket_error(); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 4c31797c50..1a821ddd02 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -191,7 +191,9 @@ void FindReplaceBar::_replace() { results_count = -1; } - search_current(); + if (!search_current()) { + search_next(); + } } void FindReplaceBar::_replace_all() { diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp index f487a3048b..e4a939c379 100644 --- a/editor/editor_path.cpp +++ b/editor/editor_path.cpp @@ -132,6 +132,15 @@ void EditorPath::_id_pressed(int p_idx) { EditorNode::get_singleton()->push_item(obj); } +void EditorPath::_notification(int p_what) { + + switch (p_what) { + case NOTIFICATION_THEME_CHANGED: { + update_path(); + } break; + } +} + void EditorPath::_bind_methods() { ClassDB::bind_method("_about_to_show", &EditorPath::_about_to_show); diff --git a/editor/editor_path.h b/editor/editor_path.h index 2dc4d21f9b..a84da9f5ac 100644 --- a/editor/editor_path.h +++ b/editor/editor_path.h @@ -48,6 +48,7 @@ class EditorPath : public MenuButton { void _add_children_to_popup(Object *p_obj, int p_depth = 0); protected: + void _notification(int p_what); static void _bind_methods(); public: diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 672844117d..a3a02dbd4c 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -436,7 +436,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("text_editor/indent/size", 4); hints["text_editor/indent/size"] = PropertyInfo(Variant::INT, "text_editor/indent/size", PROPERTY_HINT_RANGE, "1, 64, 1"); // size of 0 crashes. _initial_set("text_editor/indent/auto_indent", true); - _initial_set("text_editor/indent/convert_indent_on_save", false); + _initial_set("text_editor/indent/convert_indent_on_save", true); _initial_set("text_editor/indent/draw_tabs", true); _initial_set("text_editor/indent/draw_spaces", false); diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index 95c615afa3..f47f9b8b92 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -69,9 +69,15 @@ void ExportTemplateManager::_update_template_list() { memdelete(d); String current_version = VERSION_FULL_CONFIG; - // Downloadable export templates are only available for stable, alpha, beta and RC versions. + // Downloadable export templates are only available for stable and official alpha/beta/RC builds + // (which always have a number following their status, e.g. "alpha1"). // Therefore, don't display download-related features when using a development version - const bool downloads_available = String(VERSION_STATUS) != String("dev"); + // (whose builds aren't numbered). + const bool downloads_available = + String(VERSION_STATUS) != String("dev") && + String(VERSION_STATUS) != String("alpha") && + String(VERSION_STATUS) != String("beta") && + String(VERSION_STATUS) != String("rc"); Label *current = memnew(Label); current->set_h_size_flags(SIZE_EXPAND_FILL); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index e3f0021fbc..be05183f92 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -333,10 +333,11 @@ void FileSystemDock::_notification(int p_what) { case NOTIFICATION_DRAG_BEGIN: { Dictionary dd = get_viewport()->gui_get_drag_data(); if (tree->is_visible_in_tree() && dd.has("type")) { - if ((String(dd["type"]) == "files") || (String(dd["type"]) == "files_and_dirs") || (String(dd["type"]) == "resource")) { + if (dd.has("favorite")) { + if ((String(dd["favorite"]) == "all")) + tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN); + } else if ((String(dd["type"]) == "files") || (String(dd["type"]) == "files_and_dirs") || (String(dd["type"]) == "resource")) { tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM | Tree::DROP_MODE_INBETWEEN); - } else if ((String(dd["type"]) == "favorite")) { - tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN); } } } break; @@ -1839,7 +1840,7 @@ Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from) all_not_favorites &= !is_favorite; selected = tree->get_next_selected(selected); } - if (all_favorites) { + if (!all_not_favorites) { paths = _tree_get_selected(false); } else { paths = _tree_get_selected(); @@ -1857,12 +1858,9 @@ Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from) if (paths.empty()) return Variant(); - if (!all_favorites && !all_not_favorites) - return Variant(); - Dictionary drag_data = EditorNode::get_singleton()->drag_files_and_dirs(paths, p_from); - if (all_favorites) { - drag_data["type"] = "favorite"; + if (!all_not_favorites) { + drag_data["favorite"] = all_favorites ? "all" : "mixed"; } return drag_data; } @@ -1870,7 +1868,11 @@ Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from) bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { Dictionary drag_data = p_data; - if (drag_data.has("type") && String(drag_data["type"]) == "favorite") { + if (drag_data.has("favorite")) { + + if (String(drag_data["favorite"]) != "all") { + return false; + } // Moving favorite around. TreeItem *ti = tree->get_item_at_position(p_point); @@ -1937,7 +1939,11 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, Vector<String> dirs = EditorSettings::get_singleton()->get_favorites(); - if (drag_data.has("type") && String(drag_data["type"]) == "favorite") { + if (drag_data.has("favorite")) { + + if (String(drag_data["favorite"]) != "all") { + return; + } // Moving favorite around. TreeItem *ti = tree->get_item_at_position(p_point); if (!ti) diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index d5b1f46333..95767a96d8 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -1137,9 +1137,12 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const initial_loading = false; - // The loading text only needs to be displayed before the first page is loaded + // The loading text only needs to be displayed before the first page is loaded. + // Therefore, we don't need to show it again. library_loading->hide(); + library_error->hide(); + if (asset_items) { memdelete(asset_items); } @@ -1187,6 +1190,11 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const asset_bottom_page = _make_pages(page, pages, page_len, total_items, result.size()); library_vb->add_child(asset_bottom_page); + if (result.empty()) { + library_error->set_text(vformat(TTR("No results for \"%s\"."), filter->get_text())); + library_error->show(); + } + for (int i = 0; i < result.size(); i++) { Dictionary r = result[i]; @@ -1453,6 +1461,11 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { library_loading->set_align(Label::ALIGN_CENTER); library_vb->add_child(library_loading); + library_error = memnew(Label); + library_error->set_align(Label::ALIGN_CENTER); + library_error->hide(); + library_vb->add_child(library_error); + asset_top_page = memnew(HBoxContainer); library_vb->add_child(asset_top_page); diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index 94289f3b49..70ffbd9eed 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -184,6 +184,7 @@ class EditorAssetLibrary : public PanelContainer { ScrollContainer *library_scroll; VBoxContainer *library_vb; Label *library_loading; + Label *library_error; LineEdit *filter; OptionButton *categories; OptionButton *repository; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 84372a6f93..7659363cdf 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -2287,9 +2287,7 @@ bool CanvasItemEditor::_gui_input_ruler_tool(const Ref<InputEvent> &p_event) { return true; } - bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL); - - if (m.is_valid() && (ruler_tool_active || (is_snap_active && previous_origin != ruler_tool_origin))) { + if (m.is_valid() && (ruler_tool_active || (grid_snap_active && previous_origin != ruler_tool_origin))) { viewport->update(); return true; @@ -2687,8 +2685,6 @@ void CanvasItemEditor::_draw_ruler_tool() { if (tool != TOOL_RULER) return; - bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL); - if (ruler_tool_active) { Color ruler_primary_color = get_color("accent_color", "Editor"); Color ruler_secondary_color = ruler_primary_color; @@ -2744,13 +2740,13 @@ void CanvasItemEditor::_draw_ruler_tool() { if (begin.y < end.y) { h_angle_text_pos.y = end.y + text_height * 1.5; if (ABS(text_pos2.x - h_angle_text_pos.x) < text_width) { - int height_multiplier = 1.5 + (int)is_snap_active; + int height_multiplier = 1.5 + (int)grid_snap_active; h_angle_text_pos.y = MAX(text_pos.y + height_multiplier * text_height, MAX(end.y + text_height * 1.5, text_pos2.y + height_multiplier * text_height)); } } else { h_angle_text_pos.y = end.y - text_height * 0.5; if (ABS(text_pos2.x - h_angle_text_pos.x) < text_width) { - int height_multiplier = 1 + (int)is_snap_active; + int height_multiplier = 1 + (int)grid_snap_active; h_angle_text_pos.y = MIN(text_pos.y - height_multiplier * text_height, MIN(end.y - text_height * 0.5, text_pos2.y - height_multiplier * text_height)); } } @@ -2785,7 +2781,7 @@ void CanvasItemEditor::_draw_ruler_tool() { viewport->draw_arc(end, arc_2_radius, arc_2_start_angle, arc_2_end_angle, arc_point_count, ruler_primary_color, Math::round(EDSCALE * arc_line_width)); } - if (is_snap_active) { + if (grid_snap_active) { text_pos = (begin + end) / 2 + Vector2(-text_width / 2, text_height / 2); text_pos.x = CLAMP(text_pos.x, text_width / 2, viewport->get_rect().size.x - text_width * 1.5); @@ -2807,7 +2803,7 @@ void CanvasItemEditor::_draw_ruler_tool() { } } else { - if (is_snap_active) { + if (grid_snap_active) { Ref<Texture> position_icon = get_icon("EditorPosition", "EditorIcons"); viewport->draw_texture(get_icon("EditorPosition", "EditorIcons"), (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2); } diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 9160920c50..727d92ba05 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -736,6 +736,9 @@ void CurveEditor::_draw() { if (_selected_point > 0 && _selected_point + 1 < curve.get_point_count()) { text_color.a *= 0.4; draw_string(font, Vector2(50, font_height), TTR("Hold Shift to edit tangents individually"), text_color); + } else if (curve.get_point_count() == 0) { + text_color.a *= 0.4; + draw_string(font, Vector2(50, font_height), TTR("Right click to add point"), text_color); } } diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 803c806028..f56f7ef7ca 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -845,9 +845,10 @@ void ProjectSettingsEditor::_item_adds(String) { void ProjectSettingsEditor::_item_add() { - // Initialize the property with the default value for the given type + // Initialize the property with the default value for the given type. + // The type list starts at 1 (as we exclude Nil), so add 1 to the selected value. Variant::CallError ce; - const Variant value = Variant::construct(Variant::Type(type->get_selected()), NULL, 0, ce); + const Variant value = Variant::construct(Variant::Type(type->get_selected() + 1), NULL, 0, ce); String catname = category->get_text().strip_edges(); String propname = property->get_text().strip_edges(); @@ -1835,7 +1836,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { // Start at 1 to avoid adding "Nil" as an option for (int i = 1; i < Variant::VARIANT_MAX; i++) { - type->add_item(Variant::get_type_name(Variant::Type(i)), i); + type->add_item(Variant::get_type_name(Variant::Type(i))); } Button *add = memnew(Button); diff --git a/misc/travis/android-tools-linux.sh b/misc/travis/android-tools-linux.sh index 215b9fd159..d0c123ee6c 100755 --- a/misc/travis/android-tools-linux.sh +++ b/misc/travis/android-tools-linux.sh @@ -70,9 +70,10 @@ if [ ! -d $ANDROID_NDK_DIR ]; then echo fi -echo "Installing: Android Tools ..." mkdir -p ~/.android && echo "count=0" > ~/.android/repositories.cfg +echo "Installing: Accepting Licenses ..." yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager --licenses > /dev/null +echo "Installing: Android Build and Platform Tools ..." yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager 'tools' > /dev/null yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager 'platform-tools' > /dev/null yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager 'build-tools;28.0.3' > /dev/null diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub index b47377cbc4..8f4a8de895 100644 --- a/modules/freetype/SCsub +++ b/modules/freetype/SCsub @@ -66,7 +66,7 @@ if env['builtin_freetype']: env.Prepend(CPPPATH=[thirdparty_dir + "/include"]) env_freetype.Append(CPPDEFINES=['FT2_BUILD_LIBRARY', 'FT_CONFIG_OPTION_USE_PNG']) - if (env['target'] != 'release'): + if (env['target'] == 'debug'): env_freetype.Append(CPPDEFINES=['ZLIB_DEBUG']) # Also requires libpng headers diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index da6a52ff0d..9d229adb2a 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -89,8 +89,8 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) { // be more python-like - int current = tab_level.back()->get(); - tab_level.push_back(current); + IndentLevel current_level = indent_level.back()->get(); + indent_level.push_back(current_level); return true; //_set_error("newline expected after ':'."); //return false; @@ -105,12 +105,19 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { } else if (tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE) { int indent = tokenizer->get_token_line_indent(); - int current = tab_level.back()->get(); - if (indent <= current) { + int tabs = tokenizer->get_token_line_tab_indent(); + IndentLevel current_level = indent_level.back()->get(); + IndentLevel new_indent(indent, tabs); + if (new_indent.is_mixed(current_level)) { + _set_error("Mixed tabs and spaces in indentation."); return false; } - tab_level.push_back(indent); + if (indent <= current_level.indent) { + return false; + } + + indent_level.push_back(new_indent); tokenizer->advance(); return true; @@ -2225,7 +2232,7 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { } void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBranchNode *> &p_branches, bool p_static) { - int indent_level = tab_level.back()->get(); + IndentLevel current_level = indent_level.back()->get(); p_block->has_return = true; @@ -2240,7 +2247,7 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran if (error_set) return; - if (indent_level > tab_level.back()->get()) { + if (current_level.indent > indent_level.back()->get().indent) { break; // go back a level } @@ -2695,7 +2702,7 @@ void GDScriptParser::_transform_match_statment(MatchNode *p_match_statement) { void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { - int indent_level = tab_level.back()->get(); + IndentLevel current_level = indent_level.back()->get(); #ifdef DEBUG_ENABLED @@ -2708,9 +2715,13 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { bool is_first_line = true; while (true) { - if (!is_first_line && tab_level.back()->prev() && tab_level.back()->prev()->get() == indent_level) { + if (!is_first_line && indent_level.back()->prev() && indent_level.back()->prev()->get().indent == current_level.indent) { + if (indent_level.back()->prev()->get().is_mixed(current_level)) { + _set_error("Mixed tabs and spaces in indentation."); + return; + } // pythonic single-line expression, don't parse future lines - tab_level.pop_back(); + indent_level.pop_back(); p_block->end_line = tokenizer->get_token_line(); return; } @@ -2720,7 +2731,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { if (error_set) return; - if (indent_level > tab_level.back()->get()) { + if (current_level.indent > indent_level.back()->get().indent) { p_block->end_line = tokenizer->get_token_line(); return; //go back a level } @@ -2924,14 +2935,14 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE && _parse_newline()) ; - if (tab_level.back()->get() < indent_level) { //not at current indent level + if (indent_level.back()->get().indent < current_level.indent) { //not at current indent level p_block->end_line = tokenizer->get_token_line(); return; } if (tokenizer->get_token() == GDScriptTokenizer::TK_CF_ELIF) { - if (tab_level.back()->get() > indent_level) { + if (indent_level.back()->get().indent > current_level.indent) { _set_error("Invalid indentation."); return; @@ -2979,7 +2990,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CF_ELSE) { - if (tab_level.back()->get() > indent_level) { + if (indent_level.back()->get().indent > current_level.indent) { _set_error("Invalid indentation."); return; } @@ -3351,32 +3362,45 @@ bool GDScriptParser::_parse_newline() { if (tokenizer->get_token(1) != GDScriptTokenizer::TK_EOF && tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE) { + IndentLevel current_level = indent_level.back()->get(); int indent = tokenizer->get_token_line_indent(); - int current_indent = tab_level.back()->get(); + int tabs = tokenizer->get_token_line_tab_indent(); + IndentLevel new_level(indent, tabs); + + if (new_level.is_mixed(current_level)) { + _set_error("Mixed tabs and spaces in indentation."); + return false; + } - if (indent > current_indent) { + if (indent > current_level.indent) { _set_error("Unexpected indentation."); return false; } - if (indent < current_indent) { + if (indent < current_level.indent) { - while (indent < current_indent) { + while (indent < current_level.indent) { //exit block - if (tab_level.size() == 1) { + if (indent_level.size() == 1) { _set_error("Invalid indentation. Bug?"); return false; } - tab_level.pop_back(); + indent_level.pop_back(); - if (tab_level.back()->get() < indent) { + if (indent_level.back()->get().indent < indent) { _set_error("Unindent does not match any outer indentation level."); return false; } - current_indent = tab_level.back()->get(); + + if (indent_level.back()->get().is_mixed(current_level)) { + _set_error("Mixed tabs and spaces in indentation."); + return false; + } + + current_level = indent_level.back()->get(); } tokenizer->advance(); @@ -3474,7 +3498,7 @@ void GDScriptParser::_parse_extends(ClassNode *p_class) { void GDScriptParser::_parse_class(ClassNode *p_class) { - int indent_level = tab_level.back()->get(); + IndentLevel current_level = indent_level.back()->get(); while (true) { @@ -3482,7 +3506,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { if (error_set) return; - if (indent_level > tab_level.back()->get()) { + if (current_level.indent > indent_level.back()->get().indent) { p_class->end_line = tokenizer->get_token_line(); return; //go back a level } @@ -8562,8 +8586,8 @@ void GDScriptParser::clear() { validating = false; for_completion = false; error_set = false; - tab_level.clear(); - tab_level.push_back(0); + indent_level.clear(); + indent_level.push_back(IndentLevel(0, 0)); error_line = 0; error_column = 0; pending_newline = -1; diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 04ce9cf4c6..93557d745d 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -552,7 +552,27 @@ private: int pending_newline; - List<int> tab_level; + struct IndentLevel { + int indent; + int tabs; + + bool is_mixed(IndentLevel other) { + return ( + (indent == other.indent && tabs != other.tabs) || + (indent > other.indent && tabs < other.tabs) || + (indent < other.indent && tabs > other.tabs)); + } + + IndentLevel() : + indent(0), + tabs(0) {} + + IndentLevel(int p_indent, int p_tabs) : + indent(p_indent), + tabs(p_tabs) {} + }; + + List<IndentLevel> indent_level; String base_path; String self_path; diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 4730e9b6bc..23a86f8d2b 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -450,11 +450,11 @@ void GDScriptTokenizerText::_make_error(const String &p_error) { tk_rb_pos = (tk_rb_pos + 1) % TK_RB_SIZE; } -void GDScriptTokenizerText::_make_newline(int p_spaces) { +void GDScriptTokenizerText::_make_newline(int p_indentation, int p_tabs) { TokenData &tk = tk_rb[tk_rb_pos]; tk.type = TK_NEWLINE; - tk.constant = p_spaces; + tk.constant = Vector2(p_indentation, p_tabs); tk.line = line; tk.col = column; tk_rb_pos = (tk_rb_pos + 1) % TK_RB_SIZE; @@ -511,33 +511,6 @@ void GDScriptTokenizerText::_advance() { case ' ': INCPOS(1); continue; - case '\n': { - line++; - INCPOS(1); - column = 1; - int i = 0; - while (true) { - if (GETCHAR(i) == ' ') { - if (file_indent_type == INDENT_NONE) file_indent_type = INDENT_SPACES; - if (file_indent_type != INDENT_SPACES) { - _make_error("Spaces used for indentation in tab-indented file!"); - return; - } - } else if (GETCHAR(i) == '\t') { - if (file_indent_type == INDENT_NONE) file_indent_type = INDENT_TABS; - if (file_indent_type != INDENT_TABS) { - _make_error("Tabs used for indentation in space-indented file!"); - return; - } - } else { - break; // not indentation anymore - } - i++; - } - - _make_newline(i); - return; - } case '#': { // line comment skip #ifdef DEBUG_ENABLED String comment; @@ -565,33 +538,34 @@ void GDScriptTokenizerText::_advance() { ignore_warnings = true; } #endif // DEBUG_ENABLED + FALLTHROUGH; + } + case '\n': { + line++; INCPOS(1); + bool used_spaces = false; + int tabs = 0; column = 1; - line++; int i = 0; while (true) { if (GETCHAR(i) == ' ') { - if (file_indent_type == INDENT_NONE) file_indent_type = INDENT_SPACES; - if (file_indent_type != INDENT_SPACES) { - _make_error("Spaces used for indentation in tab-indented file!"); - return; - } + i++; + used_spaces = true; } else if (GETCHAR(i) == '\t') { - if (file_indent_type == INDENT_NONE) file_indent_type = INDENT_TABS; - if (file_indent_type != INDENT_TABS) { - _make_error("Tabs used for indentation in space-indented file!"); + if (used_spaces) { + _make_error("Spaces used before tabs on a line"); return; } + i++; + tabs++; } else { break; // not indentation anymore } - i++; } - _make_newline(i); + _make_newline(i, tabs); return; - - } break; + } case '/': { switch (GETCHAR(1)) { @@ -1108,7 +1082,6 @@ void GDScriptTokenizerText::set_code(const String &p_code) { ignore_warnings = false; #endif // DEBUG_ENABLED last_error = ""; - file_indent_type = INDENT_NONE; for (int i = 0; i < MAX_LOOKAHEAD + 1; i++) _advance(); } @@ -1183,7 +1156,17 @@ int GDScriptTokenizerText::get_token_line_indent(int p_offset) const { int ofs = (TK_RB_SIZE + tk_rb_pos + p_offset - MAX_LOOKAHEAD - 1) % TK_RB_SIZE; ERR_FAIL_COND_V(tk_rb[ofs].type != TK_NEWLINE, 0); - return tk_rb[ofs].constant; + return tk_rb[ofs].constant.operator Vector2().x; +} + +int GDScriptTokenizerText::get_token_line_tab_indent(int p_offset) const { + + ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, 0); + ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, 0); + + int ofs = (TK_RB_SIZE + tk_rb_pos + p_offset - MAX_LOOKAHEAD - 1) % TK_RB_SIZE; + ERR_FAIL_COND_V(tk_rb[ofs].type != TK_NEWLINE, 0); + return tk_rb[ofs].constant.operator Vector2().y; } String GDScriptTokenizerText::get_token_error(int p_offset) const { diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index 89d586b912..58749012b7 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -168,6 +168,7 @@ public: virtual int get_token_line(int p_offset = 0) const = 0; virtual int get_token_column(int p_offset = 0) const = 0; virtual int get_token_line_indent(int p_offset = 0) const = 0; + virtual int get_token_line_tab_indent(int p_offset = 0) const = 0; virtual String get_token_error(int p_offset = 0) const = 0; virtual void advance(int p_amount = 1) = 0; #ifdef DEBUG_ENABLED @@ -205,7 +206,7 @@ class GDScriptTokenizerText : public GDScriptTokenizer { }; void _make_token(Token p_type); - void _make_newline(int p_spaces = 0); + void _make_newline(int p_indentation = 0, int p_tabs = 0); void _make_identifier(const StringName &p_identifier); void _make_built_in_func(GDScriptFunctions::Function p_func); void _make_constant(const Variant &p_constant); @@ -222,11 +223,6 @@ class GDScriptTokenizerText : public GDScriptTokenizer { int tk_rb_pos; String last_error; bool error_flag; - enum { - INDENT_NONE, - INDENT_SPACES, - INDENT_TABS, - } file_indent_type; #ifdef DEBUG_ENABLED Vector<Pair<int, String> > warning_skips; @@ -245,6 +241,7 @@ public: virtual int get_token_line(int p_offset = 0) const; virtual int get_token_column(int p_offset = 0) const; virtual int get_token_line_indent(int p_offset = 0) const; + virtual int get_token_line_tab_indent(int p_offset = 0) const; virtual const Variant &get_token_constant(int p_offset = 0) const; virtual String get_token_error(int p_offset = 0) const; virtual void advance(int p_amount = 1); @@ -283,6 +280,7 @@ public: virtual int get_token_line(int p_offset = 0) const; virtual int get_token_column(int p_offset = 0) const; virtual int get_token_line_indent(int p_offset = 0) const; + virtual int get_token_line_tab_indent(int p_offset = 0) const { return 0; } virtual const Variant &get_token_constant(int p_offset = 0) const; virtual String get_token_error(int p_offset = 0) const; virtual void advance(int p_amount = 1); diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index 1bd3d72066..b762868f2c 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -217,6 +217,14 @@ Deprecated, use [member mesh_library] instead. </member> </members> + <signals> + <signal name="cell_size_changed"> + <argument index="0" name="cell_size" type="Vector3"> + </argument> + <description> + </description> + </signal> + </signals> <constants> <constant name="INVALID_CELL_ITEM" value="-1"> Invalid cell item that can be used in [method set_cell_item] to clear cells (or represent an empty cell in [method get_cell_item]). diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index b36afd4386..47ac0de7f9 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -227,10 +227,10 @@ Ref<MeshLibrary> GridMap::get_mesh_library() const { } void GridMap::set_cell_size(const Vector3 &p_size) { - ERR_FAIL_COND(p_size.x < 0.001 || p_size.y < 0.001 || p_size.z < 0.001); cell_size = p_size; _recreate_octant_data(); + emit_signal("cell_size_changed", cell_size); } Vector3 GridMap::get_cell_size() const { @@ -902,6 +902,8 @@ void GridMap::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); BIND_CONSTANT(INVALID_CELL_ITEM); + + ADD_SIGNAL(MethodInfo("cell_size_changed", PropertyInfo(Variant::VECTOR3, "cell_size"))); } void GridMap::set_clip(bool p_enabled, bool p_clip_above, int p_floor, Vector3::Axis p_axis) { diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 804c57fc6e..f79aea9531 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -276,6 +276,7 @@ void GridMapEditor::_update_cursor_transform() { cursor_transform = Transform(); cursor_transform.origin = cursor_origin; cursor_transform.basis.set_orthogonal_index(cursor_rot); + cursor_transform.basis *= node->get_cell_scale(); cursor_transform = node->get_global_transform() * cursor_transform; if (cursor_instance.is_valid()) { @@ -298,7 +299,7 @@ void GridMapEditor::_update_selection_transform() { } Transform xf; - xf.scale(Vector3(1, 1, 1) * (Vector3(1, 1, 1) + (selection.end - selection.begin)) * node->get_cell_size()); + xf.scale((Vector3(1, 1, 1) + (selection.end - selection.begin)) * node->get_cell_size()); xf.origin = selection.begin * node->get_cell_size(); VisualServer::get_singleton()->instance_set_transform(selection_instance, node->get_global_transform() * xf); @@ -595,7 +596,7 @@ void GridMapEditor::_update_paste_indicator() { Basis item_rot; item_rot.set_orthogonal_index(item.orientation); - xf.basis = item_rot * xf.basis; + xf.basis = item_rot * xf.basis * node->get_cell_scale(); VisualServer::get_singleton()->instance_set_transform(item.instance, node->get_global_transform() * xf); } @@ -933,9 +934,10 @@ void GridMapEditor::update_palette() { } void GridMapEditor::edit(GridMap *p_gridmap) { + if (!p_gridmap && node) + node->disconnect("cell_size_changed", this, "_draw_grids"); node = p_gridmap; - VS *vs = VS::get_singleton(); input_action = INPUT_NONE; selection.active = false; @@ -961,75 +963,13 @@ void GridMapEditor::edit(GridMap *p_gridmap) { set_process(true); - Vector3 edited_floor = p_gridmap->has_meta("_editor_floor_") ? p_gridmap->get_meta("_editor_floor_") : Variant(); clip_mode = p_gridmap->has_meta("_editor_clip_") ? ClipMode(p_gridmap->get_meta("_editor_clip_").operator int()) : CLIP_DISABLED; - for (int i = 0; i < 3; i++) { - if (vs->mesh_get_surface_count(grid[i]) > 0) - vs->mesh_remove_surface(grid[i], 0); - edit_floor[i] = edited_floor[i]; - } - - { - - // Update grids. - indicator_mat.instance(); - indicator_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - indicator_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - indicator_mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - indicator_mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - indicator_mat->set_albedo(Color(0.8, 0.5, 0.1)); - - Vector<Vector3> grid_points[3]; - Vector<Color> grid_colors[3]; - - float cell_size[3] = { p_gridmap->get_cell_size().x, p_gridmap->get_cell_size().y, p_gridmap->get_cell_size().z }; - - for (int i = 0; i < 3; i++) { - - Vector3 axis; - axis[i] = 1; - Vector3 axis_n1; - axis_n1[(i + 1) % 3] = cell_size[(i + 1) % 3]; - Vector3 axis_n2; - axis_n2[(i + 2) % 3] = cell_size[(i + 2) % 3]; - - for (int j = -GRID_CURSOR_SIZE; j <= GRID_CURSOR_SIZE; j++) { - - for (int k = -GRID_CURSOR_SIZE; k <= GRID_CURSOR_SIZE; k++) { - - Vector3 p = axis_n1 * j + axis_n2 * k; - float trans = Math::pow(MAX(0, 1.0 - (Vector2(j, k).length() / GRID_CURSOR_SIZE)), 2); - - Vector3 pj = axis_n1 * (j + 1) + axis_n2 * k; - float transj = Math::pow(MAX(0, 1.0 - (Vector2(j + 1, k).length() / GRID_CURSOR_SIZE)), 2); - - Vector3 pk = axis_n1 * j + axis_n2 * (k + 1); - float transk = Math::pow(MAX(0, 1.0 - (Vector2(j, k + 1).length() / GRID_CURSOR_SIZE)), 2); - - grid_points[i].push_back(p); - grid_points[i].push_back(pk); - grid_colors[i].push_back(Color(1, 1, 1, trans)); - grid_colors[i].push_back(Color(1, 1, 1, transk)); - - grid_points[i].push_back(p); - grid_points[i].push_back(pj); - grid_colors[i].push_back(Color(1, 1, 1, trans)); - grid_colors[i].push_back(Color(1, 1, 1, transj)); - } - } - - Array d; - d.resize(VS::ARRAY_MAX); - d[VS::ARRAY_VERTEX] = grid_points[i]; - d[VS::ARRAY_COLOR] = grid_colors[i]; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], VisualServer::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); - } - } - + _draw_grids(node->get_cell_size()); update_grid(); _update_clip(); + + node->connect("cell_size_changed", this, "_draw_grids"); } void GridMapEditor::_update_clip() { @@ -1059,6 +999,61 @@ void GridMapEditor::update_grid() { updating = false; } +void GridMapEditor::_draw_grids(const Vector3 &cell_size) { + Vector3 edited_floor = node->has_meta("_editor_floor_") ? node->get_meta("_editor_floor_") : Variant(); + + for (int i = 0; i < 3; i++) { + if (VS::get_singleton()->mesh_get_surface_count(grid[i]) > 0) + VS::get_singleton()->mesh_remove_surface(grid[i], 0); + edit_floor[i] = edited_floor[i]; + } + + Vector<Vector3> grid_points[3]; + Vector<Color> grid_colors[3]; + + for (int i = 0; i < 3; i++) { + + Vector3 axis; + axis[i] = 1; + Vector3 axis_n1; + axis_n1[(i + 1) % 3] = cell_size[(i + 1) % 3]; + Vector3 axis_n2; + axis_n2[(i + 2) % 3] = cell_size[(i + 2) % 3]; + + for (int j = -GRID_CURSOR_SIZE; j <= GRID_CURSOR_SIZE; j++) { + + for (int k = -GRID_CURSOR_SIZE; k <= GRID_CURSOR_SIZE; k++) { + + Vector3 p = axis_n1 * j + axis_n2 * k; + float trans = Math::pow(MAX(0, 1.0 - (Vector2(j, k).length() / GRID_CURSOR_SIZE)), 2); + + Vector3 pj = axis_n1 * (j + 1) + axis_n2 * k; + float transj = Math::pow(MAX(0, 1.0 - (Vector2(j + 1, k).length() / GRID_CURSOR_SIZE)), 2); + + Vector3 pk = axis_n1 * j + axis_n2 * (k + 1); + float transk = Math::pow(MAX(0, 1.0 - (Vector2(j, k + 1).length() / GRID_CURSOR_SIZE)), 2); + + grid_points[i].push_back(p); + grid_points[i].push_back(pk); + grid_colors[i].push_back(Color(1, 1, 1, trans)); + grid_colors[i].push_back(Color(1, 1, 1, transk)); + + grid_points[i].push_back(p); + grid_points[i].push_back(pj); + grid_colors[i].push_back(Color(1, 1, 1, trans)); + grid_colors[i].push_back(Color(1, 1, 1, transj)); + } + } + + Array d; + d.resize(VS::ARRAY_MAX); + d[VS::ARRAY_VERTEX] = grid_points[i]; + d[VS::ARRAY_COLOR] = grid_colors[i]; + VisualServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], VisualServer::PRIMITIVE_LINES, d); + VisualServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); + } +} + void GridMapEditor::_notification(int p_what) { switch (p_what) { @@ -1197,6 +1192,7 @@ void GridMapEditor::_bind_methods() { ClassDB::bind_method("_node_removed", &GridMapEditor::_node_removed); ClassDB::bind_method(D_METHOD("_set_display_mode", "mode"), &GridMapEditor::_set_display_mode); + ClassDB::bind_method("_draw_grids", &GridMapEditor::_draw_grids); } GridMapEditor::GridMapEditor(EditorNode *p_editor) { @@ -1472,6 +1468,13 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { _set_selection(false); updating = false; accumulated_floor_delta = 0.0; + + indicator_mat.instance(); + indicator_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + indicator_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + indicator_mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + indicator_mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + indicator_mat->set_albedo(Color(0.8, 0.5, 0.1)); } GridMapEditor::~GridMapEditor() { diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h index 48a07e9c7f..42e62f2842 100644 --- a/modules/gridmap/grid_map_editor_plugin.h +++ b/modules/gridmap/grid_map_editor_plugin.h @@ -201,7 +201,8 @@ class GridMapEditor : public VBoxContainer { EditorNode *editor; - void update_grid(); + void update_grid(); // Change which and where the grid is displayed + void _draw_grids(const Vector3 &cell_size); void _configure(); void _menu_option(int); void update_palette(); diff --git a/platform/windows/detect.py b/platform/windows/detect.py index f4390a9882..9a2b2bcb98 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -350,7 +350,7 @@ def configure_mingw(env): env.Append(CPPDEFINES=[('WINVER', env['target_win_version']), ('_WIN32_WINNT', env['target_win_version'])]) env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt', 'avrt', 'uuid']) - env.Append(CPPDEFINES=['MINGW_ENABLED']) + env.Append(CPPDEFINES=['MINGW_ENABLED', ('MINGW_HAS_SECURE_API', 1)]) # resrc env.Append(BUILDERS={'RES': env.Builder(action=build_res_file, suffix='.o', src_suffix='.rc')}) diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 1f9793190d..a7d936fcd3 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -281,7 +281,7 @@ void Tween::_bind_methods() { BIND_ENUM_CONSTANT(EASE_OUT_IN); } -Variant &Tween::_get_initial_val(InterpolateData &p_data) { +Variant Tween::_get_initial_val(const InterpolateData &p_data) const { // What type of data are we interpolating? switch (p_data.type) { @@ -299,7 +299,7 @@ Variant &Tween::_get_initial_val(InterpolateData &p_data) { ERR_FAIL_COND_V(object == NULL, p_data.initial_val); // Are we targeting a property or a method? - static Variant initial_val; + Variant initial_val; if (p_data.type == TARGETING_PROPERTY) { // Get the property from the target object bool valid = false; @@ -322,6 +322,41 @@ Variant &Tween::_get_initial_val(InterpolateData &p_data) { return p_data.delta_val; } +Variant Tween::_get_final_val(const InterpolateData &p_data) const { + switch (p_data.type) { + case FOLLOW_PROPERTY: + case FOLLOW_METHOD: { + // Get the object that is being followed + Object *target = ObjectDB::get_instance(p_data.target_id); + ERR_FAIL_COND_V(target == NULL, p_data.initial_val); + + // We want to figure out the final value + Variant final_val; + if (p_data.type == FOLLOW_PROPERTY) { + // Read the property as-is + bool valid = false; + final_val = target->get_indexed(p_data.target_key, &valid); + ERR_FAIL_COND_V(!valid, p_data.initial_val); + } else { + // We're looking at a method. Call the method on the target object + Variant::CallError error; + final_val = target->call(p_data.target_key[0], NULL, 0, error); + ERR_FAIL_COND_V(error.error != Variant::CallError::CALL_OK, p_data.initial_val); + } + + // If we're looking at an INT value, instead convert it to a REAL + // This is better for interpolation + if (final_val.get_type() == Variant::INT) final_val = final_val.operator real_t(); + + return final_val; + } + default: { + // If we're not following a final value/method, use the final value from the data + return p_data.final_val; + } + } +} + Variant &Tween::_get_delta_val(InterpolateData &p_data) { // What kind of data are we interpolating? @@ -384,7 +419,7 @@ Variant &Tween::_get_delta_val(InterpolateData &p_data) { Variant Tween::_run_equation(InterpolateData &p_data) { // Get the initial and delta values from the data - Variant &initial_val = _get_initial_val(p_data); + Variant initial_val = _get_initial_val(p_data); Variant &delta_val = _get_delta_val(p_data); Variant result; @@ -718,7 +753,8 @@ void Tween::_tween_process(float p_delta) { // Is the tween now finished? if (data.finish) { // Set it to the final value directly - _apply_tween_value(data, data.final_val); + Variant final_val = _get_final_val(data); + _apply_tween_value(data, final_val); // Mark the tween as completed and emit the signal data.elapsed = 0; diff --git a/scene/animation/tween.h b/scene/animation/tween.h index 64ce099ecd..574238f5c9 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -127,7 +127,8 @@ private: real_t _run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d); Variant &_get_delta_val(InterpolateData &p_data); - Variant &_get_initial_val(InterpolateData &p_data); + Variant _get_initial_val(const InterpolateData &p_data) const; + Variant _get_final_val(const InterpolateData &p_data) const; Variant _run_equation(InterpolateData &p_data); bool _calc_delta_val(const Variant &p_initial_val, const Variant &p_final_val, Variant &p_delta_val); bool _apply_tween_value(InterpolateData &p_data, Variant &value); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 8c19255fd0..0331046492 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1721,6 +1721,41 @@ void RichTextLabel::push_font(const Ref<Font> &p_font) { _add_item(item, true); } +void RichTextLabel::push_normal() { + Ref<Font> normal_font = get_font("normal_font"); + ERR_FAIL_COND(normal_font.is_null()); + + push_font(normal_font); +} + +void RichTextLabel::push_bold() { + Ref<Font> bold_font = get_font("bold_font"); + ERR_FAIL_COND(bold_font.is_null()); + + push_font(bold_font); +} + +void RichTextLabel::push_bold_italics() { + Ref<Font> bold_italics_font = get_font("bold_italics_font"); + ERR_FAIL_COND(bold_italics_font.is_null()); + + push_font(bold_italics_font); +} + +void RichTextLabel::push_italics() { + Ref<Font> italics_font = get_font("italics_font"); + ERR_FAIL_COND(italics_font.is_null()); + + push_font(italics_font); +} + +void RichTextLabel::push_mono() { + Ref<Font> mono_font = get_font("mono_font"); + ERR_FAIL_COND(mono_font.is_null()); + + push_font(mono_font); +} + void RichTextLabel::push_color(const Color &p_color) { ERR_FAIL_COND(current->type == ITEM_TABLE); @@ -2636,6 +2671,11 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("newline"), &RichTextLabel::add_newline); ClassDB::bind_method(D_METHOD("remove_line", "line"), &RichTextLabel::remove_line); ClassDB::bind_method(D_METHOD("push_font", "font"), &RichTextLabel::push_font); + ClassDB::bind_method(D_METHOD("push_normal"), &RichTextLabel::push_normal); + ClassDB::bind_method(D_METHOD("push_bold"), &RichTextLabel::push_bold); + ClassDB::bind_method(D_METHOD("push_bold_italics"), &RichTextLabel::push_bold_italics); + ClassDB::bind_method(D_METHOD("push_italics"), &RichTextLabel::push_italics); + ClassDB::bind_method(D_METHOD("push_mono"), &RichTextLabel::push_mono); ClassDB::bind_method(D_METHOD("push_color", "color"), &RichTextLabel::push_color); ClassDB::bind_method(D_METHOD("push_align", "align"), &RichTextLabel::push_align); ClassDB::bind_method(D_METHOD("push_indent", "level"), &RichTextLabel::push_indent); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 6cd69b9187..b9837fdfcc 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -411,6 +411,11 @@ public: void add_newline(); bool remove_line(const int p_line); void push_font(const Ref<Font> &p_font); + void push_normal(); + void push_bold(); + void push_bold_italics(); + void push_italics(); + void push_mono(); void push_color(const Color &p_color); void push_underline(); void push_strikethrough(); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index a7e87a28ae..ae9c7c88d8 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -958,6 +958,10 @@ void TextEdit::_notification(int p_what) { } } + if (minimap_line < 0 || minimap_line >= (int)text.size()) { + break; + } + Map<int, HighlighterInfo> color_map; if (syntax_coloring) { color_map = _get_line_syntax_highlighting(minimap_line); diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 0dcc184a1d..1a053a18c9 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -432,7 +432,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_font("font", "TextEdit", default_font); - theme->set_color("background_color", "TextEdit", Color(0, 0, 0)); + theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0)); theme->set_color("completion_background_color", "TextEdit", Color(0.17, 0.16, 0.2)); theme->set_color("completion_selected_color", "TextEdit", Color(0.26, 0.26, 0.27)); theme->set_color("completion_existing_color", "TextEdit", Color(0.87, 0.87, 0.87, 0.13)); diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index 7d575c57ae..ba98e14d2e 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -260,12 +260,14 @@ void BodySW::set_mode(PhysicsServer::BodyMode p_mode) { _inv_mass = mass > 0 ? (1.0 / mass) : 0; _set_static(false); + set_active(true); } break; case PhysicsServer::BODY_MODE_CHARACTER: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; _set_static(false); + set_active(true); angular_velocity = Vector3(); } break; } diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index f9939e3843..de1dfc9ee7 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -238,6 +238,7 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { _inv_mass = mass > 0 ? (1.0 / mass) : 0; _inv_inertia = inertia > 0 ? (1.0 / inertia) : 0; _set_static(false); + set_active(true); } break; case Physics2DServer::BODY_MODE_CHARACTER: { @@ -245,6 +246,7 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { _inv_mass = mass > 0 ? (1.0 / mass) : 0; _inv_inertia = 0; _set_static(false); + set_active(true); angular_velocity = 0; } break; } |