diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000000..2ef335fe020 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,126 @@ +# Engine build CI +name: Godot CI + +on: + # will build EVERY pull request + pull_request: + + # will only build explicit branches + push: + branches: [ master, 3.2, 3.1, 3.0 ] + +# Global Cache Settings +# SCONS_CACHE for windows must be set in the build environment +env: + SCONS_CACHE_MSVC_CONFIG: true + SCONS_CACHE_LIMIT: 8192 +jobs: + windows-editor: + # Windows 10 with latest image + runs-on: "windows-latest" + + # Windows Editor - checkout with the plugin + name: Windows Editor (target=release_debug, tools=yes) + + steps: + - uses: actions/checkout@v2 + + # Upload cache on completion and check it out now + # Editing this is pretty dangerous for windows since it can break and needs properly tested with a fresh cache. + # Linux with this will work reliably, so not as bad to edit for Linux. + - name: Load .scons_cache directory + id: windows-editor-cache + uses: RevoluPowered/cache@v2.1 + with: + path: /.scons_cache/ + key: ${{runner.os}}-editor-${{github.sha}} + restore-keys: | + ${{runner.os}}-editor-${{github.sha}} + ${{runner.os}}-editor + ${{runner.os}} + + # Use python 3.x release (works cross platform; best to keep self contained in it's own step) + - name: Set up Python 3.x + uses: actions/setup-python@v2 + with: + # Semantic version range syntax or exact version of a Python version + python-version: '3.x' + # Optional - x64 or x86 architecture, defaults to x64 + architecture: 'x64' + + # Setup scons, print python version and scons version info, so if anything is broken it won't run the build. + - name: Configuring Python packages + run: | + python -c "import sys; print(sys.version)" + python -m pip install scons pywin32 + python --version + scons --version + + # We should always be explicit with our flags usage here since it's gonna be sure to always set those flags + - name: Compilation + env: + SCONS_CACHE: /.scons_cache/ + run: | + scons -j2 verbose=yes warnings=all werror=yes platform=windows tools=yes target=release_debug + +# Build Product Upload (tested and working) +# sorry this is disabled until github can give us some more space as we would hit our limit very quickly +# tested this code and it works fine so just enable it to get them back +# - name: publishing godot windows-editor +# uses: actions/upload-artifact@v1 +# with: +# name: windows-editor (x64) +# path: bin/godot.windows.opt.tools.64.exe + + + windows-template: + runs-on: "windows-latest" + name: Windows Template (target=release, tools=no) + + steps: + - uses: actions/checkout@v2 + + # Upload cache on completion and check it out now + # Editing this is pretty dangerous for windows since it can break and needs properly tested with a fresh cache. + # Linux with this will work reliably, so not as bad to edit for Linux. + - name: Load .scons_cache directory + id: windows-template-cache + uses: RevoluPowered/cache@v2.1 + with: + path: /.scons_cache/ + key: ${{runner.os}}-template-${{github.sha}} + restore-keys: | + ${{runner.os}}-template-${{github.sha}} + ${{runner.os}}-template + ${{runner.os}} + + # Use python 3.x release (works cross platform) + - name: Set up Python 3.x + uses: actions/setup-python@v2 + with: + # Semantic version range syntax or exact version of a Python version + python-version: '3.x' + # Optional - x64 or x86 architecture, defaults to x64 + architecture: 'x64' + + # You can test your matrix by printing the current Python version + - name: Configuring Python packages + run: | + python -c "import sys; print(sys.version)" + python -m pip install scons pywin32 + python --version + scons --version + - name: Compilation + env: + SCONS_CACHE: /.scons_cache/ + run: | + scons -j2 verbose=yes warnings=all werror=yes platform=windows target=release tools=no + +# Build Product Upload (tested and working) +# sorry this is disabled until github can give us some more space as we would hit our limit very quickly +# tested this code and it works fine so just enable it to get them back +# - name: publishing godot windows-template +# uses: actions/upload-artifact@v1 +# with: +# name: windows-template (x64) +# path: bin/godot.windows.opt.64.exe diff --git a/SConstruct b/SConstruct index b3d033dc90d..207254713a2 100644 --- a/SConstruct +++ b/SConstruct @@ -402,6 +402,7 @@ if selected_platform in platform_list: all_plus_warnings = ["-Wwrite-strings"] if methods.using_gcc(env): + env.Append(CCFLAGS=["-Wno-misleading-indentation"]) if version[0] >= 7: shadow_local_warning = ["-Wshadow-local"] diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 61348769fab..a87bed3502d 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -482,6 +482,14 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo _load_settings_text(custom_settings); } } + // Using GLOBAL_GET on every block for compressing can be slow, so assigning here. + Compression::zstd_long_distance_matching = GLOBAL_GET("compression/formats/zstd/long_distance_matching"); + Compression::zstd_level = GLOBAL_GET("compression/formats/zstd/compression_level"); + Compression::zstd_window_log_size = GLOBAL_GET("compression/formats/zstd/window_log_size"); + + Compression::zlib_level = GLOBAL_GET("compression/formats/zlib/compression_level"); + + Compression::gzip_level = GLOBAL_GET("compression/formats/gzip/compression_level"); return err; } @@ -997,6 +1005,8 @@ void ProjectSettings::_bind_methods() { } ProjectSettings::ProjectSettings() { + // Initialization of engine variables should be done in the setup() method, + // so that the values can be overridden from project.godot or project.binary. singleton = this; last_order = NO_BUILTIN_ORDER_BASE; @@ -1200,18 +1210,17 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("debug/settings/profiler/max_functions", 16384); custom_prop_info["debug/settings/profiler/max_functions"] = PropertyInfo(Variant::INT, "debug/settings/profiler/max_functions", PROPERTY_HINT_RANGE, "128,65535,1"); - //assigning here, because using GLOBAL_GET on every block for compressing can be slow - Compression::zstd_long_distance_matching = GLOBAL_DEF("compression/formats/zstd/long_distance_matching", false); + GLOBAL_DEF("compression/formats/zstd/long_distance_matching", Compression::zstd_long_distance_matching); custom_prop_info["compression/formats/zstd/long_distance_matching"] = PropertyInfo(Variant::BOOL, "compression/formats/zstd/long_distance_matching"); - Compression::zstd_level = GLOBAL_DEF("compression/formats/zstd/compression_level", 3); + GLOBAL_DEF("compression/formats/zstd/compression_level", Compression::zstd_level); custom_prop_info["compression/formats/zstd/compression_level"] = PropertyInfo(Variant::INT, "compression/formats/zstd/compression_level", PROPERTY_HINT_RANGE, "1,22,1"); - Compression::zstd_window_log_size = GLOBAL_DEF("compression/formats/zstd/window_log_size", 27); + GLOBAL_DEF("compression/formats/zstd/window_log_size", Compression::zstd_window_log_size); custom_prop_info["compression/formats/zstd/window_log_size"] = PropertyInfo(Variant::INT, "compression/formats/zstd/window_log_size", PROPERTY_HINT_RANGE, "10,30,1"); - Compression::zlib_level = GLOBAL_DEF("compression/formats/zlib/compression_level", Z_DEFAULT_COMPRESSION); + GLOBAL_DEF("compression/formats/zlib/compression_level", Compression::zlib_level); custom_prop_info["compression/formats/zlib/compression_level"] = PropertyInfo(Variant::INT, "compression/formats/zlib/compression_level", PROPERTY_HINT_RANGE, "-1,9,1"); - Compression::gzip_level = GLOBAL_DEF("compression/formats/gzip/compression_level", Z_DEFAULT_COMPRESSION); + GLOBAL_DEF("compression/formats/gzip/compression_level", Compression::gzip_level); custom_prop_info["compression/formats/gzip/compression_level"] = PropertyInfo(Variant::INT, "compression/formats/gzip/compression_level", PROPERTY_HINT_RANGE, "-1,9,1"); // Would ideally be defined in an Android-specific file, but then it doesn't appear in the docs diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index 86611bd20af..43c77431526 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -55,6 +55,27 @@ void EditorAssetInstaller::_update_subitems(TreeItem *p_item, bool p_check, bool } } +void EditorAssetInstaller::_uncheck_parent(TreeItem *p_item) { + if (!p_item) { + return; + } + + bool any_checked = false; + TreeItem *item = p_item->get_children(); + while (item) { + if (item->is_checked(0)) { + any_checked = true; + break; + } + item = item->get_next(); + } + + if (!any_checked) { + p_item->set_checked(0, false); + _uncheck_parent(p_item->get_parent()); + } +} + void EditorAssetInstaller::_item_edited() { if (updating) @@ -67,7 +88,7 @@ void EditorAssetInstaller::_item_edited() { String path = item->get_metadata(0); updating = true; - if (path == String()) { //a dir + if (path == String() || item == tree->get_root()) { //a dir or root _update_subitems(item, item->is_checked(0), true); } @@ -76,6 +97,8 @@ void EditorAssetInstaller::_item_edited() { item->set_checked(0, true); item = item->get_parent(); } + } else { + _uncheck_parent(item->get_parent()); } updating = false; } diff --git a/editor/editor_asset_installer.h b/editor/editor_asset_installer.h index 840e7802643..7d6760a86ac 100644 --- a/editor/editor_asset_installer.h +++ b/editor/editor_asset_installer.h @@ -43,6 +43,7 @@ class EditorAssetInstaller : public ConfirmationDialog { Map status_map; bool updating; void _update_subitems(TreeItem *p_item, bool p_check, bool p_first = false); + void _uncheck_parent(TreeItem *p_item); void _item_edited(); virtual void ok_pressed(); diff --git a/methods.py b/methods.py index ee3d8369576..1d60884a816 100644 --- a/methods.py +++ b/methods.py @@ -201,14 +201,15 @@ void unregister_module_types() { def convert_custom_modules_path(path): if not path: return path + path = os.path.realpath(os.path.expanduser(os.path.expandvars(path))) err_msg = "Build option 'custom_modules' must %s" if not os.path.isdir(path): raise ValueError(err_msg % "point to an existing directory.") - if os.path.realpath(path) == os.path.realpath("modules"): + if path == os.path.realpath("modules"): raise ValueError(err_msg % "be a directory other than built-in `modules` directory.") if is_module(path): raise ValueError(err_msg % "point to a directory with modules, not a single module.") - return os.path.realpath(os.path.expanduser(path)) + return path def disable_module(self): diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml index f90b38e0637..a2cef94cd65 100644 --- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml +++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml @@ -128,7 +128,7 @@ Enforce ordered packets when using [constant NetworkedMultiplayerPeer.TRANSFER_MODE_UNRELIABLE] (thus behaving similarly to [constant NetworkedMultiplayerPeer.TRANSFER_MODE_UNRELIABLE_ORDERED]). This is the only way to use ordering with the RPC system. - The number of channels to be used by ENet. Channels are used to separate different kinds of data. In reliable or ordered mode, for example, the packet delivery order is ensured on a per channel basis. + The number of channels to be used by ENet. Channels are used to separate different kinds of data. In reliable or ordered mode, for example, the packet delivery order is ensured on a per-channel basis. This is done to combat latency and reduces ordering restrictions on packets. The delivery status of a packet in one channel won't stall the delivery of other packets in another channel. The compression method used for network packets. These have different tradeoffs of compression speed versus bandwidth, you may need to test which one works best for your use case if you use compression at all. @@ -141,7 +141,7 @@ Enable or disable the server feature that notifies clients of other peers' connection/disconnection, and relays messages between them. When this option is [code]false[/code], clients won't be automatically notified of other peers and won't be able to send them packets through the server. - Set the default channel to be used to transfer data. By default, this value is [code]-1[/code] which means that ENet will only use 2 channels, one for reliable and one for unreliable packets. Channel [code]0[/code] is reserved, and cannot be used. Setting this member to any value between [code]0[/code] and [member channel_count] (excluded) will force ENet to use that channel for sending data. + Set the default channel to be used to transfer data. By default, this value is [code]-1[/code] which means that ENet will only use 2 channels: one for reliable packets, and one for unreliable packets. The channel [code]0[/code] is reserved and cannot be used. Setting this member to any value between [code]0[/code] and [member channel_count] (excluded) will force ENet to use that channel for sending data. See [member channel_count] for more information about ENet channels. diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 91f5af89631..490fd9b0e3f 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -849,10 +849,22 @@ void GraphEdit::_gui_input(const Ref &p_ev) { r.size *= zoom; bool in_box = r.intersects(box_selecting_rect); - if (in_box) + if (in_box) { + if (!gn->is_selected() && box_selection_mode_additive) { + emit_signal("node_selected", gn); + } else if (gn->is_selected() && !box_selection_mode_additive) { + emit_signal("node_unselected", gn); + } gn->set_selected(box_selection_mode_additive); - else - gn->set_selected(previus_selected.find(gn) != NULL); + } else { + bool select = (previus_selected.find(gn) != NULL); + if (gn->is_selected() && !select) { + emit_signal("node_unselected", gn); + } else if (!gn->is_selected() && select) { + emit_signal("node_selected", gn); + } + gn->set_selected(select); + } } top_layer->update(); @@ -870,7 +882,13 @@ void GraphEdit::_gui_input(const Ref &p_ev) { if (!gn) continue; - gn->set_selected(previus_selected.find(gn) != NULL); + bool select = (previus_selected.find(gn) != NULL); + if (gn->is_selected() && !select) { + emit_signal("node_unselected", gn); + } else if (!gn->is_selected() && select) { + emit_signal("node_selected", gn); + } + gn->set_selected(select); } top_layer->update(); } else { @@ -893,6 +911,7 @@ void GraphEdit::_gui_input(const Ref &p_ev) { Rect2 r = gn->get_rect(); r.size *= zoom; if (r.has_point(b->get_position())) { + emit_signal("node_unselected", gn); gn->set_selected(false); } }