Automatically Resample CanvasItems in Scene Editor

This commit is contained in:
scgm0 2025-12-19 22:28:39 +08:00
parent 76dda5c6c5
commit fe3b8cbfb4
4 changed files with 57 additions and 1 deletions

View file

@ -317,6 +317,9 @@
<member name="docks/scene_tree/start_create_dialog_fully_expanded" type="bool" setter="" getter="">
If [code]true[/code], the Create dialog (Create New Node/Create New Resource) will start with all its sections expanded. Otherwise, sections will be collapsed until the user starts searching (which will automatically expand sections as needed).
</member>
<member name="editors/2d/auto_resample_delay" type="float" setter="" getter="">
Delay time for automatic resampling in the 2D editor (in seconds).
</member>
<member name="editors/2d/bone_color1" type="Color" setter="" getter="">
The "start" stop of the color gradient to use for bones in the 2D skeleton editor.
</member>

View file

@ -65,6 +65,7 @@
#include "scene/gui/subviewport_container.h"
#include "scene/gui/view_panner.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/timer.h"
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/style_box_texture.h"
@ -4351,6 +4352,9 @@ void CanvasItemEditor::_update_editor_settings() {
ruler_width_scaled = MAX(ruler_width_unscaled * EDSCALE, ruler_font_size * 2.0);
grab_distance = EDITOR_GET("editors/polygon_editor/point_grab_radius");
resample_delay = EDITOR_GET("editors/2d/auto_resample_delay");
resample_timer->set_wait_time(resample_delay);
}
void CanvasItemEditor::_project_settings_changed() {
@ -4613,12 +4617,19 @@ void CanvasItemEditor::_zoom_on_position(real_t p_zoom, Point2 p_position) {
zoom_widget->set_zoom(zoom);
update_viewport();
if (auto_resampling_enabled) {
resample_timer->start();
}
}
void CanvasItemEditor::_update_zoom(real_t p_zoom) {
_zoom_on_position(p_zoom, viewport_scrollable->get_size() / 2.0);
}
void CanvasItemEditor::_update_oversampling() {
EditorNode::get_singleton()->get_scene_root()->set_oversampling_override(auto_resampling_enabled ? zoom : 0.0);
}
void CanvasItemEditor::_shortcut_zoom_set(real_t p_zoom) {
_zoom_on_position(p_zoom * MAX(1, EDSCALE), viewport->get_local_mouse_position());
}
@ -5130,6 +5141,16 @@ void CanvasItemEditor::_popup_callback(int p_op) {
undo_redo->commit_action();
} break;
case AUTO_RESAMPLE_CANVAS_ITEMS: {
auto_resampling_enabled = !auto_resampling_enabled;
int idx = view_menu->get_popup()->get_item_index(AUTO_RESAMPLE_CANVAS_ITEMS);
view_menu->get_popup()->set_item_checked(idx, auto_resampling_enabled);
if (!resample_timer->is_stopped()) {
resample_timer->stop();
}
_update_oversampling();
EditorSettings::get_singleton()->set_project_metadata("2d_editor", "auto_resampling_enabled", auto_resampling_enabled);
} break;
}
}
@ -5184,6 +5205,9 @@ void CanvasItemEditor::_focus_selection(int p_op) {
zoom_widget->set_zoom(zoom);
viewport->queue_redraw(); // Redraw to update the global canvas transform after zoom changes.
callable_mp(this, &CanvasItemEditor::center_at).call_deferred(rect.get_center()); // Defer because the updated transform is needed.
if (auto_resampling_enabled) {
resample_timer->start();
}
} else {
center_at(rect.get_center());
}
@ -5252,6 +5276,9 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
// and the zoom level will still be the same (relative to the editor scale).
zoom = real_t(p_state["zoom"]) * MAX(1, EDSCALE);
zoom_widget->set_zoom(zoom);
if (auto_resampling_enabled) {
resample_timer->start();
}
}
if (state.has("ofs")) {
@ -5445,6 +5472,14 @@ void CanvasItemEditor::clear() {
snap_rotation_step = EditorSettings::get_singleton()->get_project_metadata("2d_editor", "snap_rotation_step", Math::deg_to_rad(15.0));
snap_rotation_offset = EditorSettings::get_singleton()->get_project_metadata("2d_editor", "snap_rotation_offset", 0.0);
snap_scale_step = EditorSettings::get_singleton()->get_project_metadata("2d_editor", "snap_scale_step", 0.1);
if (auto_resampling_enabled) {
if (resample_timer->is_inside_tree()) {
resample_timer->start();
} else {
_update_oversampling();
}
}
}
void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) {
@ -5906,7 +5941,11 @@ CanvasItemEditor::CanvasItemEditor() {
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTRC("Center Selection"), Key::F), VIEW_CENTER_TO_SELECTION);
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTRC("Frame Selection"), KeyModifierMask::SHIFT | Key::F), VIEW_FRAME_TO_SELECTION);
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/clear_guides", TTRC("Clear Guides")), CLEAR_GUIDES);
p->add_separator();
auto_resampling_enabled = EditorSettings::get_singleton()->get_project_metadata("2d_editor", "auto_resampling_enabled", true);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/auto_resample_canvas_items", TTRC("Auto Resample CanvasItems")), AUTO_RESAMPLE_CANVAS_ITEMS);
p->set_item_checked(p->get_item_index(AUTO_RESAMPLE_CANVAS_ITEMS), auto_resampling_enabled);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTRC("Preview Canvas Scale")), PREVIEW_CANVAS_SCALE);
theme_menu = memnew(PopupMenu);
@ -6016,6 +6055,12 @@ CanvasItemEditor::CanvasItemEditor() {
add_child(add_node_menu);
add_node_menu->connect(SceneStringName(id_pressed), callable_mp(this, &CanvasItemEditor::_add_node_pressed));
resample_timer = memnew(Timer);
resample_timer->set_wait_time(resample_delay);
resample_timer->set_one_shot(true);
add_child(resample_timer);
resample_timer->connect("timeout", callable_mp(this, &CanvasItemEditor::_update_oversampling));
multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTRC("Multiply grid step by 2"), Key::KP_MULTIPLY);
divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTRC("Divide grid step by 2"), Key::KP_DIVIDE);
reset_transform_position_shortcut = ED_SHORTCUT("canvas_item_editor/reset_transform_position", TTRC("Reset Position"), KeyModifierMask::ALT + Key::W);

