diff options
-rw-r--r-- | core/core_bind.cpp | 3 | ||||
-rw-r--r-- | editor/editor_asset_installer.cpp | 38 | ||||
-rw-r--r-- | editor/editor_asset_installer.h | 6 | ||||
-rw-r--r-- | editor/editor_zoom_widget.cpp | 86 | ||||
-rw-r--r-- | editor/editor_zoom_widget.h | 2 | ||||
-rw-r--r-- | editor/plugins/asset_library_editor_plugin.cpp | 5 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.cpp | 34 | ||||
-rw-r--r-- | scene/animation/animation_blend_space_2d.cpp | 4 |
8 files changed, 138 insertions, 40 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp index a3349444c4..9a58528bd7 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -1729,10 +1729,11 @@ void _Thread::_start_func(void *ud) { memdelete(tud); Callable::CallError ce; const Variant *arg[1] = { &t->userdata }; + int argc = (int)(arg[0]->get_type() != Variant::NIL); Thread::set_name(t->target_method); - t->ret = t->target_instance->call(t->target_method, arg, 1, ce); + t->ret = t->target_instance->call(t->target_method, arg, argc, ce); if (ce.error != Callable::CallError::CALL_OK) { String reason; switch (ce.error) { diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index 83319ee5a5..dc90f26d48 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -112,7 +112,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { unzFile pkg = unzOpen2(p_path.utf8().get_data(), &io); if (!pkg) { - error->set_text(TTR("Error opening package file, not in ZIP format.")); + error->set_text(vformat(TTR("Error opening asset file for \"%s\" (not in ZIP format)."), asset_name)); return; } @@ -196,6 +196,8 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { root->set_editable(0, true); Map<String, TreeItem *> dir_map; + int num_file_conflicts = 0; + for (Set<String>::Element *E = files_sorted.front(); E; E = E->next()) { String path = E->get(); int depth = p_depth; @@ -254,8 +256,9 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { String res_path = "res://" + path; if (FileAccess::exists(res_path)) { + num_file_conflicts += 1; ti->set_custom_color(0, tree->get_theme_color("error_color", "Editor")); - ti->set_tooltip(0, vformat(TTR("%s (Already Exists)"), res_path)); + ti->set_tooltip(0, vformat(TTR("%s (already exists)"), res_path)); ti->set_checked(0, false); } else { ti->set_tooltip(0, res_path); @@ -266,6 +269,13 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { status_map[E->get()] = ti; } + + if (num_file_conflicts >= 1) { + asset_contents->set_text(vformat(TTR("Contents of asset \"%s\" - %d file(s) conflict with your project:"), asset_name, num_file_conflicts)); + } else { + asset_contents->set_text(vformat(TTR("Contents of asset \"%s\" - No files conflict with your project:"), asset_name)); + } + popup_centered_ratio(); updating = false; } @@ -276,7 +286,7 @@ void EditorAssetInstaller::ok_pressed() { unzFile pkg = unzOpen2(package_path.utf8().get_data(), &io); if (!pkg) { - error->set_text(TTR("Error opening package file, not in ZIP format.")); + error->set_text(vformat(TTR("Error opening asset file for \"%s\" (not in ZIP format)."), asset_name)); return; } @@ -343,10 +353,10 @@ void EditorAssetInstaller::ok_pressed() { unzClose(pkg); if (failed_files.size()) { - String msg = TTR("The following files failed extraction from package:") + "\n\n"; + String msg = vformat(TTR("The following files failed extraction from asset \"%s\":"), asset_name) + "\n\n"; for (int i = 0; i < failed_files.size(); i++) { if (i > 15) { - msg += "\n" + vformat(TTR("And %s more files."), itos(failed_files.size() - i)); + msg += "\n" + vformat(TTR("(and %s more files)"), itos(failed_files.size() - i)); break; } msg += failed_files[i]; @@ -356,12 +366,20 @@ void EditorAssetInstaller::ok_pressed() { } } else { if (EditorNode::get_singleton() != nullptr) { - EditorNode::get_singleton()->show_warning(TTR("Package installed successfully!"), TTR("Success!")); + EditorNode::get_singleton()->show_warning(vformat(TTR("Asset \"%s\" installed successfully!"), asset_name), TTR("Success!")); } } EditorFileSystem::get_singleton()->scan_changes(); } +void EditorAssetInstaller::set_asset_name(const String &p_asset_name) { + asset_name = p_asset_name; +} + +String EditorAssetInstaller::get_asset_name() const { + return asset_name; +} + void EditorAssetInstaller::_bind_methods() { } @@ -369,14 +387,18 @@ EditorAssetInstaller::EditorAssetInstaller() { VBoxContainer *vb = memnew(VBoxContainer); add_child(vb); + asset_contents = memnew(Label); + vb->add_child(asset_contents); + tree = memnew(Tree); - vb->add_margin_child(TTR("Package Contents:"), tree, true); + tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); tree->connect("item_edited", callable_mp(this, &EditorAssetInstaller::_item_edited)); + vb->add_child(tree); error = memnew(AcceptDialog); add_child(error); get_ok_button()->set_text(TTR("Install")); - set_title(TTR("Package Installer")); + set_title(TTR("Asset Installer")); updating = false; diff --git a/editor/editor_asset_installer.h b/editor/editor_asset_installer.h index d9233a5ce8..9fafe2792a 100644 --- a/editor/editor_asset_installer.h +++ b/editor/editor_asset_installer.h @@ -37,7 +37,9 @@ class EditorAssetInstaller : public ConfirmationDialog { GDCLASS(EditorAssetInstaller, ConfirmationDialog); Tree *tree; + Label *asset_contents; String package_path; + String asset_name; AcceptDialog *error; Map<String, TreeItem *> status_map; bool updating; @@ -51,6 +53,10 @@ protected: public: void open(const String &p_path, int p_depth = 0); + + void set_asset_name(const String &p_asset_name); + String get_asset_name() const; + EditorAssetInstaller(); }; diff --git a/editor/editor_zoom_widget.cpp b/editor/editor_zoom_widget.cpp index f9be829493..44751a480a 100644 --- a/editor/editor_zoom_widget.cpp +++ b/editor/editor_zoom_widget.cpp @@ -51,17 +51,17 @@ void EditorZoomWidget::_update_zoom_label() { } void EditorZoomWidget::_button_zoom_minus() { - set_zoom_by_increments(-6); + set_zoom_by_increments(-6, Input::get_singleton()->is_key_pressed(KEY_ALT)); emit_signal("zoom_changed", zoom); } void EditorZoomWidget::_button_zoom_reset() { - set_zoom(1.0); + set_zoom(1.0 * MAX(1, EDSCALE)); emit_signal("zoom_changed", zoom); } void EditorZoomWidget::_button_zoom_plus() { - set_zoom_by_increments(6); + set_zoom_by_increments(6, Input::get_singleton()->is_key_pressed(KEY_ALT)); emit_signal("zoom_changed", zoom); } @@ -76,31 +76,69 @@ void EditorZoomWidget::set_zoom(float p_zoom) { } } -void EditorZoomWidget::set_zoom_by_increments(int p_increment_count) { - // Base increment factor defined as the twelveth root of two. - // This allow a smooth geometric evolution of the zoom, with the advantage of - // visiting all integer power of two scale factors. - // note: this is analogous to the 'semitones' interval in the music world - // In order to avoid numerical imprecisions, we compute and edit a zoom index - // with the following relation: zoom = 2 ^ (index / 12) - - if (zoom < CMP_EPSILON || p_increment_count == 0) { - return; - } +void EditorZoomWidget::set_zoom_by_increments(int p_increment_count, bool p_integer_only) { + // Remove editor scale from the index computation. + const float zoom_noscale = zoom / MAX(1, EDSCALE); + + if (p_integer_only) { + // Only visit integer scaling factors above 100%, and fractions with an integer denominator below 100% + // (1/2 = 50%, 1/3 = 33.33%, 1/4 = 25%, …). + // This is useful when working on pixel art projects to avoid distortion. + // This algorithm is designed to handle fractional start zoom values correctly + // (e.g. 190% will zoom up to 200% and down to 100%). + if (zoom_noscale + p_increment_count * 0.001 >= 1.0 - CMP_EPSILON) { + // New zoom is certain to be above 100%. + if (p_increment_count >= 1) { + // Zooming. + set_zoom(Math::floor(zoom_noscale + p_increment_count) * MAX(1, EDSCALE)); + } else { + // Dezooming. + set_zoom(Math::ceil(zoom_noscale + p_increment_count) * MAX(1, EDSCALE)); + } + } else { + if (p_increment_count >= 1) { + // Zooming. Convert the current zoom into a denominator. + float new_zoom = 1.0 / Math::ceil(1.0 / zoom_noscale - p_increment_count); + if (Math::is_equal_approx(zoom_noscale, new_zoom)) { + // New zoom is identical to the old zoom, so try again. + // This can happen due to floating-point precision issues. + new_zoom = 1.0 / Math::ceil(1.0 / zoom_noscale - p_increment_count - 1); + } + set_zoom(new_zoom * MAX(1, EDSCALE)); + } else { + // Dezooming. Convert the current zoom into a denominator. + float new_zoom = 1.0 / Math::floor(1.0 / zoom_noscale - p_increment_count); + if (Math::is_equal_approx(zoom_noscale, new_zoom)) { + // New zoom is identical to the old zoom, so try again. + // This can happen due to floating-point precision issues. + new_zoom = 1.0 / Math::floor(1.0 / zoom_noscale - p_increment_count + 1); + } + set_zoom(new_zoom * MAX(1, EDSCALE)); + } + } + } else { + // Base increment factor defined as the twelveth root of two. + // This allow a smooth geometric evolution of the zoom, with the advantage of + // visiting all integer power of two scale factors. + // note: this is analogous to the 'semitones' interval in the music world + // In order to avoid numerical imprecisions, we compute and edit a zoom index + // with the following relation: zoom = 2 ^ (index / 12) - // Remove Editor scale from the index computation - float zoom_noscale = zoom / MAX(1, EDSCALE); + if (zoom < CMP_EPSILON || p_increment_count == 0) { + return; + } - // zoom = 2**(index/12) => log2(zoom) = index/12 - float closest_zoom_index = Math::round(Math::log(zoom_noscale) * 12.f / Math::log(2.f)); + // zoom = 2**(index/12) => log2(zoom) = index/12 + float closest_zoom_index = Math::round(Math::log(zoom_noscale) * 12.f / Math::log(2.f)); - float new_zoom_index = closest_zoom_index + p_increment_count; - float new_zoom = Math::pow(2.f, new_zoom_index / 12.f); + float new_zoom_index = closest_zoom_index + p_increment_count; + float new_zoom = Math::pow(2.f, new_zoom_index / 12.f); - // Restore Editor scale transformation - new_zoom *= MAX(1, EDSCALE); + // Restore Editor scale transformation + new_zoom *= MAX(1, EDSCALE); - set_zoom(new_zoom); + set_zoom(new_zoom); + } } void EditorZoomWidget::_notification(int p_what) { @@ -118,7 +156,7 @@ void EditorZoomWidget::_notification(int p_what) { void EditorZoomWidget::_bind_methods() { ClassDB::bind_method(D_METHOD("set_zoom", "zoom"), &EditorZoomWidget::set_zoom); ClassDB::bind_method(D_METHOD("get_zoom"), &EditorZoomWidget::get_zoom); - ClassDB::bind_method(D_METHOD("set_zoom_by_increments", "increment"), &EditorZoomWidget::set_zoom_by_increments); + ClassDB::bind_method(D_METHOD("set_zoom_by_increments", "increment", "integer_only"), &EditorZoomWidget::set_zoom_by_increments); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "zoom"), "set_zoom", "get_zoom"); diff --git a/editor/editor_zoom_widget.h b/editor/editor_zoom_widget.h index 4e95018e52..c35faeefe7 100644 --- a/editor/editor_zoom_widget.h +++ b/editor/editor_zoom_widget.h @@ -56,7 +56,7 @@ public: float get_zoom(); void set_zoom(float p_zoom); - void set_zoom_by_increments(int p_increment_count); + void set_zoom_by_increments(int p_increment_count, bool p_integer_only = false); }; #endif // EDITOR_ZOOM_WIDGET_H diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index cd61ebd418..596b2a6527 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -369,6 +369,9 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int progress->set_modulate(Color(0, 0, 0, 0)); set_process(false); + + // Automatically prompt for installation once the download is completed. + _install(); } void EditorAssetLibraryItemDownload::configure(const String &p_title, int p_asset_id, const Ref<Texture2D> &p_preview, const String &p_download_url, const String &p_sha256_hash) { @@ -456,6 +459,7 @@ void EditorAssetLibraryItemDownload::_install() { return; } + asset_installer->set_asset_name(title->get_text()); asset_installer->open(file, 1); } @@ -1296,6 +1300,7 @@ void EditorAssetLibrary::_asset_file_selected(const String &p_file) { } asset_installer = memnew(EditorAssetInstaller); + asset_installer->set_asset_name(p_file.get_basename()); add_child(asset_installer); asset_installer->open(p_file); } diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 7282475ddf..94cd8ce17d 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1149,8 +1149,9 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); } else { - zoom_widget->set_zoom_by_increments(-1); - if (b->get_factor() != 1.f) { + zoom_widget->set_zoom_by_increments(-1, Input::get_singleton()->is_key_pressed(KEY_ALT)); + if (!Math::is_equal_approx(b->get_factor(), 1.0f)) { + // Handle high-precision (analog) scrolling. zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * b->get_factor() + 1.f)); } _zoom_on_position(zoom_widget->get_zoom(), b->get_position()); @@ -1164,8 +1165,9 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); } else { - zoom_widget->set_zoom_by_increments(1); - if (b->get_factor() != 1.f) { + zoom_widget->set_zoom_by_increments(1, Input::get_singleton()->is_key_pressed(KEY_ALT)); + if (!Math::is_equal_approx(b->get_factor(), 1.0f)) { + // Handle high-precision (analog) scrolling. zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * b->get_factor() + 1.f)); } _zoom_on_position(zoom_widget->get_zoom(), b->get_position()); @@ -1194,6 +1196,20 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo Ref<InputEventKey> k = p_event; if (k.is_valid()) { + if (k->is_pressed()) { + if (ED_GET_SHORTCUT("canvas_item_editor/zoom_100_percent")->is_shortcut(p_event)) { + _update_zoom(1.0 * MAX(1, EDSCALE)); + } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_200_percent")->is_shortcut(p_event)) { + _update_zoom(2.0 * MAX(1, EDSCALE)); + } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_400_percent")->is_shortcut(p_event)) { + _update_zoom(4.0 * MAX(1, EDSCALE)); + } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_800_percent")->is_shortcut(p_event)) { + _update_zoom(8.0 * MAX(1, EDSCALE)); + } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_1600_percent")->is_shortcut(p_event)) { + _update_zoom(16.0 * MAX(1, EDSCALE)); + } + } + bool is_pan_key = pan_view_shortcut.is_valid() && pan_view_shortcut->is_shortcut(p_event); if (is_pan_key && (EditorSettings::get_singleton()->get("editors/2d/simple_panning") || drag_type != DRAG_NONE)) { @@ -5610,6 +5626,16 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true); singleton = this; + // To ensure that scripts can parse the list of shortcuts correctly, we have to define + // those shortcuts one by one. + // Resetting zoom to 100% is a duplicate shortcut of `canvas_item_editor/reset_zoom`, + // but it ensures both 1 and Ctrl + 0 can be used to reset zoom. + ED_SHORTCUT("canvas_item_editor/zoom_100_percent", TTR("Zoom To 100%"), KEY_1); + ED_SHORTCUT("canvas_item_editor/zoom_200_percent", TTR("Zoom To 200%"), KEY_2); + ED_SHORTCUT("canvas_item_editor/zoom_400_percent", TTR("Zoom To 400%"), KEY_3); + ED_SHORTCUT("canvas_item_editor/zoom_800_percent", TTR("Zoom To 800%"), KEY_4); + ED_SHORTCUT("canvas_item_editor/zoom_1600_percent", TTR("Zoom To 1600%"), KEY_5); + set_process_unhandled_key_input(true); // Update the menus' checkboxes diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp index 935ec457aa..0871423fbd 100644 --- a/scene/animation/animation_blend_space_2d.cpp +++ b/scene/animation/animation_blend_space_2d.cpp @@ -532,10 +532,10 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) { float from = 0.0; if (blend_mode == BLEND_MODE_DISCRETE_CARRY && closest != -1) { //see how much animation remains - from = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, true, 0.0, FILTER_IGNORE, false) - length_internal; + from = length_internal - blend_node(blend_points[closest].name, blend_points[closest].node, p_time, false, 0.0, FILTER_IGNORE, false); } - mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, 1.0, FILTER_IGNORE, false) + from; + mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, 1.0, FILTER_IGNORE, false); length_internal = from + mind; closest = new_closest; |