summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/core_bind.cpp3
-rw-r--r--editor/editor_asset_installer.cpp38
-rw-r--r--editor/editor_asset_installer.h6
-rw-r--r--editor/editor_zoom_widget.cpp86
-rw-r--r--editor/editor_zoom_widget.h2
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp5
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp34
-rw-r--r--scene/animation/animation_blend_space_2d.cpp4
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;