View file

@ -46,6 +46,7 @@ class HSplitContainer;
class MenuButton;
class PanelContainer;
class StyleBoxTexture;
class Timer;
class ViewPanner;
class VScrollBar;
class VSeparator;
@ -145,7 +146,8 @@ private:
VIEW_FRAME_TO_SELECTION,
PREVIEW_CANVAS_SCALE,
SKELETON_MAKE_BONES,
SKELETON_SHOW_BONES
SKELETON_SHOW_BONES,
AUTO_RESAMPLE_CANVAS_ITEMS,
};
enum DragType {
@ -227,6 +229,10 @@ private:
Point2 view_offset;
Point2 previous_update_view_offset;
Timer *resample_timer = nullptr;
bool auto_resampling_enabled = true;
real_t resample_delay = 0.3;
bool selected_from_canvas = false;
// Defaults are defined in clear().
@ -432,6 +438,7 @@ private:
void _prepare_grid_menu();
void _on_grid_menu_id_pressed(int p_id);
void _reset_transform(TransformType p_type);
void _update_oversampling();
public:
enum ThemePreviewMode {

View file

@ -981,6 +981,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/2d/use_integer_zoom_by_default", false, true);
EDITOR_SETTING_BASIC(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/2d/zoom_speed_factor", 1.1, "1.01,2,0.01")
EDITOR_SETTING_BASIC(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/2d/ruler_width", 16.0, "12.0,30.0,1.0")
EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/2d/auto_resample_delay", 0.3, "0.1,2,0.1")
// Bone mapper (BoneMapEditorPlugin)
_initial_set("editors/bone_mapper/handle_colors/unset", Color(0.3, 0.3, 0.3));