summaryrefslogtreecommitdiff
path: root/editor/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'editor/plugins')
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp1
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.h3
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.cpp1
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.h4
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.cpp1
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.h4
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.cpp1
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.h3
-rw-r--r--editor/plugins/animation_library_editor.cpp25
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp6
-rw-r--r--editor/plugins/animation_player_editor_plugin.h5
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp1
-rw-r--r--editor/plugins/animation_state_machine_editor.h3
-rw-r--r--editor/plugins/audio_stream_randomizer_editor_plugin.cpp5
-rw-r--r--editor/plugins/bone_map_editor_plugin.cpp931
-rw-r--r--editor/plugins/bone_map_editor_plugin.h65
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp130
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h5
-rw-r--r--editor/plugins/cast_2d_editor_plugin.cpp1
-rw-r--r--editor/plugins/cast_2d_editor_plugin.h3
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.cpp1
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.h3
-rw-r--r--editor/plugins/control_editor_plugin.cpp849
-rw-r--r--editor/plugins/control_editor_plugin.h172
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.cpp1
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.h3
-rw-r--r--editor/plugins/curve_editor_plugin.cpp54
-rw-r--r--editor/plugins/debugger_editor_plugin.cpp73
-rw-r--r--editor/plugins/debugger_editor_plugin.h4
-rw-r--r--editor/plugins/font_config_plugin.cpp14
-rw-r--r--editor/plugins/font_config_plugin.h6
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.cpp3
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.h3
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp5
-rw-r--r--editor/plugins/gradient_editor_plugin.cpp3
-rw-r--r--editor/plugins/gradient_texture_2d_editor_plugin.cpp5
-rw-r--r--editor/plugins/gradient_texture_2d_editor_plugin.h6
-rw-r--r--editor/plugins/material_editor_plugin.cpp7
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp15
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp61
-rw-r--r--editor/plugins/node_3d_editor_gizmos.h6
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp68
-rw-r--r--editor/plugins/node_3d_editor_plugin.h9
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp1
-rw-r--r--editor/plugins/path_2d_editor_plugin.h3
-rw-r--r--editor/plugins/path_3d_editor_plugin.cpp13
-rw-r--r--editor/plugins/polygon_3d_editor_plugin.cpp1
-rw-r--r--editor/plugins/polygon_3d_editor_plugin.h3
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp6
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.h5
-rw-r--r--editor/plugins/script_editor_plugin.cpp23
-rw-r--r--editor/plugins/script_editor_plugin.h10
-rw-r--r--editor/plugins/script_text_editor.cpp12
-rw-r--r--editor/plugins/script_text_editor.h2
-rw-r--r--editor/plugins/shader_editor_plugin.cpp2
-rw-r--r--editor/plugins/skeleton_2d_editor_plugin.cpp5
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp38
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.h10
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.cpp9
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp7
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h5
-rw-r--r--editor/plugins/text_editor.cpp6
-rw-r--r--editor/plugins/text_editor.h2
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp1
-rw-r--r--editor/plugins/texture_region_editor_plugin.h3
-rw-r--r--editor/plugins/theme_editor_plugin.cpp49
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.cpp1
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.h3
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp26
-rw-r--r--editor/plugins/tiles/tile_data_editors.h14
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp5
-rw-r--r--editor/plugins/tiles/tile_map_editor.h8
-rw-r--r--editor/plugins/tiles/tile_proxies_manager_dialog.cpp1
-rw-r--r--editor/plugins/tiles/tile_proxies_manager_dialog.h2
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp14
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.h2
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp9
-rw-r--r--editor/plugins/tiles/tile_set_editor.h4
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.h2
-rw-r--r--editor/plugins/version_control_editor_plugin.cpp2
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp33
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h13
82 files changed, 2015 insertions, 909 deletions
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index a7d7c0145a..275859f528 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -36,6 +36,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/separator.h"
bool AbstractPolygon2DEditor::Vertex::operator==(const AbstractPolygon2DEditor::Vertex &p_vertex) const {
diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h
index 696fd7b637..1fbbe67c8d 100644
--- a/editor/plugins/abstract_polygon_2d_editor.h
+++ b/editor/plugins/abstract_polygon_2d_editor.h
@@ -36,6 +36,7 @@
#include "scene/gui/box_container.h"
class CanvasItemEditor;
+class EditorUndoRedoManager;
class AbstractPolygon2DEditor : public HBoxContainer {
GDCLASS(AbstractPolygon2DEditor, HBoxContainer);
@@ -99,7 +100,7 @@ protected:
int mode = MODE_EDIT;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
virtual void _menu_option(int p_option);
void _wip_changed();
diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp
index 32d97c65a9..2578099a9f 100644
--- a/editor/plugins/animation_blend_space_1d_editor.cpp
+++ b/editor/plugins/animation_blend_space_1d_editor.cpp
@@ -35,6 +35,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/animation/animation_blend_tree.h"
StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const {
diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h
index 9b06f3248f..125a3382fa 100644
--- a/editor/plugins/animation_blend_space_1d_editor.h
+++ b/editor/plugins/animation_blend_space_1d_editor.h
@@ -40,6 +40,8 @@
#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
+class EditorUndoRedoManager;
+
class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
GDCLASS(AnimationNodeBlendSpace1DEditor, AnimationTreeNodeEditorPlugin);
@@ -76,7 +78,7 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
bool updating = false;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
static AnimationNodeBlendSpace1DEditor *singleton;
diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp
index dc764725dd..c0723cef87 100644
--- a/editor/plugins/animation_blend_space_2d_editor.cpp
+++ b/editor/plugins/animation_blend_space_2d_editor.cpp
@@ -39,6 +39,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/menu_button.h"
diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h
index 26471df051..df2bcf254d 100644
--- a/editor/plugins/animation_blend_space_2d_editor.h
+++ b/editor/plugins/animation_blend_space_2d_editor.h
@@ -40,6 +40,8 @@
#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
+class EditorUndoRedoManager;
+
class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
GDCLASS(AnimationNodeBlendSpace2DEditor, AnimationTreeNodeEditorPlugin);
@@ -82,7 +84,7 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
bool updating;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
static AnimationNodeBlendSpace2DEditor *singleton;
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp
index 79be2d04b3..e4f5576d66 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp
@@ -39,6 +39,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/panel.h"
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h
index 18199676b8..af43da6197 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.h
+++ b/editor/plugins/animation_blend_tree_editor_plugin.h
@@ -41,6 +41,7 @@
class ProgressBar;
class EditorFileDialog;
+class EditorUndoRedoManager;
class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
GDCLASS(AnimationNodeBlendTreeEditor, AnimationTreeNodeEditorPlugin);
@@ -54,7 +55,7 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
PanelContainer *error_panel = nullptr;
Label *error_label = nullptr;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
AcceptDialog *filter_dialog = nullptr;
Tree *filters = nullptr;
diff --git a/editor/plugins/animation_library_editor.cpp b/editor/plugins/animation_library_editor.cpp
index c36ae1c521..f9e5aa799a 100644
--- a/editor/plugins/animation_library_editor.cpp
+++ b/editor/plugins/animation_library_editor.cpp
@@ -32,6 +32,7 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_undo_redo_manager.h"
void AnimationLibraryEditor::set_animation_player(Object *p_player) {
player = p_player;
@@ -92,7 +93,7 @@ void AnimationLibraryEditor::_add_library_validate(const String &p_name) {
void AnimationLibraryEditor::_add_library_confirm() {
if (adding_animation) {
String anim_name = add_library_name->get_text();
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
Ref<AnimationLibrary> al = player->call("get_animation_library", adding_animation_to_library);
ERR_FAIL_COND(!al.is_valid());
@@ -109,7 +110,7 @@ void AnimationLibraryEditor::_add_library_confirm() {
} else {
String lib_name = add_library_name->get_text();
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
Ref<AnimationLibrary> al;
al.instantiate();
@@ -203,7 +204,7 @@ void AnimationLibraryEditor::_file_popup_selected(int p_id) {
// TODO: should probably make all foreign animations assigned to this library
// unique too.
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Make Animation Library Unique: %s"), lib_name));
undo_redo->add_do_method(player, "remove_animation_library", lib_name);
undo_redo->add_do_method(player, "add_animation_library", lib_name, ald);
@@ -272,7 +273,7 @@ void AnimationLibraryEditor::_file_popup_selected(int p_id) {
Ref<Animation> animd = anim->duplicate();
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Make Animation Unique: %s"), anim_name));
undo_redo->add_do_method(al.ptr(), "remove_animation", anim_name);
undo_redo->add_do_method(al.ptr(), "add_animation", anim_name, animd);
@@ -320,7 +321,7 @@ void AnimationLibraryEditor::_load_file(String p_path) {
name = p_path.get_file().get_basename() + " " + itos(attempt);
}
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Add Animation Library: %s"), name));
undo_redo->add_do_method(player, "add_animation_library", name, al);
@@ -358,7 +359,7 @@ void AnimationLibraryEditor::_load_file(String p_path) {
name = p_path.get_file().get_basename() + " " + itos(attempt);
}
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Load Animation into Library: %s"), name));
undo_redo->add_do_method(al.ptr(), "add_animation", name, anim);
@@ -374,7 +375,7 @@ void AnimationLibraryEditor::_load_file(String p_path) {
EditorNode::get_singleton()->save_resource_in_path(al, p_path);
if (al->get_path() != prev_path) { // Save successful.
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Save Animation library to File: %s"), file_dialog_library));
undo_redo->add_do_method(al.ptr(), "set_path", al->get_path());
@@ -395,7 +396,7 @@ void AnimationLibraryEditor::_load_file(String p_path) {
String prev_path = anim->get_path();
EditorNode::get_singleton()->save_resource_in_path(anim, p_path);
if (anim->get_path() != prev_path) { // Save successful.
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Save Animation to File: %s"), file_dialog_animation));
undo_redo->add_do_method(anim.ptr(), "set_path", anim->get_path());
@@ -413,7 +414,7 @@ void AnimationLibraryEditor::_item_renamed() {
String text = ti->get_text(0);
String old_text = ti->get_metadata(0);
bool restore_text = false;
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
if (String(text).contains("/") || String(text).contains(":") || String(text).contains(",") || String(text).contains("[")) {
restore_text = true;
@@ -527,7 +528,7 @@ void AnimationLibraryEditor::_button_pressed(TreeItem *p_item, int p_column, int
name = base_name + " (" + itos(attempt) + ")";
}
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Add Animation to Library: %s"), name));
undo_redo->add_do_method(al.ptr(), "add_animation", name, anim);
@@ -553,7 +554,7 @@ void AnimationLibraryEditor::_button_pressed(TreeItem *p_item, int p_column, int
file_dialog_library = lib_name;
} break;
case LIB_BUTTON_DELETE: {
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Remove Animation Library: %s"), lib_name));
undo_redo->add_do_method(player, "remove_animation_library", lib_name);
undo_redo->add_undo_method(player, "add_animation_library", lib_name, al);
@@ -594,7 +595,7 @@ void AnimationLibraryEditor::_button_pressed(TreeItem *p_item, int p_column, int
} break;
case ANIM_BUTTON_DELETE: {
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(vformat(TTR("Remove Animation from Library: %s"), anim_name));
undo_redo->add_do_method(al.ptr(), "remove_animation", anim_name);
undo_redo->add_undo_method(al.ptr(), "add_animation", anim_name, anim);
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 516079673d..f374f48fb2 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -1045,6 +1045,10 @@ void AnimationPlayerEditor::_update_name_dialog_library_dropdown() {
}
}
+void AnimationPlayerEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) {
+ undo_redo = p_undo_redo;
+}
+
void AnimationPlayerEditor::edit(AnimationPlayer *p_player) {
if (player && pin->is_pressed()) {
return; // Ignore, pinned.
@@ -1925,7 +1929,7 @@ void AnimationPlayerEditorPlugin::_update_keying() {
}
void AnimationPlayerEditorPlugin::edit(Object *p_object) {
- anim_editor->set_undo_redo(&get_undo_redo());
+ anim_editor->set_undo_redo(get_undo_redo());
if (!p_object) {
return;
}
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index 3b1de070fa..a37a9debef 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -41,6 +41,7 @@
#include "scene/gui/texture_button.h"
#include "scene/gui/tree.h"
+class EditorUndoRedoManager;
class AnimationPlayerEditorPlugin;
class AnimationPlayerEditor : public VBoxContainer {
@@ -100,7 +101,7 @@ class AnimationPlayerEditor : public VBoxContainer {
LineEdit *name = nullptr;
OptionButton *library = nullptr;
Label *name_title = nullptr;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
Ref<Texture2D> autoplay_icon;
Ref<Texture2D> reset_icon;
@@ -233,7 +234,7 @@ public:
void ensure_visibility();
- void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; }
+ void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo);
void edit(AnimationPlayer *p_player);
void forward_force_draw_over_viewport(Control *p_overlay);
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index 473450b292..ef4ae3dca4 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -39,6 +39,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/menu_button.h"
diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h
index 165940e639..fdd1af0f6d 100644
--- a/editor/plugins/animation_state_machine_editor.h
+++ b/editor/plugins/animation_state_machine_editor.h
@@ -40,6 +40,7 @@
#include "scene/gui/tree.h"
class EditorFileDialog;
+class EditorUndoRedoManager;
class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
GDCLASS(AnimationNodeStateMachineEditor, AnimationTreeNodeEditorPlugin);
@@ -76,7 +77,7 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
bool updating = false;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
static AnimationNodeStateMachineEditor *singleton;
diff --git a/editor/plugins/audio_stream_randomizer_editor_plugin.cpp b/editor/plugins/audio_stream_randomizer_editor_plugin.cpp
index 9e551ae0ed..d670197c53 100644
--- a/editor/plugins/audio_stream_randomizer_editor_plugin.cpp
+++ b/editor/plugins/audio_stream_randomizer_editor_plugin.cpp
@@ -31,6 +31,7 @@
#include "audio_stream_randomizer_editor_plugin.h"
#include "editor/editor_node.h"
+#include "editor/editor_undo_redo_manager.h"
void AudioStreamRandomizerEditorPlugin::edit(Object *p_object) {
}
@@ -43,8 +44,8 @@ void AudioStreamRandomizerEditorPlugin::make_visible(bool p_visible) {
}
void AudioStreamRandomizerEditorPlugin::_move_stream_array_element(Object *p_undo_redo, Object *p_edited, String p_array_prefix, int p_from_index, int p_to_pos) {
- UndoRedo *undo_redo = Object::cast_to<UndoRedo>(p_undo_redo);
- ERR_FAIL_COND(!undo_redo);
+ Ref<EditorUndoRedoManager> undo_redo = Object::cast_to<EditorUndoRedoManager>(p_undo_redo);
+ ERR_FAIL_COND(undo_redo.is_null());
AudioStreamRandomizer *randomizer = Object::cast_to<AudioStreamRandomizer>(p_edited);
if (!randomizer) {
diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp
index 70775c1ee2..5db9249af1 100644
--- a/editor/plugins/bone_map_editor_plugin.cpp
+++ b/editor/plugins/bone_map_editor_plugin.cpp
@@ -47,6 +47,9 @@ void BoneMapperButton::fetch_textures() {
set_offset(SIDE_TOP, 0);
set_offset(SIDE_BOTTOM, 0);
+ // Hack to avoid handle color darkening...
+ set_modulate(EditorSettings::get_singleton()->is_dark_theme() ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25));
+
circle = memnew(TextureRect);
circle->set_texture(get_theme_icon(SNAME("BoneMapperHandleCircle"), SNAME("EditorIcons")));
add_child(circle);
@@ -98,14 +101,24 @@ BoneMapperButton::~BoneMapperButton() {
}
void BoneMapperItem::create_editor() {
- skeleton_bone_selector = memnew(EditorPropertyTextEnum);
- skeleton_bone_selector->setup(skeleton_bone_names, false, true);
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ add_child(hbox);
+
+ skeleton_bone_selector = memnew(EditorPropertyText);
skeleton_bone_selector->set_label(profile_bone_name);
skeleton_bone_selector->set_selectable(false);
+ skeleton_bone_selector->set_h_size_flags(SIZE_EXPAND_FILL);
skeleton_bone_selector->set_object_and_property(bone_map.ptr(), "bone_map/" + String(profile_bone_name));
skeleton_bone_selector->update_property();
skeleton_bone_selector->connect("property_changed", callable_mp(this, &BoneMapperItem::_value_changed));
- add_child(skeleton_bone_selector);
+ hbox->add_child(skeleton_bone_selector);
+
+ picker_button = memnew(Button);
+ picker_button->set_icon(get_theme_icon(SNAME("ClassList"), SNAME("EditorIcons")));
+ picker_button->connect("pressed", callable_mp(this, &BoneMapperItem::_open_picker));
+ hbox->add_child(picker_button);
+
+ add_child(memnew(HSeparator));
}
void BoneMapperItem::_update_property() {
@@ -114,6 +127,10 @@ void BoneMapperItem::_update_property() {
}
}
+void BoneMapperItem::_open_picker() {
+ emit_signal(SNAME("pick"), profile_bone_name);
+}
+
void BoneMapperItem::_value_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
bone_map->set(p_property, p_value);
}
@@ -133,25 +150,153 @@ void BoneMapperItem::_notification(int p_what) {
}
void BoneMapperItem::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("pick", PropertyInfo(Variant::STRING_NAME, "profile_bone_name")));
}
-BoneMapperItem::BoneMapperItem(Ref<BoneMap> &p_bone_map, PackedStringArray p_skeleton_bone_names, const StringName &p_profile_bone_name) {
+BoneMapperItem::BoneMapperItem(Ref<BoneMap> &p_bone_map, const StringName &p_profile_bone_name) {
bone_map = p_bone_map;
- skeleton_bone_names = p_skeleton_bone_names;
profile_bone_name = p_profile_bone_name;
}
BoneMapperItem::~BoneMapperItem() {
}
+void BonePicker::create_editors() {
+ set_title(TTR("Bone Picker:"));
+
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ add_child(vbox);
+
+ bones = memnew(Tree);
+ bones->set_select_mode(Tree::SELECT_SINGLE);
+ bones->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ bones->set_hide_root(true);
+ bones->connect("item_activated", callable_mp(this, &BonePicker::_confirm));
+ vbox->add_child(bones);
+
+ create_bones_tree(skeleton);
+}
+
+void BonePicker::create_bones_tree(Skeleton3D *p_skeleton) {
+ bones->clear();
+
+ if (!p_skeleton) {
+ return;
+ }
+
+ TreeItem *root = bones->create_item();
+
+ HashMap<int, TreeItem *> items;
+
+ items.insert(-1, root);
+
+ Ref<Texture> bone_icon = get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons"));
+
+ Vector<int> bones_to_process = p_skeleton->get_parentless_bones();
+ bool is_first = true;
+ while (bones_to_process.size() > 0) {
+ int current_bone_idx = bones_to_process[0];
+ bones_to_process.erase(current_bone_idx);
+
+ Vector<int> current_bone_child_bones = p_skeleton->get_bone_children(current_bone_idx);
+ int child_bone_size = current_bone_child_bones.size();
+ for (int i = 0; i < child_bone_size; i++) {
+ bones_to_process.push_back(current_bone_child_bones[i]);
+ }
+
+ const int parent_idx = p_skeleton->get_bone_parent(current_bone_idx);
+ TreeItem *parent_item = items.find(parent_idx)->value;
+
+ TreeItem *joint_item = bones->create_item(parent_item);
+ items.insert(current_bone_idx, joint_item);
+
+ joint_item->set_text(0, p_skeleton->get_bone_name(current_bone_idx));
+ joint_item->set_icon(0, bone_icon);
+ joint_item->set_selectable(0, true);
+ joint_item->set_metadata(0, "bones/" + itos(current_bone_idx));
+ if (is_first) {
+ is_first = false;
+ } else {
+ joint_item->set_collapsed(true);
+ }
+ }
+}
+
+void BonePicker::_confirm() {
+ _ok_pressed();
+}
+
+void BonePicker::popup_bones_tree(const Size2i &p_minsize) {
+ popup_centered(p_minsize);
+}
+
+bool BonePicker::has_selected_bone() {
+ TreeItem *selected = bones->get_selected();
+ if (!selected) {
+ return false;
+ }
+ return true;
+}
+
+StringName BonePicker::get_selected_bone() {
+ TreeItem *selected = bones->get_selected();
+ if (!selected) {
+ return StringName();
+ }
+ return selected->get_text(0);
+}
+
+void BonePicker::_bind_methods() {
+}
+
+void BonePicker::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ create_editors();
+ } break;
+ }
+}
+
+BonePicker::BonePicker(Skeleton3D *p_skeleton) {
+ skeleton = p_skeleton;
+}
+
+BonePicker::~BonePicker() {
+}
+
void BoneMapper::create_editor() {
+ // Create Bone picker.
+ picker = memnew(BonePicker(skeleton));
+ picker->connect("confirmed", callable_mp(this, &BoneMapper::_apply_picker_selection));
+ add_child(picker, false, INTERNAL_MODE_FRONT);
+
+ profile_selector = memnew(EditorPropertyResource);
+ profile_selector->setup(bone_map.ptr(), "profile", "SkeletonProfile");
+ profile_selector->set_label("Profile");
+ profile_selector->set_selectable(false);
+ profile_selector->set_object_and_property(bone_map.ptr(), "profile");
+ profile_selector->update_property();
+ profile_selector->connect("property_changed", callable_mp(this, &BoneMapper::_profile_changed));
+ add_child(profile_selector);
+ add_child(memnew(HSeparator));
+
+ HBoxContainer *group_hbox = memnew(HBoxContainer);
+ add_child(group_hbox);
+
profile_group_selector = memnew(EditorPropertyEnum);
profile_group_selector->set_label("Group");
profile_group_selector->set_selectable(false);
+ profile_group_selector->set_h_size_flags(SIZE_EXPAND_FILL);
profile_group_selector->set_object_and_property(this, "current_group_idx");
profile_group_selector->update_property();
profile_group_selector->connect("property_changed", callable_mp(this, &BoneMapper::_value_changed));
- add_child(profile_group_selector);
+ group_hbox->add_child(profile_group_selector);
+
+ clear_mapping_button = memnew(Button);
+ clear_mapping_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")));
+ clear_mapping_button->set_tooltip(TTR("Clear mappings in current group."));
+ clear_mapping_button->connect("pressed", callable_mp(this, &BoneMapper::_clear_mapping_current_group));
+ group_hbox->add_child(clear_mapping_button);
bone_mapper_field = memnew(AspectRatioContainer);
bone_mapper_field->set_stretch_mode(AspectRatioContainer::STRETCH_FIT);
@@ -175,9 +320,6 @@ void BoneMapper::create_editor() {
mapper_item_vbox = memnew(VBoxContainer);
add_child(mapper_item_vbox);
- separator = memnew(HSeparator);
- add_child(separator);
-
recreate_items();
}
@@ -201,6 +343,18 @@ void BoneMapper::update_group_idx() {
}
}
+void BoneMapper::_pick_bone(const StringName &p_bone_name) {
+ picker_key_name = p_bone_name;
+ picker->popup_bones_tree(Size2(500, 500) * EDSCALE);
+}
+
+void BoneMapper::_apply_picker_selection() {
+ if (!picker->has_selected_bone()) {
+ return;
+ }
+ bone_map->set_skeleton_bone_name(picker_key_name, picker->get_selected_bone());
+}
+
void BoneMapper::set_current_group_idx(int p_group_idx) {
current_group_idx = p_group_idx;
recreate_editor();
@@ -282,6 +436,7 @@ void BoneMapper::clear_items() {
// Clear items.
int len = bone_mapper_items.size();
for (int i = 0; i < len; i++) {
+ bone_mapper_items[i]->disconnect("pick", callable_mp(this, &BoneMapper::_pick_bone));
mapper_item_vbox->remove_child(bone_mapper_items[i]);
memdelete(bone_mapper_items[i]);
}
@@ -293,16 +448,11 @@ void BoneMapper::recreate_items() {
// Create items by profile.
Ref<SkeletonProfile> profile = bone_map->get_profile();
if (profile.is_valid()) {
- PackedStringArray skeleton_bone_names;
- int len = skeleton->get_bone_count();
- for (int i = 0; i < len; i++) {
- skeleton_bone_names.push_back(skeleton->get_bone_name(i));
- }
-
- len = profile->get_bone_size();
+ int len = profile->get_bone_size();
for (int i = 0; i < len; i++) {
StringName bn = profile->get_bone_name(i);
- bone_mapper_items.append(memnew(BoneMapperItem(bone_map, skeleton_bone_names, bn)));
+ bone_mapper_items.append(memnew(BoneMapperItem(bone_map, bn)));
+ bone_mapper_items[i]->connect("pick", callable_mp(this, &BoneMapper::_pick_bone), CONNECT_DEFERRED);
mapper_item_vbox->add_child(bone_mapper_items[i]);
}
}
@@ -363,11 +513,754 @@ void BoneMapper::_update_state() {
}
}
+void BoneMapper::_clear_mapping_current_group() {
+ if (bone_map.is_valid()) {
+ Ref<SkeletonProfile> profile = bone_map->get_profile();
+ if (profile.is_valid() && profile->get_group_size() > 0) {
+ int len = profile->get_bone_size();
+ for (int i = 0; i < len; i++) {
+ if (profile->get_group(i) == profile->get_group_name(current_group_idx)) {
+ bone_map->_set_skeleton_bone_name(profile->get_bone_name(i), StringName());
+ }
+ }
+ recreate_items();
+ }
+ }
+}
+
+#ifdef MODULE_REGEX_ENABLED
+int BoneMapper::search_bone_by_name(Skeleton3D *p_skeleton, Vector<String> p_picklist, BoneSegregation p_segregation, int p_parent, int p_child, int p_children_count) {
+ // There may be multiple candidates hit by existing the subsidiary bone.
+ // The one with the shortest name is probably the original.
+ LocalVector<String> hit_list;
+ String shortest = "";
+
+ for (int word_idx = 0; word_idx < p_picklist.size(); word_idx++) {
+ RegEx re = RegEx(p_picklist[word_idx]);
+ if (p_child == -1) {
+ Vector<int> bones_to_process = p_parent == -1 ? p_skeleton->get_parentless_bones() : p_skeleton->get_bone_children(p_parent);
+ while (bones_to_process.size() > 0) {
+ int idx = bones_to_process[0];
+ bones_to_process.erase(idx);
+ Vector<int> children = p_skeleton->get_bone_children(idx);
+ for (int i = 0; i < children.size(); i++) {
+ bones_to_process.push_back(children[i]);
+ }
+
+ if (p_children_count == 0 && children.size() > 0) {
+ continue;
+ }
+ if (p_children_count > 0 && children.size() < p_children_count) {
+ continue;
+ }
+
+ String bn = skeleton->get_bone_name(idx);
+ if (!re.search(bn.to_lower()).is_null() && guess_bone_segregation(bn) == p_segregation) {
+ hit_list.push_back(bn);
+ }
+ }
+
+ if (hit_list.size() > 0) {
+ shortest = hit_list[0];
+ for (uint32_t i = 0; i < hit_list.size(); i++) {
+ if (hit_list[i].length() < shortest.length()) {
+ shortest = hit_list[i]; // Prioritize parent.
+ }
+ }
+ }
+ } else {
+ int idx = skeleton->get_bone_parent(p_child);
+ while (idx != p_parent && idx >= 0) {
+ Vector<int> children = p_skeleton->get_bone_children(idx);
+ if (p_children_count == 0 && children.size() > 0) {
+ continue;
+ }
+ if (p_children_count > 0 && children.size() < p_children_count) {
+ continue;
+ }
+
+ String bn = skeleton->get_bone_name(idx);
+ if (!re.search(bn.to_lower()).is_null() && guess_bone_segregation(bn) == p_segregation) {
+ hit_list.push_back(bn);
+ }
+ idx = skeleton->get_bone_parent(idx);
+ }
+
+ if (hit_list.size() > 0) {
+ shortest = hit_list[0];
+ for (uint32_t i = 0; i < hit_list.size(); i++) {
+ if (hit_list[i].length() <= shortest.length()) {
+ shortest = hit_list[i]; // Prioritize parent.
+ }
+ }
+ }
+ }
+
+ if (shortest != "") {
+ break;
+ }
+ }
+
+ if (shortest == "") {
+ return -1;
+ }
+
+ return skeleton->find_bone(shortest);
+}
+
+BoneMapper::BoneSegregation BoneMapper::guess_bone_segregation(String p_bone_name) {
+ String fixed_bn = p_bone_name.camelcase_to_underscore().to_lower();
+
+ LocalVector<String> left_words;
+ left_words.push_back("(?<![a-zA-Z])left");
+ left_words.push_back("(?<![a-zA-Z0-9])l(?![a-zA-Z0-9])");
+
+ LocalVector<String> right_words;
+ right_words.push_back("(?<![a-zA-Z])right");
+ right_words.push_back("(?<![a-zA-Z0-9])r(?![a-zA-Z0-9])");
+
+ for (uint32_t i = 0; i < left_words.size(); i++) {
+ RegEx re_l = RegEx(left_words[i]);
+ if (!re_l.search(fixed_bn).is_null()) {
+ return BONE_SEGREGATION_LEFT;
+ }
+ RegEx re_r = RegEx(right_words[i]);
+ if (!re_r.search(fixed_bn).is_null()) {
+ return BONE_SEGREGATION_RIGHT;
+ }
+ }
+
+ return BONE_SEGREGATION_NONE;
+}
+
+void BoneMapper::_run_auto_mapping() {
+ auto_mapping_process(bone_map);
+ recreate_items();
+}
+
+void BoneMapper::auto_mapping_process(Ref<BoneMap> &p_bone_map) {
+ WARN_PRINT("Run auto mapping.");
+
+ int bone_idx = -1;
+ Vector<String> picklist; // Use Vector<String> because match words have priority.
+ Vector<int> search_path;
+
+ // 1. Guess Hips
+ picklist.push_back("hip");
+ picklist.push_back("pelvis");
+ picklist.push_back("waist");
+ picklist.push_back("torso");
+ int hips = search_bone_by_name(skeleton, picklist);
+ if (hips == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess Hips. Abort auto mapping.");
+ return; // If there is no Hips, we cannot guess bone after then.
+ } else {
+ p_bone_map->_set_skeleton_bone_name("Hips", skeleton->get_bone_name(hips));
+ }
+ picklist.clear();
+
+ // 2. Guess Root
+ bone_idx = skeleton->get_bone_parent(hips);
+ while (bone_idx >= 0) {
+ search_path.push_back(bone_idx);
+ bone_idx = skeleton->get_bone_parent(bone_idx);
+ }
+ if (search_path.size() == 0) {
+ bone_idx = -1;
+ } else if (search_path.size() == 1) {
+ bone_idx = search_path[0]; // It is only one bone which can be root.
+ } else {
+ bool found = false;
+ for (int i = 0; i < search_path.size(); i++) {
+ RegEx re = RegEx("root");
+ if (!re.search(skeleton->get_bone_name(search_path[i]).to_lower()).is_null()) {
+ bone_idx = search_path[i]; // Name match is preferred.
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ for (int i = 0; i < search_path.size(); i++) {
+ if (Vector3(0, 0, 0).is_equal_approx(skeleton->get_bone_global_rest(search_path[i]).origin)) {
+ bone_idx = search_path[i]; // The bone existing at the origin is appropriate as a root.
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ bone_idx = search_path[search_path.size() - 1]; // Ambiguous, but most parental bone selected.
+ }
+ }
+ if (bone_idx == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess Root."); // Root is not required, so continue.
+ } else {
+ p_bone_map->_set_skeleton_bone_name("Root", skeleton->get_bone_name(bone_idx));
+ }
+ bone_idx = -1;
+ search_path.clear();
+
+ // 3. Guess Neck
+ picklist.push_back("neck");
+ picklist.push_back("head"); // For no neck model.
+ picklist.push_back("face"); // Same above.
+ int neck = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_NONE, hips);
+ picklist.clear();
+
+ // 4. Guess Head
+ picklist.push_back("head");
+ picklist.push_back("face");
+ int head = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_NONE, neck);
+ if (head == -1) {
+ search_path = skeleton->get_bone_children(neck);
+ if (search_path.size() == 1) {
+ head = search_path[0]; // Maybe only one child of the Neck is Head.
+ }
+ }
+ if (head == -1) {
+ if (neck != -1) {
+ head = neck; // The head animation should have more movement.
+ neck = -1;
+ p_bone_map->_set_skeleton_bone_name("Head", skeleton->get_bone_name(head));
+ } else {
+ WARN_PRINT("Auto Mapping couldn't guess Neck or Head."); // Continued for guessing on the other bones. But abort when guessing spines step.
+ }
+ } else {
+ p_bone_map->_set_skeleton_bone_name("Neck", skeleton->get_bone_name(neck));
+ p_bone_map->_set_skeleton_bone_name("Head", skeleton->get_bone_name(head));
+ }
+ picklist.clear();
+ search_path.clear();
+
+ int neck_or_head = neck != -1 ? neck : (head != -1 ? head : -1);
+ if (neck_or_head != -1) {
+ // 4-1. Guess Eyes
+ picklist.push_back("eye(?!.*(brow|lash|lid))");
+ bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, neck_or_head);
+ if (bone_idx == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess LeftEye.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("LeftEye", skeleton->get_bone_name(bone_idx));
+ }
+ bone_idx = -1;
+
+ bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, neck_or_head);
+ if (bone_idx == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess RightEye.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("RightEye", skeleton->get_bone_name(bone_idx));
+ }
+ bone_idx = -1;
+ picklist.clear();
+
+ // 4-2. Guess Jaw
+ picklist.push_back("jaw");
+ bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_NONE, neck_or_head);
+ if (bone_idx == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess Jaw.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("Jaw", skeleton->get_bone_name(bone_idx));
+ }
+ bone_idx = -1;
+ picklist.clear();
+ }
+
+ // 5. Guess Foots
+ picklist.push_back("foot");
+ picklist.push_back("ankle");
+ int left_foot = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, hips);
+ if (left_foot == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess LeftFoot.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("LeftFoot", skeleton->get_bone_name(left_foot));
+ }
+ int right_foot = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, hips);
+ if (right_foot == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess RightFoot.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("RightFoot", skeleton->get_bone_name(right_foot));
+ }
+ picklist.clear();
+
+ // 5-1. Guess LowerLegs
+ picklist.push_back("(low|under).*leg");
+ picklist.push_back("knee");
+ picklist.push_back("shin");
+ picklist.push_back("calf");
+ picklist.push_back("leg");
+ int left_lower_leg = -1;
+ if (left_foot != -1) {
+ left_lower_leg = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, hips, left_foot);
+ }
+ if (left_lower_leg == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess LeftLowerLeg.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("LeftLowerLeg", skeleton->get_bone_name(left_lower_leg));
+ }
+ int right_lower_leg = -1;
+ if (right_foot != -1) {
+ right_lower_leg = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, hips, right_foot);
+ }
+ if (right_lower_leg == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess RightLowerLeg.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("RightLowerLeg", skeleton->get_bone_name(right_lower_leg));
+ }
+ picklist.clear();
+
+ // 5-2. Guess UpperLegs
+ picklist.push_back("up.*leg");
+ picklist.push_back("thigh");
+ picklist.push_back("leg");
+ if (left_lower_leg != -1) {
+ bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, hips, left_lower_leg);
+ }
+ if (bone_idx == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess LeftUpperLeg.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("LeftUpperLeg", skeleton->get_bone_name(bone_idx));
+ }
+ bone_idx = -1;
+ if (right_lower_leg != -1) {
+ bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, hips, right_lower_leg);
+ }
+ if (bone_idx == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess RightUpperLeg.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("RightUpperLeg", skeleton->get_bone_name(bone_idx));
+ }
+ bone_idx = -1;
+ picklist.clear();
+
+ // 5-3. Guess Toes
+ picklist.push_back("toe");
+ picklist.push_back("ball");
+ if (left_foot != -1) {
+ bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, left_foot);
+ if (bone_idx == -1) {
+ search_path = skeleton->get_bone_children(left_foot);
+ if (search_path.size() == 1) {
+ bone_idx = search_path[0]; // Maybe only one child of the Foot is Toes.
+ }
+ search_path.clear();
+ }
+ }
+ if (bone_idx == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess LeftToes.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("LeftToes", skeleton->get_bone_name(bone_idx));
+ }
+ bone_idx = -1;
+ if (right_foot != -1) {
+ bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, right_foot);
+ if (bone_idx == -1) {
+ search_path = skeleton->get_bone_children(right_foot);
+ if (search_path.size() == 1) {
+ bone_idx = search_path[0]; // Maybe only one child of the Foot is Toes.
+ }
+ search_path.clear();
+ }
+ }
+ if (bone_idx == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess RightToes.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("RightToes", skeleton->get_bone_name(bone_idx));
+ }
+ bone_idx = -1;
+ picklist.clear();
+
+ // 6. Guess Hands
+ picklist.push_back("hand");
+ picklist.push_back("wrist");
+ picklist.push_back("palm");
+ picklist.push_back("fingers");
+ int left_hand_or_palm = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, hips, -1, 5);
+ if (left_hand_or_palm == -1) {
+ // Ambiguous, but try again for fewer finger models.
+ left_hand_or_palm = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, hips);
+ }
+ int left_hand = left_hand_or_palm; // Check for the presence of a wrist, since bones with five children may be palmar.
+ while (left_hand != -1) {
+ bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, hips, left_hand);
+ if (bone_idx == -1) {
+ break;
+ }
+ left_hand = bone_idx;
+ }
+ if (left_hand == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess LeftHand.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("LeftHand", skeleton->get_bone_name(left_hand));
+ }
+ bone_idx = -1;
+ int right_hand_or_palm = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, hips, -1, 5);
+ if (right_hand_or_palm == -1) {
+ // Ambiguous, but try again for fewer finger models.
+ right_hand_or_palm = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, hips);
+ }
+ int right_hand = right_hand_or_palm;
+ while (right_hand != -1) {
+ bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, hips, right_hand);
+ if (bone_idx == -1) {
+ break;
+ }
+ right_hand = bone_idx;
+ }
+ if (right_hand == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess RightHand.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("RightHand", skeleton->get_bone_name(right_hand));
+ }
+ bone_idx = -1;
+ picklist.clear();
+
+ // 6-1. Guess Finger
+ bool named_finger_is_found = false;
+ LocalVector<String> fingers;
+ fingers.push_back("thumb|pollex");
+ fingers.push_back("index|fore");
+ fingers.push_back("middle");
+ fingers.push_back("ring");
+ fingers.push_back("little|pinkie|pinky");
+ if (left_hand_or_palm != -1) {
+ LocalVector<LocalVector<String>> left_fingers_map;
+ left_fingers_map.resize(5);
+ left_fingers_map[0].push_back("LeftThumbMetacarpal");
+ left_fingers_map[0].push_back("LeftThumbProximal");
+ left_fingers_map[0].push_back("LeftThumbDistal");
+ left_fingers_map[1].push_back("LeftIndexProximal");
+ left_fingers_map[1].push_back("LeftIndexIntermediate");
+ left_fingers_map[1].push_back("LeftIndexDistal");
+ left_fingers_map[2].push_back("LeftMiddleProximal");
+ left_fingers_map[2].push_back("LeftMiddleIntermediate");
+ left_fingers_map[2].push_back("LeftMiddleDistal");
+ left_fingers_map[3].push_back("LeftRingProximal");
+ left_fingers_map[3].push_back("LeftRingIntermediate");
+ left_fingers_map[3].push_back("LeftRingDistal");
+ left_fingers_map[4].push_back("LeftLittleProximal");
+ left_fingers_map[4].push_back("LeftLittleIntermediate");
+ left_fingers_map[4].push_back("LeftLittleDistal");
+ for (int i = 0; i < 5; i++) {
+ picklist.push_back(fingers[i]);
+ int finger = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, left_hand_or_palm, -1, 0);
+ if (finger != -1) {
+ while (finger != left_hand_or_palm && finger >= 0) {
+ search_path.push_back(finger);
+ finger = skeleton->get_bone_parent(finger);
+ }
+ search_path.reverse();
+ if (search_path.size() == 1) {
+ p_bone_map->_set_skeleton_bone_name(left_fingers_map[i][0], skeleton->get_bone_name(search_path[0]));
+ named_finger_is_found = true;
+ } else if (search_path.size() == 2) {
+ p_bone_map->_set_skeleton_bone_name(left_fingers_map[i][0], skeleton->get_bone_name(search_path[0]));
+ p_bone_map->_set_skeleton_bone_name(left_fingers_map[i][1], skeleton->get_bone_name(search_path[1]));
+ named_finger_is_found = true;
+ } else if (search_path.size() >= 3) {
+ search_path = search_path.slice(-3); // Eliminate the possibility of carpal bone.
+ p_bone_map->_set_skeleton_bone_name(left_fingers_map[i][0], skeleton->get_bone_name(search_path[0]));
+ p_bone_map->_set_skeleton_bone_name(left_fingers_map[i][1], skeleton->get_bone_name(search_path[1]));
+ p_bone_map->_set_skeleton_bone_name(left_fingers_map[i][2], skeleton->get_bone_name(search_path[2]));
+ named_finger_is_found = true;
+ }
+ }
+ picklist.clear();
+ search_path.clear();
+ }
+
+ // It is a bit corner case, but possibly the finger names are sequentially numbered...
+ if (!named_finger_is_found) {
+ picklist.push_back("finger");
+ RegEx finger_re = RegEx("finger");
+ search_path = skeleton->get_bone_children(left_hand_or_palm);
+ Vector<String> finger_names;
+ for (int i = 0; i < search_path.size(); i++) {
+ String bn = skeleton->get_bone_name(search_path[i]);
+ if (!finger_re.search(bn.to_lower()).is_null()) {
+ finger_names.push_back(bn);
+ }
+ }
+ finger_names.sort(); // Order by lexicographic, normal use cases never have more than 10 fingers in one hand.
+ search_path.clear();
+ for (int i = 0; i < finger_names.size(); i++) {
+ if (i >= 5) {
+ break;
+ }
+ int finger_root = skeleton->find_bone(finger_names[i]);
+ int finger = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, finger_root, -1, 0);
+ if (finger != -1) {
+ while (finger != finger_root && finger >= 0) {
+ search_path.push_back(finger);
+ finger = skeleton->get_bone_parent(finger);
+ }
+ }
+ search_path.push_back(finger_root);
+ search_path.reverse();
+ if (search_path.size() == 1) {
+ p_bone_map->_set_skeleton_bone_name(left_fingers_map[i][0], skeleton->get_bone_name(search_path[0]));
+ } else if (search_path.size() == 2) {
+ p_bone_map->_set_skeleton_bone_name(left_fingers_map[i][0], skeleton->get_bone_name(search_path[0]));
+ p_bone_map->_set_skeleton_bone_name(left_fingers_map[i][1], skeleton->get_bone_name(search_path[1]));
+ } else if (search_path.size() >= 3) {
+ search_path = search_path.slice(-3); // Eliminate the possibility of carpal bone.
+ p_bone_map->_set_skeleton_bone_name(left_fingers_map[i][0], skeleton->get_bone_name(search_path[0]));
+ p_bone_map->_set_skeleton_bone_name(left_fingers_map[i][1], skeleton->get_bone_name(search_path[1]));
+ p_bone_map->_set_skeleton_bone_name(left_fingers_map[i][2], skeleton->get_bone_name(search_path[2]));
+ }
+ search_path.clear();
+ }
+ picklist.clear();
+ }
+ }
+ named_finger_is_found = false;
+ if (right_hand_or_palm != -1) {
+ LocalVector<LocalVector<String>> right_fingers_map;
+ right_fingers_map.resize(5);
+ right_fingers_map[0].push_back("RightThumbMetacarpal");
+ right_fingers_map[0].push_back("RightThumbProximal");
+ right_fingers_map[0].push_back("RightThumbDistal");
+ right_fingers_map[1].push_back("RightIndexProximal");
+ right_fingers_map[1].push_back("RightIndexIntermediate");
+ right_fingers_map[1].push_back("RightIndexDistal");
+ right_fingers_map[2].push_back("RightMiddleProximal");
+ right_fingers_map[2].push_back("RightMiddleIntermediate");
+ right_fingers_map[2].push_back("RightMiddleDistal");
+ right_fingers_map[3].push_back("RightRingProximal");
+ right_fingers_map[3].push_back("RightRingIntermediate");
+ right_fingers_map[3].push_back("RightRingDistal");
+ right_fingers_map[4].push_back("RightLittleProximal");
+ right_fingers_map[4].push_back("RightLittleIntermediate");
+ right_fingers_map[4].push_back("RightLittleDistal");
+ for (int i = 0; i < 5; i++) {
+ picklist.push_back(fingers[i]);
+ int finger = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, right_hand_or_palm, -1, 0);
+ if (finger != -1) {
+ while (finger != right_hand_or_palm && finger >= 0) {
+ search_path.push_back(finger);
+ finger = skeleton->get_bone_parent(finger);
+ }
+ search_path.reverse();
+ if (search_path.size() == 1) {
+ p_bone_map->_set_skeleton_bone_name(right_fingers_map[i][0], skeleton->get_bone_name(search_path[0]));
+ named_finger_is_found = true;
+ } else if (search_path.size() == 2) {
+ p_bone_map->_set_skeleton_bone_name(right_fingers_map[i][0], skeleton->get_bone_name(search_path[0]));
+ p_bone_map->_set_skeleton_bone_name(right_fingers_map[i][1], skeleton->get_bone_name(search_path[1]));
+ named_finger_is_found = true;
+ } else if (search_path.size() >= 3) {
+ search_path = search_path.slice(-3); // Eliminate the possibility of carpal bone.
+ p_bone_map->_set_skeleton_bone_name(right_fingers_map[i][0], skeleton->get_bone_name(search_path[0]));
+ p_bone_map->_set_skeleton_bone_name(right_fingers_map[i][1], skeleton->get_bone_name(search_path[1]));
+ p_bone_map->_set_skeleton_bone_name(right_fingers_map[i][2], skeleton->get_bone_name(search_path[2]));
+ named_finger_is_found = true;
+ }
+ }
+ picklist.clear();
+ search_path.clear();
+ }
+
+ // It is a bit corner case, but possibly the finger names are sequentially numbered...
+ if (!named_finger_is_found) {
+ picklist.push_back("finger");
+ RegEx finger_re = RegEx("finger");
+ search_path = skeleton->get_bone_children(right_hand_or_palm);
+ Vector<String> finger_names;
+ for (int i = 0; i < search_path.size(); i++) {
+ String bn = skeleton->get_bone_name(search_path[i]);
+ if (!finger_re.search(bn.to_lower()).is_null()) {
+ finger_names.push_back(bn);
+ }
+ }
+ finger_names.sort(); // Order by lexicographic, normal use cases never have more than 10 fingers in one hand.
+ search_path.clear();
+ for (int i = 0; i < finger_names.size(); i++) {
+ if (i >= 5) {
+ break;
+ }
+ int finger_root = skeleton->find_bone(finger_names[i]);
+ int finger = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, finger_root, -1, 0);
+ if (finger != -1) {
+ while (finger != finger_root && finger >= 0) {
+ search_path.push_back(finger);
+ finger = skeleton->get_bone_parent(finger);
+ }
+ }
+ search_path.push_back(finger_root);
+ search_path.reverse();
+ if (search_path.size() == 1) {
+ p_bone_map->_set_skeleton_bone_name(right_fingers_map[i][0], skeleton->get_bone_name(search_path[0]));
+ } else if (search_path.size() == 2) {
+ p_bone_map->_set_skeleton_bone_name(right_fingers_map[i][0], skeleton->get_bone_name(search_path[0]));
+ p_bone_map->_set_skeleton_bone_name(right_fingers_map[i][1], skeleton->get_bone_name(search_path[1]));
+ } else if (search_path.size() >= 3) {
+ search_path = search_path.slice(-3); // Eliminate the possibility of carpal bone.
+ p_bone_map->_set_skeleton_bone_name(right_fingers_map[i][0], skeleton->get_bone_name(search_path[0]));
+ p_bone_map->_set_skeleton_bone_name(right_fingers_map[i][1], skeleton->get_bone_name(search_path[1]));
+ p_bone_map->_set_skeleton_bone_name(right_fingers_map[i][2], skeleton->get_bone_name(search_path[2]));
+ }
+ search_path.clear();
+ }
+ picklist.clear();
+ }
+ }
+
+ // 7. Guess Arms
+ picklist.push_back("shoulder");
+ picklist.push_back("clavicle");
+ picklist.push_back("collar");
+ int left_shoulder = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, hips);
+ if (left_shoulder == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess LeftShoulder.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("LeftShoulder", skeleton->get_bone_name(left_shoulder));
+ }
+ int right_shoulder = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, hips);
+ if (right_shoulder == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess RightShoulder.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("RightShoulder", skeleton->get_bone_name(right_shoulder));
+ }
+ picklist.clear();
+
+ // 7-1. Guess LowerArms
+ picklist.push_back("(low|fore).*arm");
+ picklist.push_back("elbow");
+ picklist.push_back("arm");
+ int left_lower_arm = -1;
+ if (left_shoulder != -1 && left_hand_or_palm != -1) {
+ left_lower_arm = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, left_shoulder, left_hand_or_palm);
+ }
+ if (left_lower_arm == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess LeftLowerArm.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("LeftLowerArm", skeleton->get_bone_name(left_lower_arm));
+ }
+ int right_lower_arm = -1;
+ if (right_shoulder != -1 && right_hand_or_palm != -1) {
+ right_lower_arm = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, right_shoulder, right_hand_or_palm);
+ }
+ if (right_lower_arm == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess RightLowerArm.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("RightLowerArm", skeleton->get_bone_name(right_lower_arm));
+ }
+ picklist.clear();
+
+ // 7-2. Guess UpperArms
+ picklist.push_back("up.*arm");
+ picklist.push_back("arm");
+ if (left_shoulder != -1 && left_lower_arm != -1) {
+ bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_LEFT, left_shoulder, left_lower_arm);
+ }
+ if (bone_idx == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess LeftUpperArm.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("LeftUpperArm", skeleton->get_bone_name(bone_idx));
+ }
+ bone_idx = -1;
+ if (right_shoulder != -1 && right_lower_arm != -1) {
+ bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, right_shoulder, right_lower_arm);
+ }
+ if (bone_idx == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess RightUpperArm.");
+ } else {
+ p_bone_map->_set_skeleton_bone_name("RightUpperArm", skeleton->get_bone_name(bone_idx));
+ }
+ bone_idx = -1;
+ picklist.clear();
+
+ // 8. Guess UpperChest or Chest
+ if (neck_or_head == -1) {
+ return; // Abort.
+ }
+ int chest_or_upper_chest = skeleton->get_bone_parent(neck_or_head);
+ bool is_appropriate = true;
+ if (left_shoulder != -1) {
+ bone_idx = skeleton->get_bone_parent(left_shoulder);
+ bool detect = false;
+ while (bone_idx != hips && bone_idx >= 0) {
+ if (bone_idx == chest_or_upper_chest) {
+ detect = true;
+ break;
+ }
+ bone_idx = skeleton->get_bone_parent(bone_idx);
+ }
+ if (!detect) {
+ is_appropriate = false;
+ }
+ bone_idx = -1;
+ }
+ if (right_shoulder != -1) {
+ bone_idx = skeleton->get_bone_parent(right_shoulder);
+ bool detect = false;
+ while (bone_idx != hips && bone_idx >= 0) {
+ if (bone_idx == chest_or_upper_chest) {
+ detect = true;
+ break;
+ }
+ bone_idx = skeleton->get_bone_parent(bone_idx);
+ }
+ if (!detect) {
+ is_appropriate = false;
+ }
+ bone_idx = -1;
+ }
+ if (!is_appropriate) {
+ if (skeleton->get_bone_parent(left_shoulder) == skeleton->get_bone_parent(right_shoulder)) {
+ chest_or_upper_chest = skeleton->get_bone_parent(left_shoulder);
+ } else {
+ chest_or_upper_chest = -1;
+ }
+ }
+ if (chest_or_upper_chest == -1) {
+ WARN_PRINT("Auto Mapping couldn't guess Chest or UpperChest. Abort auto mapping.");
+ return; // Will be not able to guess Spines.
+ }
+
+ // 9. Guess Spines
+ bone_idx = skeleton->get_bone_parent(chest_or_upper_chest);
+ while (bone_idx != hips && bone_idx >= 0) {
+ search_path.push_back(bone_idx);
+ bone_idx = skeleton->get_bone_parent(bone_idx);
+ }
+ search_path.reverse();
+ if (search_path.size() == 0) {
+ p_bone_map->_set_skeleton_bone_name("Spine", skeleton->get_bone_name(chest_or_upper_chest)); // Maybe chibi model...?
+ } else if (search_path.size() == 1) {
+ p_bone_map->_set_skeleton_bone_name("Spine", skeleton->get_bone_name(search_path[0]));
+ p_bone_map->_set_skeleton_bone_name("Chest", skeleton->get_bone_name(chest_or_upper_chest));
+ } else if (search_path.size() >= 2) {
+ p_bone_map->_set_skeleton_bone_name("Spine", skeleton->get_bone_name(search_path[0]));
+ p_bone_map->_set_skeleton_bone_name("Chest", skeleton->get_bone_name(search_path[search_path.size() - 1])); // Probably UppeChest's parent is appropriate.
+ p_bone_map->_set_skeleton_bone_name("UpperChest", skeleton->get_bone_name(chest_or_upper_chest));
+ }
+ bone_idx = -1;
+ search_path.clear();
+
+ WARN_PRINT("Finish auto mapping.");
+}
+#endif // MODULE_REGEX_ENABLED
+
void BoneMapper::_value_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
set(p_property, p_value);
recreate_editor();
}
+void BoneMapper::_profile_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
+ bone_map->set(p_property, p_value);
+
+ // Run auto mapping when setting SkeletonProfileHumanoid by GUI Editor.
+ Ref<SkeletonProfile> profile = bone_map->get_profile();
+ if (profile.is_valid()) {
+ SkeletonProfileHumanoid *hmn = Object::cast_to<SkeletonProfileHumanoid>(profile.ptr());
+ if (hmn) {
+#ifdef MODULE_REGEX_ENABLED
+ _run_auto_mapping();
+#endif // MODULE_REGEX_ENABLED
+ }
+ }
+}
+
void BoneMapper::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_current_group_idx", "current_group_idx"), &BoneMapper::set_current_group_idx);
ClassDB::bind_method(D_METHOD("get_current_group_idx"), &BoneMapper::get_current_group_idx);
@@ -444,10 +1337,6 @@ void BoneMapEditor::_notification(int p_what) {
create_editors();
} break;
case NOTIFICATION_EXIT_TREE: {
- if (bone_mapper) {
- remove_child(bone_mapper);
- bone_mapper->queue_delete();
- }
skeleton = nullptr;
} break;
}
diff --git a/editor/plugins/bone_map_editor_plugin.h b/editor/plugins/bone_map_editor_plugin.h
index 339547ea10..0541ce6eac 100644
--- a/editor/plugins/bone_map_editor_plugin.h
+++ b/editor/plugins/bone_map_editor_plugin.h
@@ -34,6 +34,12 @@
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
#include "editor/editor_properties.h"
+
+#include "modules/modules_enabled.gen.h" // For regex.
+#ifdef MODULE_REGEX_ENABLED
+#include "modules/regex/regex.h"
+#endif
+
#include "scene/3d/skeleton_3d.h"
#include "scene/gui/color_rect.h"
#include "scene/gui/dialogs.h"
@@ -79,12 +85,13 @@ class BoneMapperItem : public VBoxContainer {
int button_id = -1;
StringName profile_bone_name;
- PackedStringArray skeleton_bone_names;
Ref<BoneMap> bone_map;
- EditorPropertyTextEnum *skeleton_bone_selector;
+ EditorPropertyText *skeleton_bone_selector;
+ Button *picker_button;
void _update_property();
+ void _open_picker();
protected:
void _notification(int p_what);
@@ -95,20 +102,49 @@ protected:
public:
void assign_button_id(int p_button_id);
- BoneMapperItem(Ref<BoneMap> &p_bone_map, PackedStringArray p_skeleton_bone_names, const StringName &p_profile_bone_name = StringName());
+ BoneMapperItem(Ref<BoneMap> &p_bone_map, const StringName &p_profile_bone_name = StringName());
~BoneMapperItem();
};
+class BonePicker : public AcceptDialog {
+ GDCLASS(BonePicker, AcceptDialog);
+
+ Skeleton3D *skeleton = nullptr;
+ Tree *bones = nullptr;
+
+public:
+ void popup_bones_tree(const Size2i &p_minsize = Size2i());
+ bool has_selected_bone();
+ StringName get_selected_bone();
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+ void _confirm();
+
+private:
+ void create_editors();
+ void create_bones_tree(Skeleton3D *p_skeleton);
+
+public:
+ BonePicker(Skeleton3D *p_skeleton);
+ ~BonePicker();
+};
+
class BoneMapper : public VBoxContainer {
GDCLASS(BoneMapper, VBoxContainer);
Skeleton3D *skeleton;
Ref<BoneMap> bone_map;
+ EditorPropertyResource *profile_selector;
+
Vector<BoneMapperItem *> bone_mapper_items;
+ Button *clear_mapping_button;
+
VBoxContainer *mapper_item_vbox;
- HSeparator *separator;
int current_group_idx = 0;
int current_bone_idx = -1;
@@ -126,10 +162,31 @@ class BoneMapper : public VBoxContainer {
void update_group_idx();
void _update_state();
+ /* Bone picker */
+ BonePicker *picker = nullptr;
+ StringName picker_key_name;
+ void _pick_bone(const StringName &p_bone_name);
+ void _apply_picker_selection();
+ void _clear_mapping_current_group();
+
+#ifdef MODULE_REGEX_ENABLED
+ /* For auto mapping */
+ enum BoneSegregation {
+ BONE_SEGREGATION_NONE,
+ BONE_SEGREGATION_LEFT,
+ BONE_SEGREGATION_RIGHT
+ };
+ int search_bone_by_name(Skeleton3D *p_skeleton, Vector<String> p_picklist, BoneSegregation p_segregation = BONE_SEGREGATION_NONE, int p_parent = -1, int p_child = -1, int p_children_count = -1);
+ BoneSegregation guess_bone_segregation(String p_bone_name);
+ void auto_mapping_process(Ref<BoneMap> &p_bone_map);
+ void _run_auto_mapping();
+#endif // MODULE_REGEX_ENABLED
+
protected:
void _notification(int p_what);
static void _bind_methods();
virtual void _value_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing);
+ virtual void _profile_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing);
public:
void set_current_group_idx(int p_group_idx);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index fc70ace331..2e83e2041f 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -40,6 +40,7 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_toaster.h"
+#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor/plugins/script_editor_plugin.h"
#include "editor/scene_tree_dock.h"
@@ -2957,6 +2958,9 @@ void CanvasItemEditor::_draw_ruler_tool() {
Point2 corner = Point2(begin.x, end.y);
Vector2 length_vector = (begin - end).abs() / zoom;
+ const real_t horizontal_angle_rad = length_vector.angle();
+ const real_t vertical_angle_rad = Math_PI / 2.0 - horizontal_angle_rad;
+
Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
Color font_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
@@ -2973,6 +2977,42 @@ void CanvasItemEditor::_draw_ruler_tool() {
text_pos.x = CLAMP(text_pos.x, text_width / 2, viewport->get_rect().size.x - text_width * 1.5);
text_pos.y = CLAMP(text_pos.y, text_height * 1.5, viewport->get_rect().size.y - text_height * 1.5);
+ // Draw lines.
+ viewport->draw_line(begin, end, ruler_primary_color, Math::round(EDSCALE * 3));
+
+ bool draw_secondary_lines = !(Math::is_equal_approx(begin.y, corner.y) || Math::is_equal_approx(end.x, corner.x));
+ if (draw_secondary_lines) {
+ viewport->draw_line(begin, corner, ruler_secondary_color, Math::round(EDSCALE));
+ viewport->draw_line(corner, end, ruler_secondary_color, Math::round(EDSCALE));
+
+ // Angle arcs.
+ int arc_point_count = 8;
+ real_t arc_radius_max_length_percent = 0.1;
+ real_t ruler_length = length_vector.length() * zoom;
+ real_t arc_max_radius = 50.0;
+ real_t arc_line_width = 2.0;
+
+ const Vector2 end_to_begin = (end - begin);
+
+ real_t arc_1_start_angle = end_to_begin.x < 0
+ ? (end_to_begin.y < 0 ? 3.0 * Math_PI / 2.0 - vertical_angle_rad : Math_PI / 2.0)
+ : (end_to_begin.y < 0 ? 3.0 * Math_PI / 2.0 : Math_PI / 2.0 - vertical_angle_rad);
+ real_t arc_1_end_angle = arc_1_start_angle + vertical_angle_rad;
+ // Constrain arc to triangle height & max size.
+ real_t arc_1_radius = MIN(MIN(arc_radius_max_length_percent * ruler_length, ABS(end_to_begin.y)), arc_max_radius);
+
+ real_t arc_2_start_angle = end_to_begin.x < 0
+ ? (end_to_begin.y < 0 ? 0.0 : -horizontal_angle_rad)
+ : (end_to_begin.y < 0 ? Math_PI - horizontal_angle_rad : Math_PI);
+ real_t arc_2_end_angle = arc_2_start_angle + horizontal_angle_rad;
+ // Constrain arc to triangle width & max size.
+ real_t arc_2_radius = MIN(MIN(arc_radius_max_length_percent * ruler_length, ABS(end_to_begin.x)), arc_max_radius);
+
+ viewport->draw_arc(begin, arc_1_radius, arc_1_start_angle, arc_1_end_angle, arc_point_count, ruler_primary_color, Math::round(EDSCALE * arc_line_width));
+ 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));
+ }
+
+ // Draw text.
if (begin.is_equal_approx(end)) {
viewport->draw_string_outline(font, text_pos, (String)ruler_tool_origin, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos, (String)ruler_tool_origin, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
@@ -2984,17 +3024,7 @@ void CanvasItemEditor::_draw_ruler_tool() {
viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
- bool draw_secondary_lines = !(Math::is_equal_approx(begin.y, corner.y) || Math::is_equal_approx(end.x, corner.x));
-
- viewport->draw_line(begin, end, ruler_primary_color, Math::round(EDSCALE * 3));
- if (draw_secondary_lines) {
- viewport->draw_line(begin, corner, ruler_secondary_color, Math::round(EDSCALE));
- viewport->draw_line(corner, end, ruler_secondary_color, Math::round(EDSCALE));
- }
-
if (draw_secondary_lines) {
- const real_t horizontal_angle_rad = length_vector.angle();
- const real_t vertical_angle_rad = Math_PI / 2.0 - horizontal_angle_rad;
const int horizontal_angle = round(180 * horizontal_angle_rad / Math_PI);
const int vertical_angle = round(180 * vertical_angle_rad / Math_PI);
@@ -3031,32 +3061,6 @@ void CanvasItemEditor::_draw_ruler_tool() {
}
viewport->draw_string_outline(font, h_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, h_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
-
- // Angle arcs
- int arc_point_count = 8;
- real_t arc_radius_max_length_percent = 0.1;
- real_t ruler_length = length_vector.length() * zoom;
- real_t arc_max_radius = 50.0;
- real_t arc_line_width = 2.0;
-
- const Vector2 end_to_begin = (end - begin);
-
- real_t arc_1_start_angle = end_to_begin.x < 0
- ? (end_to_begin.y < 0 ? 3.0 * Math_PI / 2.0 - vertical_angle_rad : Math_PI / 2.0)
- : (end_to_begin.y < 0 ? 3.0 * Math_PI / 2.0 : Math_PI / 2.0 - vertical_angle_rad);
- real_t arc_1_end_angle = arc_1_start_angle + vertical_angle_rad;
- // Constrain arc to triangle height & max size
- real_t arc_1_radius = MIN(MIN(arc_radius_max_length_percent * ruler_length, ABS(end_to_begin.y)), arc_max_radius);
-
- real_t arc_2_start_angle = end_to_begin.x < 0
- ? (end_to_begin.y < 0 ? 0.0 : -horizontal_angle_rad)
- : (end_to_begin.y < 0 ? Math_PI - horizontal_angle_rad : Math_PI);
- real_t arc_2_end_angle = arc_2_start_angle + horizontal_angle_rad;
- // Constrain arc to triangle width & max size
- real_t arc_2_radius = MIN(MIN(arc_radius_max_length_percent * ruler_length, ABS(end_to_begin.x)), arc_max_radius);
-
- viewport->draw_arc(begin, arc_1_radius, arc_1_start_angle, arc_1_end_angle, arc_point_count, ruler_primary_color, Math::round(EDSCALE * arc_line_width));
- 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 (grid_snap_active) {
@@ -3988,6 +3992,10 @@ void CanvasItemEditor::_selection_changed() {
selected_from_canvas = false;
}
+void CanvasItemEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) {
+ undo_redo = p_undo_redo;
+}
+
void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
Array selection = editor_selection->get_selected_nodes();
if (selection.size() != 1 || Object::cast_to<Node>(selection[0]) != p_canvas_item) {
@@ -5419,7 +5427,7 @@ CanvasItemEditor::CanvasItemEditor() {
CanvasItemEditor *CanvasItemEditor::singleton = nullptr;
void CanvasItemEditorPlugin::edit(Object *p_object) {
- canvas_item_editor->set_undo_redo(&get_undo_redo());
+ canvas_item_editor->set_undo_redo(EditorNode::get_undo_redo());
canvas_item_editor->edit(Object::cast_to<CanvasItem>(p_object));
}
@@ -5572,34 +5580,34 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
Ref<Texture2D> texture = ResourceCache::get_ref(path);
if (parent) {
- editor_data->get_undo_redo().add_do_method(parent, "add_child", child, true);
- editor_data->get_undo_redo().add_do_method(child, "set_owner", EditorNode::get_singleton()->get_edited_scene());
- editor_data->get_undo_redo().add_do_reference(child);
- editor_data->get_undo_redo().add_undo_method(parent, "remove_child", child);
+ editor_data->get_undo_redo()->add_do_method(parent, "add_child", child, true);
+ editor_data->get_undo_redo()->add_do_method(child, "set_owner", EditorNode::get_singleton()->get_edited_scene());
+ editor_data->get_undo_redo()->add_do_reference(child);
+ editor_data->get_undo_redo()->add_undo_method(parent, "remove_child", child);
} else { // If no parent is selected, set as root node of the scene.
- editor_data->get_undo_redo().add_do_method(EditorNode::get_singleton(), "set_edited_scene", child);
- editor_data->get_undo_redo().add_do_method(child, "set_owner", EditorNode::get_singleton()->get_edited_scene());
- editor_data->get_undo_redo().add_do_reference(child);
- editor_data->get_undo_redo().add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
+ editor_data->get_undo_redo()->add_do_method(EditorNode::get_singleton(), "set_edited_scene", child);
+ editor_data->get_undo_redo()->add_do_method(child, "set_owner", EditorNode::get_singleton()->get_edited_scene());
+ editor_data->get_undo_redo()->add_do_reference(child);
+ editor_data->get_undo_redo()->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
}
if (parent) {
String new_name = parent->validate_child_name(child);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
- editor_data->get_undo_redo().add_do_method(ed, "live_debug_create_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent), child->get_class(), new_name);
- editor_data->get_undo_redo().add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
+ editor_data->get_undo_redo()->add_do_method(ed, "live_debug_create_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent), child->get_class(), new_name);
+ editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
}
if (Object::cast_to<TouchScreenButton>(child) || Object::cast_to<TextureButton>(child)) {
- editor_data->get_undo_redo().add_do_property(child, "texture_normal", texture);
+ editor_data->get_undo_redo()->add_do_property(child, "texture_normal", texture);
} else {
- editor_data->get_undo_redo().add_do_property(child, "texture", texture);
+ editor_data->get_undo_redo()->add_do_property(child, "texture", texture);
}
// make visible for certain node type
if (Object::cast_to<Control>(child)) {
Size2 texture_size = texture->get_size();
- editor_data->get_undo_redo().add_do_property(child, "rect_size", texture_size);
+ editor_data->get_undo_redo()->add_do_property(child, "rect_size", texture_size);
} else if (Object::cast_to<Polygon2D>(child)) {
Size2 texture_size = texture->get_size();
Vector<Vector2> list = {
@@ -5608,7 +5616,7 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
Vector2(texture_size.width, texture_size.height),
Vector2(0, texture_size.height)
};
- editor_data->get_undo_redo().add_do_property(child, "polygon", list);
+ editor_data->get_undo_redo()->add_do_property(child, "polygon", list);
}
// Compute the global position
@@ -5617,7 +5625,7 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
// there's nothing to be used as source position so snapping will work as absolute if enabled
target_position = canvas_item_editor->snap_point(target_position);
- editor_data->get_undo_redo().add_do_method(child, "set_global_position", target_position);
+ editor_data->get_undo_redo()->add_do_method(child, "set_global_position", target_position);
}
bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) {
@@ -5642,15 +5650,15 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
instantiated_scene->set_scene_file_path(ProjectSettings::get_singleton()->localize_path(path));
- editor_data->get_undo_redo().add_do_method(parent, "add_child", instantiated_scene, true);
- editor_data->get_undo_redo().add_do_method(instantiated_scene, "set_owner", edited_scene);
- editor_data->get_undo_redo().add_do_reference(instantiated_scene);
- editor_data->get_undo_redo().add_undo_method(parent, "remove_child", instantiated_scene);
+ editor_data->get_undo_redo()->add_do_method(parent, "add_child", instantiated_scene, true);
+ editor_data->get_undo_redo()->add_do_method(instantiated_scene, "set_owner", edited_scene);
+ editor_data->get_undo_redo()->add_do_reference(instantiated_scene);
+ editor_data->get_undo_redo()->add_undo_method(parent, "remove_child", instantiated_scene);
String new_name = parent->validate_child_name(instantiated_scene);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
- editor_data->get_undo_redo().add_do_method(ed, "live_debug_instance_node", edited_scene->get_path_to(parent), path, new_name);
- editor_data->get_undo_redo().add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)) + "/" + new_name));
+ editor_data->get_undo_redo()->add_do_method(ed, "live_debug_instance_node", edited_scene->get_path_to(parent), path, new_name);
+ editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)) + "/" + new_name));
CanvasItem *instance_ci = Object::cast_to<CanvasItem>(instantiated_scene);
if (instance_ci) {
@@ -5664,7 +5672,7 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
// Preserve instance position of the original scene.
target_pos += instance_ci->_edit_get_position();
- editor_data->get_undo_redo().add_do_method(instantiated_scene, "set_position", target_pos);
+ editor_data->get_undo_redo()->add_do_method(instantiated_scene, "set_position", target_pos);
}
return true;
@@ -5682,7 +5690,7 @@ void CanvasItemEditorViewport::_perform_drop_data() {
Vector<String> error_files;
- editor_data->get_undo_redo().create_action(TTR("Create Node"));
+ editor_data->get_undo_redo()->create_action(TTR("Create Node"));
for (int i = 0; i < selected_files.size(); i++) {
String path = selected_files[i];
@@ -5713,7 +5721,7 @@ void CanvasItemEditorViewport::_perform_drop_data() {
}
}
- editor_data->get_undo_redo().commit_action();
+ editor_data->get_undo_redo()->commit_action();
if (error_files.size() > 0) {
String files_str;
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 04fd819dec..2ca495e5d6 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -45,6 +45,7 @@
class EditorData;
class CanvasItemEditorViewport;
class ViewPanner;
+class EditorUndoRedoManager;
class CanvasItemEditorSelectedItem : public Object {
GDCLASS(CanvasItemEditorSelectedItem, Object);
@@ -400,7 +401,7 @@ private:
void _prepare_grid_menu();
void _on_grid_menu_id_pressed(int p_id);
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
List<CanvasItem *> _get_edited_canvas_items(bool retrieve_locked = false, bool remove_canvas_item_if_parent_in_selection = true);
Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list);
@@ -547,7 +548,7 @@ public:
Tool get_current_tool() { return tool; }
void set_current_tool(Tool p_tool);
- void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; }
+ void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo);
void edit(CanvasItem *p_canvas_item);
void focus_selection();
diff --git a/editor/plugins/cast_2d_editor_plugin.cpp b/editor/plugins/cast_2d_editor_plugin.cpp
index 18c38e7ab8..a8d255f997 100644
--- a/editor/plugins/cast_2d_editor_plugin.cpp
+++ b/editor/plugins/cast_2d_editor_plugin.cpp
@@ -32,6 +32,7 @@
#include "canvas_item_editor_plugin.h"
#include "editor/editor_node.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/2d/ray_cast_2d.h"
#include "scene/2d/shape_cast_2d.h"
diff --git a/editor/plugins/cast_2d_editor_plugin.h b/editor/plugins/cast_2d_editor_plugin.h
index d9c0cc4a06..85ff497bc7 100644
--- a/editor/plugins/cast_2d_editor_plugin.h
+++ b/editor/plugins/cast_2d_editor_plugin.h
@@ -35,11 +35,12 @@
#include "scene/2d/node_2d.h"
class CanvasItemEditor;
+class EditorUndoRedoManager;
class Cast2DEditor : public Control {
GDCLASS(Cast2DEditor, Control);
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
CanvasItemEditor *canvas_item_editor = nullptr;
Node2D *node;
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp
index af20064a8d..11992ad10e 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp
@@ -33,6 +33,7 @@
#include "canvas_item_editor_plugin.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/resources/capsule_shape_2d.h"
#include "scene/resources/circle_shape_2d.h"
#include "scene/resources/concave_polygon_shape_2d.h"
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h
index f7de05ddd1..49e0820ae9 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.h
+++ b/editor/plugins/collision_shape_2d_editor_plugin.h
@@ -35,6 +35,7 @@
#include "scene/2d/collision_shape_2d.h"
class CanvasItemEditor;
+class EditorUndoRedoManager;
class CollisionShape2DEditor : public Control {
GDCLASS(CollisionShape2DEditor, Control);
@@ -61,7 +62,7 @@ class CollisionShape2DEditor : public Control {
Point2(1, -1),
};
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
CanvasItemEditor *canvas_item_editor = nullptr;
CollisionShape2D *node = nullptr;
diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp
index 2756e45cf4..2a12dc0e89 100644
--- a/editor/plugins/control_editor_plugin.cpp
+++ b/editor/plugins/control_editor_plugin.cpp
@@ -31,10 +31,14 @@
#include "control_editor_plugin.h"
#include "editor/editor_node.h"
+#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "scene/gui/separator.h"
+// Inspector controls.
+
void ControlPositioningWarning::_update_warning() {
if (!control_node) {
title_icon->set_texture(nullptr);
@@ -49,7 +53,7 @@ void ControlPositioningWarning::_update_warning() {
title_label->set_text(TTR("This node doesn't have a control parent."));
hint_label->set_text(TTR("Use the appropriate layout properties depending on where you are going to put it."));
} else if (Object::cast_to<Container>(parent_node)) {
- title_icon->set_texture(get_theme_icon(SNAME("Container"), SNAME("EditorIcons")));
+ title_icon->set_texture(get_theme_icon(SNAME("ContainerLayout"), SNAME("EditorIcons")));
title_label->set_text(TTR("This node is a child of a container."));
hint_label->set_text(TTR("Use container properties for positioning."));
} else {
@@ -448,37 +452,280 @@ bool EditorInspectorPluginControl::parse_property(Object *p_object, const Varian
return false;
}
-void ControlEditorToolbar::_set_anchors_and_offsets_preset(Control::LayoutPreset p_preset) {
+// Toolbars controls.
+
+Size2 ControlEditorPopupButton::get_minimum_size() const {
+ Vector2 base_size = Vector2(26, 26) * EDSCALE;
+
+ if (arrow_icon.is_null()) {
+ return base_size;
+ }
+
+ Vector2 final_size;
+ final_size.x = base_size.x + arrow_icon->get_width();
+ final_size.y = MAX(base_size.y, arrow_icon->get_height());
+
+ return final_size;
+}
+
+void ControlEditorPopupButton::toggled(bool p_pressed) {
+ if (!p_pressed) {
+ return;
+ }
+
+ Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale();
+
+ popup_panel->set_size(Size2(size.width, 0));
+ Point2 gp = get_screen_position();
+ gp.y += size.y;
+ if (is_layout_rtl()) {
+ gp.x += size.width - popup_panel->get_size().width;
+ }
+ popup_panel->set_position(gp);
+
+ popup_panel->popup();
+}
+
+void ControlEditorPopupButton::_popup_visibility_changed(bool p_visible) {
+ set_pressed(p_visible);
+}
+
+void ControlEditorPopupButton::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ arrow_icon = get_theme_icon("select_arrow", "Tree");
+ } break;
+
+ case NOTIFICATION_DRAW: {
+ if (arrow_icon.is_valid()) {
+ Vector2 arrow_pos = Point2(26, 0) * EDSCALE;
+ arrow_pos.y = get_size().y / 2 - arrow_icon->get_height() / 2;
+ draw_texture(arrow_icon, arrow_pos);
+ }
+ } break;
+
+ case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
+ popup_panel->set_layout_direction((Window::LayoutDirection)get_layout_direction());
+ } break;
+
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (!is_visible_in_tree()) {
+ popup_panel->hide();
+ }
+ } break;
+ }
+}
+
+ControlEditorPopupButton::ControlEditorPopupButton() {
+ set_flat(true);
+ set_toggle_mode(true);
+ set_focus_mode(FOCUS_NONE);
+
+ popup_panel = memnew(PopupPanel);
+ popup_panel->set_theme_type_variation("ControlEditorPopupButton");
+ add_child(popup_panel);
+ popup_panel->connect("about_to_popup", callable_mp(this, &ControlEditorPopupButton::_popup_visibility_changed).bind(true));
+ popup_panel->connect("popup_hide", callable_mp(this, &ControlEditorPopupButton::_popup_visibility_changed).bind(false));
+
+ popup_vbox = memnew(VBoxContainer);
+ popup_panel->add_child(popup_vbox);
+}
+
+void ControlEditorPresetPicker::_add_row_button(HBoxContainer *p_row, const int p_preset, const String &p_name) {
+ ERR_FAIL_COND(preset_buttons.has(p_preset));
+
+ Button *b = memnew(Button);
+ b->set_custom_minimum_size(Size2i(36, 36) * EDSCALE);
+ b->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER);
+ b->set_tooltip(p_name);
+ b->set_flat(true);
+ p_row->add_child(b);
+ b->connect("pressed", callable_mp(this, &ControlEditorPresetPicker::_preset_button_pressed).bind(p_preset));
+
+ preset_buttons[p_preset] = b;
+}
+
+void ControlEditorPresetPicker::_add_separator(BoxContainer *p_box, Separator *p_separator) {
+ p_separator->add_theme_constant_override("separation", grid_separation);
+ p_separator->set_custom_minimum_size(Size2i(1, 1));
+ p_box->add_child(p_separator);
+}
+
+void AnchorPresetPicker::_preset_button_pressed(const int p_preset) {
+ emit_signal("anchors_preset_selected", p_preset);
+}
+
+void AnchorPresetPicker::_notification(int p_notification) {
+ switch (p_notification) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ preset_buttons[PRESET_TOP_LEFT]->set_icon(get_theme_icon(SNAME("ControlAlignTopLeft"), SNAME("EditorIcons")));
+ preset_buttons[PRESET_CENTER_TOP]->set_icon(get_theme_icon(SNAME("ControlAlignCenterTop"), SNAME("EditorIcons")));
+ preset_buttons[PRESET_TOP_RIGHT]->set_icon(get_theme_icon(SNAME("ControlAlignTopRight"), SNAME("EditorIcons")));
+
+ preset_buttons[PRESET_CENTER_LEFT]->set_icon(get_theme_icon(SNAME("ControlAlignCenterLeft"), SNAME("EditorIcons")));
+ preset_buttons[PRESET_CENTER]->set_icon(get_theme_icon(SNAME("ControlAlignCenter"), SNAME("EditorIcons")));
+ preset_buttons[PRESET_CENTER_RIGHT]->set_icon(get_theme_icon(SNAME("ControlAlignCenterRight"), SNAME("EditorIcons")));
+
+ preset_buttons[PRESET_BOTTOM_LEFT]->set_icon(get_theme_icon(SNAME("ControlAlignBottomLeft"), SNAME("EditorIcons")));
+ preset_buttons[PRESET_CENTER_BOTTOM]->set_icon(get_theme_icon(SNAME("ControlAlignCenterBottom"), SNAME("EditorIcons")));
+ preset_buttons[PRESET_BOTTOM_RIGHT]->set_icon(get_theme_icon(SNAME("ControlAlignBottomRight"), SNAME("EditorIcons")));
+
+ preset_buttons[PRESET_TOP_WIDE]->set_icon(get_theme_icon(SNAME("ControlAlignTopWide"), SNAME("EditorIcons")));
+ preset_buttons[PRESET_HCENTER_WIDE]->set_icon(get_theme_icon(SNAME("ControlAlignHCenterWide"), SNAME("EditorIcons")));
+ preset_buttons[PRESET_BOTTOM_WIDE]->set_icon(get_theme_icon(SNAME("ControlAlignBottomWide"), SNAME("EditorIcons")));
+
+ preset_buttons[PRESET_LEFT_WIDE]->set_icon(get_theme_icon(SNAME("ControlAlignLeftWide"), SNAME("EditorIcons")));
+ preset_buttons[PRESET_VCENTER_WIDE]->set_icon(get_theme_icon(SNAME("ControlAlignVCenterWide"), SNAME("EditorIcons")));
+ preset_buttons[PRESET_RIGHT_WIDE]->set_icon(get_theme_icon(SNAME("ControlAlignRightWide"), SNAME("EditorIcons")));
+
+ preset_buttons[PRESET_FULL_RECT]->set_icon(get_theme_icon(SNAME("ControlAlignFullRect"), SNAME("EditorIcons")));
+ } break;
+ }
+}
+
+void AnchorPresetPicker::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("anchors_preset_selected", PropertyInfo(Variant::INT, "preset")));
+}
+
+AnchorPresetPicker::AnchorPresetPicker() {
+ VBoxContainer *main_vb = memnew(VBoxContainer);
+ main_vb->add_theme_constant_override("separation", grid_separation);
+ add_child(main_vb);
+
+ HBoxContainer *top_row = memnew(HBoxContainer);
+ top_row->set_alignment(BoxContainer::ALIGNMENT_CENTER);
+ top_row->add_theme_constant_override("separation", grid_separation);
+ main_vb->add_child(top_row);
+
+ _add_row_button(top_row, PRESET_TOP_LEFT, TTR("Top Left"));
+ _add_row_button(top_row, PRESET_CENTER_TOP, TTR("Center Top"));
+ _add_row_button(top_row, PRESET_TOP_RIGHT, TTR("Top Right"));
+ _add_separator(top_row, memnew(VSeparator));
+ _add_row_button(top_row, PRESET_TOP_WIDE, TTR("Top Wide"));
+
+ HBoxContainer *mid_row = memnew(HBoxContainer);
+ mid_row->set_alignment(BoxContainer::ALIGNMENT_CENTER);
+ mid_row->add_theme_constant_override("separation", grid_separation);
+ main_vb->add_child(mid_row);
+
+ _add_row_button(mid_row, PRESET_CENTER_LEFT, TTR("Center Left"));
+ _add_row_button(mid_row, PRESET_CENTER, TTR("Center"));
+ _add_row_button(mid_row, PRESET_CENTER_RIGHT, TTR("Center Right"));
+ _add_separator(mid_row, memnew(VSeparator));
+ _add_row_button(mid_row, PRESET_HCENTER_WIDE, TTR("HCenter Wide"));
+
+ HBoxContainer *bot_row = memnew(HBoxContainer);
+ bot_row->set_alignment(BoxContainer::ALIGNMENT_CENTER);
+ bot_row->add_theme_constant_override("separation", grid_separation);
+ main_vb->add_child(bot_row);
+
+ _add_row_button(bot_row, PRESET_BOTTOM_LEFT, TTR("Bottom Left"));
+ _add_row_button(bot_row, PRESET_CENTER_BOTTOM, TTR("Center Bottom"));
+ _add_row_button(bot_row, PRESET_BOTTOM_RIGHT, TTR("Bottom Right"));
+ _add_separator(bot_row, memnew(VSeparator));
+ _add_row_button(bot_row, PRESET_BOTTOM_WIDE, TTR("Bottom Wide"));
+
+ _add_separator(main_vb, memnew(HSeparator));
+
+ HBoxContainer *extra_row = memnew(HBoxContainer);
+ extra_row->set_alignment(BoxContainer::ALIGNMENT_CENTER);
+ extra_row->add_theme_constant_override("separation", grid_separation);
+ main_vb->add_child(extra_row);
+
+ _add_row_button(extra_row, PRESET_LEFT_WIDE, TTR("Left Wide"));
+ _add_row_button(extra_row, PRESET_VCENTER_WIDE, TTR("VCenter Wide"));
+ _add_row_button(extra_row, PRESET_RIGHT_WIDE, TTR("Right Wide"));
+ _add_separator(extra_row, memnew(VSeparator));
+ _add_row_button(extra_row, PRESET_FULL_RECT, TTR("Full Rect"));
+}
+
+void SizeFlagPresetPicker::_preset_button_pressed(const int p_preset) {
+ int flags = (SizeFlags)p_preset;
+ if (expand_button->is_pressed()) {
+ flags |= SIZE_EXPAND;
+ }
+
+ emit_signal("size_flags_selected", flags);
+}
+
+void SizeFlagPresetPicker::set_allowed_flags(Vector<SizeFlags> &p_flags) {
+ preset_buttons[SIZE_SHRINK_BEGIN]->set_disabled(!p_flags.has(SIZE_SHRINK_BEGIN));
+ preset_buttons[SIZE_SHRINK_CENTER]->set_disabled(!p_flags.has(SIZE_SHRINK_CENTER));
+ preset_buttons[SIZE_SHRINK_END]->set_disabled(!p_flags.has(SIZE_SHRINK_END));
+ preset_buttons[SIZE_FILL]->set_disabled(!p_flags.has(SIZE_FILL));
+
+ expand_button->set_disabled(!p_flags.has(SIZE_EXPAND));
+ if (p_flags.has(SIZE_EXPAND)) {
+ expand_button->set_tooltip(TTR("Enable to also set the Expand flag.\nDisable to only set Shrink/Fill flags."));
+ } else {
+ expand_button->set_pressed(false);
+ expand_button->set_tooltip(TTR("Some parents of the selected nodes do not support the Expand flag."));
+ }
+}
+
+void SizeFlagPresetPicker::_notification(int p_notification) {
+ switch (p_notification) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ if (vertical) {
+ preset_buttons[SIZE_SHRINK_BEGIN]->set_icon(get_theme_icon(SNAME("ControlAlignCenterTop"), SNAME("EditorIcons")));
+ preset_buttons[SIZE_SHRINK_CENTER]->set_icon(get_theme_icon(SNAME("ControlAlignCenter"), SNAME("EditorIcons")));
+ preset_buttons[SIZE_SHRINK_END]->set_icon(get_theme_icon(SNAME("ControlAlignCenterBottom"), SNAME("EditorIcons")));
+
+ preset_buttons[SIZE_FILL]->set_icon(get_theme_icon(SNAME("ControlAlignVCenterWide"), SNAME("EditorIcons")));
+ } else {
+ preset_buttons[SIZE_SHRINK_BEGIN]->set_icon(get_theme_icon(SNAME("ControlAlignCenterLeft"), SNAME("EditorIcons")));
+ preset_buttons[SIZE_SHRINK_CENTER]->set_icon(get_theme_icon(SNAME("ControlAlignCenter"), SNAME("EditorIcons")));
+ preset_buttons[SIZE_SHRINK_END]->set_icon(get_theme_icon(SNAME("ControlAlignCenterRight"), SNAME("EditorIcons")));
+
+ preset_buttons[SIZE_FILL]->set_icon(get_theme_icon(SNAME("ControlAlignHCenterWide"), SNAME("EditorIcons")));
+ }
+ } break;
+ }
+}
+
+void SizeFlagPresetPicker::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("size_flags_selected", PropertyInfo(Variant::INT, "size_flags")));
+}
+
+SizeFlagPresetPicker::SizeFlagPresetPicker(bool p_vertical) {
+ vertical = p_vertical;
+
+ VBoxContainer *main_vb = memnew(VBoxContainer);
+ add_child(main_vb);
+
+ HBoxContainer *main_row = memnew(HBoxContainer);
+ main_row->set_alignment(BoxContainer::ALIGNMENT_CENTER);
+ main_row->add_theme_constant_override("separation", grid_separation);
+ main_vb->add_child(main_row);
+
+ _add_row_button(main_row, SIZE_SHRINK_BEGIN, TTR("Shrink Begin"));
+ _add_row_button(main_row, SIZE_SHRINK_CENTER, TTR("Shrink Center"));
+ _add_row_button(main_row, SIZE_SHRINK_END, TTR("Shrink End"));
+ _add_separator(main_row, memnew(VSeparator));
+ _add_row_button(main_row, SIZE_FILL, TTR("Fill"));
+
+ expand_button = memnew(CheckBox);
+ expand_button->set_flat(true);
+ expand_button->set_text(TTR("Align with Expand"));
+ expand_button->set_tooltip(TTR("Enable to also set the Expand flag.\nDisable to only set Shrink/Fill flags."));
+ main_vb->add_child(expand_button);
+}
+
+// Toolbar.
+
+void ControlEditorToolbar::_anchors_preset_selected(int p_preset) {
+ LayoutPreset preset = (LayoutPreset)p_preset;
List<Node *> selection = editor_selection->get_selected_node_list();
- undo_redo->create_action(TTR("Change Anchors and Offsets"));
+ undo_redo->create_action(TTR("Change Anchors, Offsets, Grow Direction"));
for (Node *E : selection) {
Control *control = Object::cast_to<Control>(E);
if (control) {
- undo_redo->add_do_method(control, "set_anchors_preset", p_preset);
- switch (p_preset) {
- case PRESET_TOP_LEFT:
- case PRESET_TOP_RIGHT:
- case PRESET_BOTTOM_LEFT:
- case PRESET_BOTTOM_RIGHT:
- case PRESET_CENTER_LEFT:
- case PRESET_CENTER_TOP:
- case PRESET_CENTER_RIGHT:
- case PRESET_CENTER_BOTTOM:
- case PRESET_CENTER:
- undo_redo->add_do_method(control, "set_offsets_preset", p_preset, Control::PRESET_MODE_KEEP_SIZE);
- break;
- case PRESET_LEFT_WIDE:
- case PRESET_TOP_WIDE:
- case PRESET_RIGHT_WIDE:
- case PRESET_BOTTOM_WIDE:
- case PRESET_VCENTER_WIDE:
- case PRESET_HCENTER_WIDE:
- case PRESET_FULL_RECT:
- undo_redo->add_do_method(control, "set_offsets_preset", p_preset, Control::PRESET_MODE_MINSIZE);
- break;
- }
+ undo_redo->add_do_property(control, "anchors_preset", preset);
undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
}
}
@@ -489,10 +736,10 @@ void ControlEditorToolbar::_set_anchors_and_offsets_preset(Control::LayoutPreset
anchor_mode_button->set_pressed(anchors_mode);
}
-void ControlEditorToolbar::_set_anchors_and_offsets_to_keep_ratio() {
+void ControlEditorToolbar::_anchors_to_current_ratio() {
List<Node *> selection = editor_selection->get_selected_node_list();
- undo_redo->create_action(TTR("Change Anchors and Offsets"));
+ undo_redo->create_action(TTR("Change Anchors, Offsets (Keep Ratio)"));
for (Node *E : selection) {
Control *control = Object::cast_to<Control>(E);
@@ -521,44 +768,41 @@ void ControlEditorToolbar::_set_anchors_and_offsets_to_keep_ratio() {
undo_redo->commit_action();
}
-void ControlEditorToolbar::_set_anchors_preset(Control::LayoutPreset p_preset) {
- List<Node *> selection = editor_selection->get_selected_node_list();
+void ControlEditorToolbar::_anchor_mode_toggled(bool p_status) {
+ List<Control *> selection = _get_edited_controls();
+ for (Control *E : selection) {
+ if (Object::cast_to<Container>(E->get_parent())) {
+ continue;
+ }
- undo_redo->create_action(TTR("Change Anchors"));
- for (Node *E : selection) {
- Control *control = Object::cast_to<Control>(E);
- if (control) {
- undo_redo->add_do_method(control, "set_anchors_preset", p_preset);
- undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
+ if (p_status) {
+ E->set_meta("_edit_use_anchors_", true);
+ } else {
+ E->remove_meta("_edit_use_anchors_");
}
}
- undo_redo->commit_action();
+ anchors_mode = p_status;
+ CanvasItemEditor::get_singleton()->update_viewport();
}
-void ControlEditorToolbar::_set_container_h_preset(Control::SizeFlags p_preset) {
+void ControlEditorToolbar::_container_flags_selected(int p_flags, bool p_vertical) {
List<Node *> selection = editor_selection->get_selected_node_list();
- undo_redo->create_action(TTR("Change Horizontal Size Flags"));
- for (Node *E : selection) {
- Control *control = Object::cast_to<Control>(E);
- if (control) {
- undo_redo->add_do_method(control, "set_h_size_flags", p_preset);
- undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
- }
+ if (p_vertical) {
+ undo_redo->create_action(TTR("Change Vertical Size Flags"));
+ } else {
+ undo_redo->create_action(TTR("Change Horizontal Size Flags"));
}
- undo_redo->commit_action();
-}
-
-void ControlEditorToolbar::_set_container_v_preset(Control::SizeFlags p_preset) {
- List<Node *> selection = editor_selection->get_selected_node_list();
-
- undo_redo->create_action(TTR("Change Horizontal Size Flags"));
for (Node *E : selection) {
Control *control = Object::cast_to<Control>(E);
if (control) {
- undo_redo->add_do_method(control, "set_v_size_flags", p_preset);
+ if (p_vertical) {
+ undo_redo->add_do_method(control, "set_v_size_flags", p_flags);
+ } else {
+ undo_redo->add_do_method(control, "set_h_size_flags", p_flags);
+ }
undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
}
}
@@ -594,400 +838,205 @@ Vector2 ControlEditorToolbar::_position_to_anchor(const Control *p_control, Vect
return output;
}
-void ControlEditorToolbar::_button_toggle_anchor_mode(bool p_status) {
- List<Control *> selection = _get_edited_controls(false, false);
- for (Control *E : selection) {
- if (Object::cast_to<Container>(E->get_parent())) {
- continue;
- }
-
- if (p_status) {
- E->set_meta("_edit_use_anchors_", true);
- } else {
- E->remove_meta("_edit_use_anchors_");
- }
- }
-
- anchors_mode = p_status;
- CanvasItemEditor::get_singleton()->update_viewport();
-}
-
bool ControlEditorToolbar::_is_node_locked(const Node *p_node) {
return p_node->get_meta("_edit_lock_", false);
}
-List<Control *> ControlEditorToolbar::_get_edited_controls(bool retrieve_locked, bool remove_controls_if_parent_in_selection) {
+List<Control *> ControlEditorToolbar::_get_edited_controls() {
List<Control *> selection;
for (const KeyValue<Node *, Object *> &E : editor_selection->get_selection()) {
Control *control = Object::cast_to<Control>(E.key);
- if (control && control->is_visible_in_tree() && control->get_viewport() == EditorNode::get_singleton()->get_scene_root() && (retrieve_locked || !_is_node_locked(control))) {
+ if (control && control->is_visible_in_tree() && control->get_viewport() == EditorNode::get_singleton()->get_scene_root() && !_is_node_locked(control)) {
selection.push_back(control);
}
}
- if (remove_controls_if_parent_in_selection) {
- List<Control *> filtered_selection;
- for (Control *E : selection) {
- if (!selection.find(E->get_parent())) {
- filtered_selection.push_back(E);
- }
- }
- return filtered_selection;
- }
-
return selection;
}
-void ControlEditorToolbar::_popup_callback(int p_op) {
- switch (p_op) {
- case ANCHORS_AND_OFFSETS_PRESET_TOP_LEFT: {
- _set_anchors_and_offsets_preset(PRESET_TOP_LEFT);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_TOP_RIGHT: {
- _set_anchors_and_offsets_preset(PRESET_TOP_RIGHT);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_BOTTOM_LEFT: {
- _set_anchors_and_offsets_preset(PRESET_BOTTOM_LEFT);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_BOTTOM_RIGHT: {
- _set_anchors_and_offsets_preset(PRESET_BOTTOM_RIGHT);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_CENTER_LEFT: {
- _set_anchors_and_offsets_preset(PRESET_CENTER_LEFT);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_CENTER_RIGHT: {
- _set_anchors_and_offsets_preset(PRESET_CENTER_RIGHT);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_CENTER_TOP: {
- _set_anchors_and_offsets_preset(PRESET_CENTER_TOP);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_CENTER_BOTTOM: {
- _set_anchors_and_offsets_preset(PRESET_CENTER_BOTTOM);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_CENTER: {
- _set_anchors_and_offsets_preset(PRESET_CENTER);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_TOP_WIDE: {
- _set_anchors_and_offsets_preset(PRESET_TOP_WIDE);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_LEFT_WIDE: {
- _set_anchors_and_offsets_preset(PRESET_LEFT_WIDE);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_RIGHT_WIDE: {
- _set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_BOTTOM_WIDE: {
- _set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_VCENTER_WIDE: {
- _set_anchors_and_offsets_preset(PRESET_VCENTER_WIDE);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE: {
- _set_anchors_and_offsets_preset(PRESET_HCENTER_WIDE);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_FULL_RECT: {
- _set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
- } break;
- case ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO: {
- _set_anchors_and_offsets_to_keep_ratio();
- } break;
-
- case ANCHORS_PRESET_TOP_LEFT: {
- _set_anchors_preset(PRESET_TOP_LEFT);
- } break;
- case ANCHORS_PRESET_TOP_RIGHT: {
- _set_anchors_preset(PRESET_TOP_RIGHT);
- } break;
- case ANCHORS_PRESET_BOTTOM_LEFT: {
- _set_anchors_preset(PRESET_BOTTOM_LEFT);
- } break;
- case ANCHORS_PRESET_BOTTOM_RIGHT: {
- _set_anchors_preset(PRESET_BOTTOM_RIGHT);
- } break;
- case ANCHORS_PRESET_CENTER_LEFT: {
- _set_anchors_preset(PRESET_CENTER_LEFT);
- } break;
- case ANCHORS_PRESET_CENTER_RIGHT: {
- _set_anchors_preset(PRESET_CENTER_RIGHT);
- } break;
- case ANCHORS_PRESET_CENTER_TOP: {
- _set_anchors_preset(PRESET_CENTER_TOP);
- } break;
- case ANCHORS_PRESET_CENTER_BOTTOM: {
- _set_anchors_preset(PRESET_CENTER_BOTTOM);
- } break;
- case ANCHORS_PRESET_CENTER: {
- _set_anchors_preset(PRESET_CENTER);
- } break;
- case ANCHORS_PRESET_TOP_WIDE: {
- _set_anchors_preset(PRESET_TOP_WIDE);
- } break;
- case ANCHORS_PRESET_LEFT_WIDE: {
- _set_anchors_preset(PRESET_LEFT_WIDE);
- } break;
- case ANCHORS_PRESET_RIGHT_WIDE: {
- _set_anchors_preset(PRESET_RIGHT_WIDE);
- } break;
- case ANCHORS_PRESET_BOTTOM_WIDE: {
- _set_anchors_preset(PRESET_BOTTOM_WIDE);
- } break;
- case ANCHORS_PRESET_VCENTER_WIDE: {
- _set_anchors_preset(PRESET_VCENTER_WIDE);
- } break;
- case ANCHORS_PRESET_HCENTER_WIDE: {
- _set_anchors_preset(PRESET_HCENTER_WIDE);
- } break;
- case ANCHORS_PRESET_FULL_RECT: {
- _set_anchors_preset(Control::PRESET_FULL_RECT);
- } break;
-
- case CONTAINERS_H_PRESET_FILL: {
- _set_container_h_preset(Control::SIZE_FILL);
- } break;
- case CONTAINERS_H_PRESET_FILL_EXPAND: {
- _set_container_h_preset(Control::SIZE_EXPAND_FILL);
- } break;
- case CONTAINERS_H_PRESET_SHRINK_BEGIN: {
- _set_container_h_preset(Control::SIZE_SHRINK_BEGIN);
- } break;
- case CONTAINERS_H_PRESET_SHRINK_CENTER: {
- _set_container_h_preset(Control::SIZE_SHRINK_CENTER);
- } break;
- case CONTAINERS_H_PRESET_SHRINK_END: {
- _set_container_h_preset(Control::SIZE_SHRINK_END);
- } break;
-
- case CONTAINERS_V_PRESET_FILL: {
- _set_container_v_preset(Control::SIZE_FILL);
- } break;
- case CONTAINERS_V_PRESET_FILL_EXPAND: {
- _set_container_v_preset(Control::SIZE_EXPAND_FILL);
- } break;
- case CONTAINERS_V_PRESET_SHRINK_BEGIN: {
- _set_container_v_preset(Control::SIZE_SHRINK_BEGIN);
- } break;
- case CONTAINERS_V_PRESET_SHRINK_CENTER: {
- _set_container_v_preset(Control::SIZE_SHRINK_CENTER);
- } break;
- case CONTAINERS_V_PRESET_SHRINK_END: {
- _set_container_v_preset(Control::SIZE_SHRINK_END);
- } break;
- }
-}
-
void ControlEditorToolbar::_selection_changed() {
- // Update the anchors_mode.
- int nb_controls = 0;
- int nb_valid_controls = 0;
- int nb_anchors_mode = 0;
+ // Update toolbar visibility.
+ bool has_controls = false;
+ bool has_control_parents = false;
+ bool has_container_parents = false;
+
+ // Also update which size flags can be configured for the selected nodes.
+ Vector<SizeFlags> allowed_h_flags = {
+ SIZE_SHRINK_BEGIN,
+ SIZE_SHRINK_CENTER,
+ SIZE_SHRINK_END,
+ SIZE_FILL,
+ SIZE_EXPAND,
+ };
+ Vector<SizeFlags> allowed_v_flags = {
+ SIZE_SHRINK_BEGIN,
+ SIZE_SHRINK_CENTER,
+ SIZE_SHRINK_END,
+ SIZE_FILL,
+ SIZE_EXPAND,
+ };
- List<Node *> selection = editor_selection->get_selected_node_list();
- for (Node *E : selection) {
- Control *control = Object::cast_to<Control>(E);
+ for (const KeyValue<Node *, Object *> &E : editor_selection->get_selection()) {
+ Control *control = Object::cast_to<Control>(E.key);
if (!control) {
continue;
}
+ has_controls = true;
- nb_controls++;
+ if (Object::cast_to<Control>(control->get_parent())) {
+ has_control_parents = true;
+ }
if (Object::cast_to<Container>(control->get_parent())) {
- continue;
+ has_container_parents = true;
+
+ Container *parent_container = Object::cast_to<Container>(control->get_parent());
+
+ Vector<int> container_h_flags = parent_container->get_allowed_size_flags_horizontal();
+ Vector<SizeFlags> tmp_flags = allowed_h_flags.duplicate();
+ for (int i = 0; i < allowed_h_flags.size(); i++) {
+ if (!container_h_flags.has((int)allowed_h_flags[i])) {
+ tmp_flags.erase(allowed_h_flags[i]);
+ }
+ }
+ allowed_h_flags = tmp_flags;
+
+ Vector<int> container_v_flags = parent_container->get_allowed_size_flags_vertical();
+ tmp_flags = allowed_v_flags.duplicate();
+ for (int i = 0; i < allowed_v_flags.size(); i++) {
+ if (!container_v_flags.has((int)allowed_v_flags[i])) {
+ tmp_flags.erase(allowed_v_flags[i]);
+ }
+ }
+ allowed_v_flags = tmp_flags;
}
+ }
+
+ // Set general toolbar visibility.
+ set_visible(has_controls);
+
+ // Set anchor tools visibility.
+ if (has_controls && (!has_control_parents || !has_container_parents)) {
+ anchors_button->set_visible(true);
+ anchor_mode_button->set_visible(true);
+
+ // Update anchor mode.
+ int nb_valid_controls = 0;
+ int nb_anchors_mode = 0;
- nb_valid_controls++;
- if (control->get_meta("_edit_use_anchors_", false)) {
- nb_anchors_mode++;
+ List<Node *> selection = editor_selection->get_selected_node_list();
+ for (Node *E : selection) {
+ Control *control = Object::cast_to<Control>(E);
+ if (!control) {
+ continue;
+ }
+ if (Object::cast_to<Container>(control->get_parent())) {
+ continue;
+ }
+
+ nb_valid_controls++;
+ if (control->get_meta("_edit_use_anchors_", false)) {
+ nb_anchors_mode++;
+ }
}
+
+ anchors_mode = (nb_valid_controls == nb_anchors_mode);
+ anchor_mode_button->set_pressed(anchors_mode);
+ } else {
+ anchors_button->set_visible(false);
+ anchor_mode_button->set_visible(false);
+ anchor_mode_button->set_pressed(false);
}
- anchors_mode = (nb_valid_controls == nb_anchors_mode);
- anchor_mode_button->set_pressed(anchors_mode);
+ // Set container tools visibility.
+ if (has_controls && (!has_control_parents || has_container_parents)) {
+ containers_button->set_visible(true);
- if (nb_controls > 0) {
- set_physics_process(true);
+ // Update allowed size flags.
+ if (has_container_parents) {
+ container_h_picker->set_allowed_flags(allowed_h_flags);
+ container_v_picker->set_allowed_flags(allowed_v_flags);
+ } else {
+ Vector<SizeFlags> allowed_all_flags = {
+ SIZE_SHRINK_BEGIN,
+ SIZE_SHRINK_CENTER,
+ SIZE_SHRINK_END,
+ SIZE_FILL,
+ SIZE_EXPAND,
+ };
+
+ container_h_picker->set_allowed_flags(allowed_all_flags);
+ container_v_picker->set_allowed_flags(allowed_all_flags);
+ }
} else {
- set_physics_process(false);
- set_visible(false);
+ containers_button->set_visible(false);
}
}
void ControlEditorToolbar::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
- case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- anchor_presets_menu->set_icon(get_theme_icon(SNAME("ControlLayout"), SNAME("EditorIcons")));
-
- PopupMenu *p = anchor_presets_menu->get_popup();
- p->clear();
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignTopLeft"), SNAME("EditorIcons")), TTR("Top Left"), ANCHORS_AND_OFFSETS_PRESET_TOP_LEFT);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignTopRight"), SNAME("EditorIcons")), TTR("Top Right"), ANCHORS_AND_OFFSETS_PRESET_TOP_RIGHT);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomRight"), SNAME("EditorIcons")), TTR("Bottom Right"), ANCHORS_AND_OFFSETS_PRESET_BOTTOM_RIGHT);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomLeft"), SNAME("EditorIcons")), TTR("Bottom Left"), ANCHORS_AND_OFFSETS_PRESET_BOTTOM_LEFT);
- p->add_separator();
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignCenterLeft"), SNAME("EditorIcons")), TTR("Center Left"), ANCHORS_AND_OFFSETS_PRESET_CENTER_LEFT);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignCenterTop"), SNAME("EditorIcons")), TTR("Center Top"), ANCHORS_AND_OFFSETS_PRESET_CENTER_TOP);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignCenterRight"), SNAME("EditorIcons")), TTR("Center Right"), ANCHORS_AND_OFFSETS_PRESET_CENTER_RIGHT);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignCenterBottom"), SNAME("EditorIcons")), TTR("Center Bottom"), ANCHORS_AND_OFFSETS_PRESET_CENTER_BOTTOM);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignCenter"), SNAME("EditorIcons")), TTR("Center"), ANCHORS_AND_OFFSETS_PRESET_CENTER);
- p->add_separator();
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignLeftWide"), SNAME("EditorIcons")), TTR("Left Wide"), ANCHORS_AND_OFFSETS_PRESET_LEFT_WIDE);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignTopWide"), SNAME("EditorIcons")), TTR("Top Wide"), ANCHORS_AND_OFFSETS_PRESET_TOP_WIDE);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignRightWide"), SNAME("EditorIcons")), TTR("Right Wide"), ANCHORS_AND_OFFSETS_PRESET_RIGHT_WIDE);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomWide"), SNAME("EditorIcons")), TTR("Bottom Wide"), ANCHORS_AND_OFFSETS_PRESET_BOTTOM_WIDE);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignVCenterWide"), SNAME("EditorIcons")), TTR("VCenter Wide"), ANCHORS_AND_OFFSETS_PRESET_VCENTER_WIDE);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignHCenterWide"), SNAME("EditorIcons")), TTR("HCenter Wide"), ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE);
- p->add_separator();
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignFullRect"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_AND_OFFSETS_PRESET_FULL_RECT);
- p->add_icon_item(get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons")), TTR("Keep Current Ratio"), ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO);
- p->set_item_tooltip(19, TTR("Adjust anchors and offsets to match the current rect size."));
-
- p->add_separator();
- p->add_submenu_item(TTR("Anchors only"), "Anchors");
- p->set_item_icon(21, get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons")));
-
- anchors_popup->clear();
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignTopLeft"), SNAME("EditorIcons")), TTR("Top Left"), ANCHORS_PRESET_TOP_LEFT);
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignTopRight"), SNAME("EditorIcons")), TTR("Top Right"), ANCHORS_PRESET_TOP_RIGHT);
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomRight"), SNAME("EditorIcons")), TTR("Bottom Right"), ANCHORS_PRESET_BOTTOM_RIGHT);
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomLeft"), SNAME("EditorIcons")), TTR("Bottom Left"), ANCHORS_PRESET_BOTTOM_LEFT);
- anchors_popup->add_separator();
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignCenterLeft"), SNAME("EditorIcons")), TTR("Center Left"), ANCHORS_PRESET_CENTER_LEFT);
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignCenterTop"), SNAME("EditorIcons")), TTR("Center Top"), ANCHORS_PRESET_CENTER_TOP);
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignCenterRight"), SNAME("EditorIcons")), TTR("Center Right"), ANCHORS_PRESET_CENTER_RIGHT);
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignCenterBottom"), SNAME("EditorIcons")), TTR("Center Bottom"), ANCHORS_PRESET_CENTER_BOTTOM);
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignCenter"), SNAME("EditorIcons")), TTR("Center"), ANCHORS_PRESET_CENTER);
- anchors_popup->add_separator();
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignLeftWide"), SNAME("EditorIcons")), TTR("Left Wide"), ANCHORS_PRESET_LEFT_WIDE);
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignTopWide"), SNAME("EditorIcons")), TTR("Top Wide"), ANCHORS_PRESET_TOP_WIDE);
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignRightWide"), SNAME("EditorIcons")), TTR("Right Wide"), ANCHORS_PRESET_RIGHT_WIDE);
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignBottomWide"), SNAME("EditorIcons")), TTR("Bottom Wide"), ANCHORS_PRESET_BOTTOM_WIDE);
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignVCenterWide"), SNAME("EditorIcons")), TTR("VCenter Wide"), ANCHORS_PRESET_VCENTER_WIDE);
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignHCenterWide"), SNAME("EditorIcons")), TTR("HCenter Wide"), ANCHORS_PRESET_HCENTER_WIDE);
- anchors_popup->add_separator();
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignFullRect"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_PRESET_FULL_RECT);
-
+ case NOTIFICATION_THEME_CHANGED: {
+ anchors_button->set_icon(get_theme_icon(SNAME("ControlLayout"), SNAME("EditorIcons")));
anchor_mode_button->set_icon(get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons")));
-
- container_h_presets_menu->set_icon(get_theme_icon(SNAME("Container"), SNAME("EditorIcons")));
- container_v_presets_menu->set_icon(get_theme_icon(SNAME("Container"), SNAME("EditorIcons")));
-
- p = container_h_presets_menu->get_popup();
- p->clear();
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignHCenterWide"), SNAME("EditorIcons")), TTR("Fill"), CONTAINERS_H_PRESET_FILL);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignHCenterWide"), SNAME("EditorIcons")), TTR("Fill & Expand"), CONTAINERS_H_PRESET_FILL_EXPAND);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignCenterLeft"), SNAME("EditorIcons")), TTR("Shrink Begin"), CONTAINERS_H_PRESET_SHRINK_BEGIN);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignCenter"), SNAME("EditorIcons")), TTR("Shrink Center"), CONTAINERS_H_PRESET_SHRINK_CENTER);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignCenterRight"), SNAME("EditorIcons")), TTR("Shrink End"), CONTAINERS_H_PRESET_SHRINK_END);
-
- p = container_v_presets_menu->get_popup();
- p->clear();
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignVCenterWide"), SNAME("EditorIcons")), TTR("Fill"), CONTAINERS_V_PRESET_FILL);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignVCenterWide"), SNAME("EditorIcons")), TTR("Fill & Expand"), CONTAINERS_V_PRESET_FILL_EXPAND);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignCenterTop"), SNAME("EditorIcons")), TTR("Shrink Begin"), CONTAINERS_V_PRESET_SHRINK_BEGIN);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignCenter"), SNAME("EditorIcons")), TTR("Shrink Center"), CONTAINERS_V_PRESET_SHRINK_CENTER);
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignCenterBottom"), SNAME("EditorIcons")), TTR("Shrink End"), CONTAINERS_V_PRESET_SHRINK_END);
- } break;
-
- case NOTIFICATION_PHYSICS_PROCESS: {
- bool has_control_parents = false;
- bool has_container_parents = false;
-
- // Update the viewport if the canvas_item changes
- List<Control *> selection = _get_edited_controls(true);
- for (Control *control : selection) {
- if (Object::cast_to<Control>(control->get_parent())) {
- has_control_parents = true;
- }
- if (Object::cast_to<Container>(control->get_parent())) {
- has_container_parents = true;
- }
- }
-
- // Show / Hide the control layout buttons.
- if (selection.size() > 0) {
- set_visible(true);
-
- // Toggle anchor and container layout buttons depending on parents of the selected nodes.
- // - If there are no control parents, enable everything.
- // - If there are container parents, then enable only container buttons.
- // - If there are NO container parents, then enable only anchor buttons.
- bool enable_anchors = false;
- bool enable_containers = false;
- if (!has_control_parents) {
- enable_anchors = true;
- enable_containers = true;
- } else if (has_container_parents) {
- enable_containers = true;
- } else {
- enable_anchors = true;
- }
-
- if (enable_anchors) {
- anchor_presets_menu->set_visible(true);
- anchor_mode_button->set_visible(true);
- } else {
- anchor_presets_menu->set_visible(false);
- anchor_mode_button->set_visible(false);
- }
-
- if (enable_containers) {
- container_h_presets_menu->set_visible(true);
- container_v_presets_menu->set_visible(true);
- } else {
- container_h_presets_menu->set_visible(false);
- container_v_presets_menu->set_visible(false);
- }
- } else {
- set_visible(false);
- }
+ containers_button->set_icon(get_theme_icon(SNAME("ContainerLayout"), SNAME("EditorIcons")));
} break;
}
}
ControlEditorToolbar::ControlEditorToolbar() {
- anchor_presets_menu = memnew(MenuButton);
- anchor_presets_menu->set_shortcut_context(this);
- anchor_presets_menu->set_text(TTR("Anchors"));
- anchor_presets_menu->set_tooltip(TTR("Presets for the anchor and offset values of a Control node."));
- add_child(anchor_presets_menu);
- anchor_presets_menu->set_switch_on_hover(true);
+ add_child(memnew(VSeparator));
- PopupMenu *p = anchor_presets_menu->get_popup();
- p->connect("id_pressed", callable_mp(this, &ControlEditorToolbar::_popup_callback));
+ // Anchor and offset tools.
+ anchors_button = memnew(ControlEditorPopupButton);
+ anchors_button->set_tooltip(TTR("Presets for the anchor and offset values of a Control node."));
+ add_child(anchors_button);
- anchors_popup = memnew(PopupMenu);
- p->add_child(anchors_popup);
- anchors_popup->set_name("Anchors");
- anchors_popup->connect("id_pressed", callable_mp(this, &ControlEditorToolbar::_popup_callback));
+ Label *anchors_label = memnew(Label);
+ anchors_label->set_text(TTR("Anchor preset"));
+ anchors_button->get_popup_hbox()->add_child(anchors_label);
+ AnchorPresetPicker *anchors_picker = memnew(AnchorPresetPicker);
+ anchors_picker->set_h_size_flags(SIZE_SHRINK_CENTER);
+ anchors_button->get_popup_hbox()->add_child(anchors_picker);
+ anchors_picker->connect("anchors_preset_selected", callable_mp(this, &ControlEditorToolbar::_anchors_preset_selected));
+
+ anchors_button->get_popup_hbox()->add_child(memnew(HSeparator));
+
+ Button *keep_ratio_button = memnew(Button);
+ keep_ratio_button->set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT);
+ keep_ratio_button->set_text(TTR("Set to Current Ratio"));
+ keep_ratio_button->set_tooltip(TTR("Adjust anchors and offsets to match the current rect size."));
+ anchors_button->get_popup_hbox()->add_child(keep_ratio_button);
+ keep_ratio_button->connect("pressed", callable_mp(this, &ControlEditorToolbar::_anchors_to_current_ratio));
anchor_mode_button = memnew(Button);
anchor_mode_button->set_flat(true);
anchor_mode_button->set_toggle_mode(true);
anchor_mode_button->set_tooltip(TTR("When active, moving Control nodes changes their anchors instead of their offsets."));
add_child(anchor_mode_button);
- anchor_mode_button->connect("toggled", callable_mp(this, &ControlEditorToolbar::_button_toggle_anchor_mode));
-
- add_child(memnew(VSeparator));
-
- container_h_presets_menu = memnew(MenuButton);
- container_h_presets_menu->set_shortcut_context(this);
- container_h_presets_menu->set_text(TTR("Horizontal"));
- container_h_presets_menu->set_tooltip(TTR("Horizontal sizing setting for children of a Container node."));
- add_child(container_h_presets_menu);
- container_h_presets_menu->set_switch_on_hover(true);
-
- p = container_h_presets_menu->get_popup();
- p->connect("id_pressed", callable_mp(this, &ControlEditorToolbar::_popup_callback));
-
- container_v_presets_menu = memnew(MenuButton);
- container_v_presets_menu->set_shortcut_context(this);
- container_v_presets_menu->set_text(TTR("Vertical"));
- container_v_presets_menu->set_tooltip(TTR("Vertical sizing setting for children of a Container node."));
- add_child(container_v_presets_menu);
- container_v_presets_menu->set_switch_on_hover(true);
-
- p = container_v_presets_menu->get_popup();
- p->connect("id_pressed", callable_mp(this, &ControlEditorToolbar::_popup_callback));
-
+ anchor_mode_button->connect("toggled", callable_mp(this, &ControlEditorToolbar::_anchor_mode_toggled));
+
+ // Container tools.
+ containers_button = memnew(ControlEditorPopupButton);
+ containers_button->set_tooltip(TTR("Sizing settings for children of a Container node."));
+ add_child(containers_button);
+
+ Label *container_h_label = memnew(Label);
+ container_h_label->set_text(TTR("Horizontal alignment"));
+ containers_button->get_popup_hbox()->add_child(container_h_label);
+ container_h_picker = memnew(SizeFlagPresetPicker(false));
+ containers_button->get_popup_hbox()->add_child(container_h_picker);
+ container_h_picker->connect("size_flags_selected", callable_mp(this, &ControlEditorToolbar::_container_flags_selected).bind(false));
+
+ containers_button->get_popup_hbox()->add_child(memnew(HSeparator));
+
+ Label *container_v_label = memnew(Label);
+ container_v_label->set_text(TTR("Vertical alignment"));
+ containers_button->get_popup_hbox()->add_child(container_v_label);
+ container_v_picker = memnew(SizeFlagPresetPicker(true));
+ containers_button->get_popup_hbox()->add_child(container_v_picker);
+ container_v_picker->connect("size_flags_selected", callable_mp(this, &ControlEditorToolbar::_container_flags_selected).bind(true));
+
+ // Editor connections.
undo_redo = EditorNode::get_singleton()->get_undo_redo();
editor_selection = EditorNode::get_singleton()->get_editor_selection();
editor_selection->add_editor_plugin(this);
@@ -998,6 +1047,8 @@ ControlEditorToolbar::ControlEditorToolbar() {
ControlEditorToolbar *ControlEditorToolbar::singleton = nullptr;
+// Editor plugin.
+
ControlEditorPlugin::ControlEditorPlugin() {
toolbar = memnew(ControlEditorToolbar);
toolbar->hide();
diff --git a/editor/plugins/control_editor_plugin.h b/editor/plugins/control_editor_plugin.h
index 11389bc095..584d05aab0 100644
--- a/editor/plugins/control_editor_plugin.h
+++ b/editor/plugins/control_editor_plugin.h
@@ -33,14 +33,20 @@
#include "editor/editor_plugin.h"
#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
#include "scene/gui/check_box.h"
#include "scene/gui/control.h"
#include "scene/gui/label.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/option_button.h"
#include "scene/gui/panel_container.h"
+#include "scene/gui/popup.h"
+#include "scene/gui/separator.h"
#include "scene/gui/texture_rect.h"
+class EditorUndoRedoManager;
+
+// Inspector controls.
class ControlPositioningWarning : public MarginContainer {
GDCLASS(ControlPositioningWarning, MarginContainer);
@@ -125,102 +131,101 @@ public:
virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override;
};
+// Toolbar controls.
+class ControlEditorPopupButton : public Button {
+ GDCLASS(ControlEditorPopupButton, Button);
+
+ Ref<Texture2D> arrow_icon;
+
+ PopupPanel *popup_panel = nullptr;
+ VBoxContainer *popup_vbox = nullptr;
+
+ void _popup_visibility_changed(bool p_visible);
+
+protected:
+ void _notification(int p_what);
+
+public:
+ virtual Size2 get_minimum_size() const override;
+ virtual void toggled(bool p_pressed) override;
+
+ VBoxContainer *get_popup_hbox() const { return popup_vbox; }
+
+ ControlEditorPopupButton();
+};
+
+class ControlEditorPresetPicker : public MarginContainer {
+ GDCLASS(ControlEditorPresetPicker, MarginContainer);
+
+ virtual void _preset_button_pressed(const int p_preset) {}
+
+protected:
+ static constexpr int grid_separation = 0;
+ HashMap<int, Button *> preset_buttons;
+
+ void _add_row_button(HBoxContainer *p_row, const int p_preset, const String &p_name);
+ void _add_separator(BoxContainer *p_box, Separator *p_separator);
+
+public:
+ ControlEditorPresetPicker() {}
+};
+
+class AnchorPresetPicker : public ControlEditorPresetPicker {
+ GDCLASS(AnchorPresetPicker, ControlEditorPresetPicker);
+
+ virtual void _preset_button_pressed(const int p_preset) override;
+
+protected:
+ void _notification(int p_notification);
+ static void _bind_methods();
+
+public:
+ AnchorPresetPicker();
+};
+
+class SizeFlagPresetPicker : public ControlEditorPresetPicker {
+ GDCLASS(SizeFlagPresetPicker, ControlEditorPresetPicker);
+
+ CheckBox *expand_button;
+
+ bool vertical = false;
+
+ virtual void _preset_button_pressed(const int p_preset) override;
+
+protected:
+ void _notification(int p_notification);
+ static void _bind_methods();
+
+public:
+ void set_allowed_flags(Vector<SizeFlags> &p_flags);
+
+ SizeFlagPresetPicker(bool p_vertical);
+};
+
class ControlEditorToolbar : public HBoxContainer {
GDCLASS(ControlEditorToolbar, HBoxContainer);
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
EditorSelection *editor_selection = nullptr;
- enum MenuOption {
- ANCHORS_AND_OFFSETS_PRESET_TOP_LEFT,
- ANCHORS_AND_OFFSETS_PRESET_TOP_RIGHT,
- ANCHORS_AND_OFFSETS_PRESET_BOTTOM_LEFT,
- ANCHORS_AND_OFFSETS_PRESET_BOTTOM_RIGHT,
- ANCHORS_AND_OFFSETS_PRESET_CENTER_LEFT,
- ANCHORS_AND_OFFSETS_PRESET_CENTER_RIGHT,
- ANCHORS_AND_OFFSETS_PRESET_CENTER_TOP,
- ANCHORS_AND_OFFSETS_PRESET_CENTER_BOTTOM,
- ANCHORS_AND_OFFSETS_PRESET_CENTER,
- ANCHORS_AND_OFFSETS_PRESET_TOP_WIDE,
- ANCHORS_AND_OFFSETS_PRESET_LEFT_WIDE,
- ANCHORS_AND_OFFSETS_PRESET_RIGHT_WIDE,
- ANCHORS_AND_OFFSETS_PRESET_BOTTOM_WIDE,
- ANCHORS_AND_OFFSETS_PRESET_VCENTER_WIDE,
- ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE,
- ANCHORS_AND_OFFSETS_PRESET_FULL_RECT,
-
- ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO,
-
- ANCHORS_PRESET_TOP_LEFT,
- ANCHORS_PRESET_TOP_RIGHT,
- ANCHORS_PRESET_BOTTOM_LEFT,
- ANCHORS_PRESET_BOTTOM_RIGHT,
- ANCHORS_PRESET_CENTER_LEFT,
- ANCHORS_PRESET_CENTER_RIGHT,
- ANCHORS_PRESET_CENTER_TOP,
- ANCHORS_PRESET_CENTER_BOTTOM,
- ANCHORS_PRESET_CENTER,
- ANCHORS_PRESET_TOP_WIDE,
- ANCHORS_PRESET_LEFT_WIDE,
- ANCHORS_PRESET_RIGHT_WIDE,
- ANCHORS_PRESET_BOTTOM_WIDE,
- ANCHORS_PRESET_VCENTER_WIDE,
- ANCHORS_PRESET_HCENTER_WIDE,
- ANCHORS_PRESET_FULL_RECT,
-
- // Offsets Presets are not currently in use.
- OFFSETS_PRESET_TOP_LEFT,
- OFFSETS_PRESET_TOP_RIGHT,
- OFFSETS_PRESET_BOTTOM_LEFT,
- OFFSETS_PRESET_BOTTOM_RIGHT,
- OFFSETS_PRESET_CENTER_LEFT,
- OFFSETS_PRESET_CENTER_RIGHT,
- OFFSETS_PRESET_CENTER_TOP,
- OFFSETS_PRESET_CENTER_BOTTOM,
- OFFSETS_PRESET_CENTER,
- OFFSETS_PRESET_TOP_WIDE,
- OFFSETS_PRESET_LEFT_WIDE,
- OFFSETS_PRESET_RIGHT_WIDE,
- OFFSETS_PRESET_BOTTOM_WIDE,
- OFFSETS_PRESET_VCENTER_WIDE,
- OFFSETS_PRESET_HCENTER_WIDE,
- OFFSETS_PRESET_FULL_RECT,
-
- CONTAINERS_H_PRESET_FILL,
- CONTAINERS_H_PRESET_FILL_EXPAND,
- CONTAINERS_H_PRESET_SHRINK_BEGIN,
- CONTAINERS_H_PRESET_SHRINK_CENTER,
- CONTAINERS_H_PRESET_SHRINK_END,
- CONTAINERS_V_PRESET_FILL,
- CONTAINERS_V_PRESET_FILL_EXPAND,
- CONTAINERS_V_PRESET_SHRINK_BEGIN,
- CONTAINERS_V_PRESET_SHRINK_CENTER,
- CONTAINERS_V_PRESET_SHRINK_END,
- };
-
- MenuButton *anchor_presets_menu = nullptr;
- PopupMenu *anchors_popup = nullptr;
- MenuButton *container_h_presets_menu = nullptr;
- MenuButton *container_v_presets_menu = nullptr;
-
+ ControlEditorPopupButton *anchors_button = nullptr;
+ ControlEditorPopupButton *containers_button = nullptr;
Button *anchor_mode_button = nullptr;
+ SizeFlagPresetPicker *container_h_picker = nullptr;
+ SizeFlagPresetPicker *container_v_picker = nullptr;
+
bool anchors_mode = false;
- void _set_anchors_preset(Control::LayoutPreset p_preset);
- void _set_anchors_and_offsets_preset(Control::LayoutPreset p_preset);
- void _set_anchors_and_offsets_to_keep_ratio();
- void _set_container_h_preset(Control::SizeFlags p_preset);
- void _set_container_v_preset(Control::SizeFlags p_preset);
+ void _anchors_preset_selected(int p_preset);
+ void _anchors_to_current_ratio();
+ void _anchor_mode_toggled(bool p_status);
+ void _container_flags_selected(int p_flags, bool p_vertical);
Vector2 _anchor_to_position(const Control *p_control, Vector2 anchor);
Vector2 _position_to_anchor(const Control *p_control, Vector2 position);
-
- void _button_toggle_anchor_mode(bool p_status);
-
bool _is_node_locked(const Node *p_node);
- List<Control *> _get_edited_controls(bool retrieve_locked = false, bool remove_controls_if_parent_in_selection = true);
- void _popup_callback(int p_op);
+ List<Control *> _get_edited_controls();
void _selection_changed();
protected:
@@ -236,6 +241,7 @@ public:
ControlEditorToolbar();
};
+// Editor plugin.
class ControlEditorPlugin : public EditorPlugin {
GDCLASS(ControlEditorPlugin, EditorPlugin);
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.cpp b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
index a7c3c32120..e20d298195 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
@@ -34,6 +34,7 @@
#include "core/io/image_loader.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/2d/cpu_particles_2d.h"
#include "scene/gui/separator.h"
#include "scene/resources/particles_material.h"
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.h b/editor/plugins/cpu_particles_2d_editor_plugin.h
index cc59bc924f..06ca208463 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.h
@@ -39,6 +39,7 @@
class EditorPlugin;
class SpinBox;
class EditorFileDialog;
+class EditorUndoRedoManager;
class CPUParticles2DEditorPlugin : public EditorPlugin {
GDCLASS(CPUParticles2DEditorPlugin, EditorPlugin);
@@ -70,7 +71,7 @@ class CPUParticles2DEditorPlugin : public EditorPlugin {
String source_emission_file;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
void _file_selected(const String &p_file);
void _menu_callback(int p_idx);
void _generate_emission_mask();
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index 8aeab684e3..013a9f10a4 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -139,14 +139,14 @@ void CurveEditor::gui_input(const Ref<InputEvent> &p_event) {
if (!mb.is_pressed() && _dragging && mb.get_button_index() == MouseButton::LEFT) {
_dragging = false;
if (_has_undo_data) {
- UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
- ur.create_action(_selected_tangent == TANGENT_NONE ? TTR("Modify Curve Point") : TTR("Modify Curve Tangent"));
- ur.add_do_method(*_curve_ref, "_set_data", _curve_ref->get_data());
- ur.add_undo_method(*_curve_ref, "_set_data", _undo_data);
+ ur->create_action(_selected_tangent == TANGENT_NONE ? TTR("Modify Curve Point") : TTR("Modify Curve Tangent"));
+ ur->add_do_method(*_curve_ref, "_set_data", _curve_ref->get_data());
+ ur->add_undo_method(*_curve_ref, "_set_data", _undo_data);
// Note: this will trigger one more "changed" signal even if nothing changes,
// but it's ok since it would have fired every frame during the drag anyways
- ur.commit_action();
+ ur->commit_action();
_has_undo_data = false;
}
@@ -301,13 +301,13 @@ void CurveEditor::on_preset_item_selected(int preset_id) {
break;
}
- UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo();
- ur.create_action(TTR("Load Curve Preset"));
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
+ ur->create_action(TTR("Load Curve Preset"));
- ur.add_do_method(&curve, "_set_data", curve.get_data());
- ur.add_undo_method(&curve, "_set_data", previous_data);
+ ur->add_do_method(&curve, "_set_data", curve.get_data());
+ ur->add_undo_method(&curve, "_set_data", previous_data);
- ur.commit_action();
+ ur->commit_action();
}
void CurveEditor::_curve_changed() {
@@ -435,8 +435,8 @@ CurveEditor::TangentIndex CurveEditor::get_tangent_at(Vector2 pos) const {
void CurveEditor::add_point(Vector2 pos) {
ERR_FAIL_COND(_curve_ref.is_null());
- UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo();
- ur.create_action(TTR("Remove Curve Point"));
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
+ ur->create_action(TTR("Remove Curve Point"));
Vector2 point_pos = get_world_pos(pos);
if (point_pos.y < 0.0) {
@@ -449,22 +449,22 @@ void CurveEditor::add_point(Vector2 pos) {
int i = _curve_ref->add_point(point_pos);
_curve_ref->remove_point(i);
- ur.add_do_method(*_curve_ref, "add_point", point_pos);
- ur.add_undo_method(*_curve_ref, "remove_point", i);
+ ur->add_do_method(*_curve_ref, "add_point", point_pos);
+ ur->add_undo_method(*_curve_ref, "remove_point", i);
- ur.commit_action();
+ ur->commit_action();
}
void CurveEditor::remove_point(int index) {
ERR_FAIL_COND(_curve_ref.is_null());
- UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo();
- ur.create_action(TTR("Remove Curve Point"));
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
+ ur->create_action(TTR("Remove Curve Point"));
Curve::Point p = _curve_ref->get_point(index);
- ur.add_do_method(*_curve_ref, "remove_point", index);
- ur.add_undo_method(*_curve_ref, "add_point", p.position, p.left_tangent, p.right_tangent, p.left_mode, p.right_mode);
+ ur->add_do_method(*_curve_ref, "remove_point", index);
+ ur->add_undo_method(*_curve_ref, "add_point", p.position, p.left_tangent, p.right_tangent, p.left_mode, p.right_mode);
if (index == _selected_point) {
set_selected_point(-1);
@@ -474,14 +474,14 @@ void CurveEditor::remove_point(int index) {
set_hover_point_index(-1);
}
- ur.commit_action();
+ ur->commit_action();
}
void CurveEditor::toggle_linear(TangentIndex tangent) {
ERR_FAIL_COND(_curve_ref.is_null());
- UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo();
- ur.create_action(TTR("Toggle Curve Linear Tangent"));
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
+ ur->create_action(TTR("Toggle Curve Linear Tangent"));
if (tangent == TANGENT_NONE) {
tangent = _selected_tangent;
@@ -493,8 +493,8 @@ void CurveEditor::toggle_linear(TangentIndex tangent) {
Curve::TangentMode prev_mode = _curve_ref->get_point_left_mode(_selected_point);
Curve::TangentMode mode = is_linear ? Curve::TANGENT_FREE : Curve::TANGENT_LINEAR;
- ur.add_do_method(*_curve_ref, "set_point_left_mode", _selected_point, mode);
- ur.add_undo_method(*_curve_ref, "set_point_left_mode", _selected_point, prev_mode);
+ ur->add_do_method(*_curve_ref, "set_point_left_mode", _selected_point, mode);
+ ur->add_undo_method(*_curve_ref, "set_point_left_mode", _selected_point, prev_mode);
} else {
bool is_linear = _curve_ref->get_point_right_mode(_selected_point) == Curve::TANGENT_LINEAR;
@@ -502,11 +502,11 @@ void CurveEditor::toggle_linear(TangentIndex tangent) {
Curve::TangentMode prev_mode = _curve_ref->get_point_right_mode(_selected_point);
Curve::TangentMode mode = is_linear ? Curve::TANGENT_FREE : Curve::TANGENT_LINEAR;
- ur.add_do_method(*_curve_ref, "set_point_right_mode", _selected_point, mode);
- ur.add_undo_method(*_curve_ref, "set_point_right_mode", _selected_point, prev_mode);
+ ur->add_do_method(*_curve_ref, "set_point_right_mode", _selected_point, mode);
+ ur->add_undo_method(*_curve_ref, "set_point_right_mode", _selected_point, prev_mode);
}
- ur.commit_action();
+ ur->commit_action();
}
void CurveEditor::set_selected_point(int index) {
diff --git a/editor/plugins/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp
index c572b5b7fe..40e7dfead2 100644
--- a/editor/plugins/debugger_editor_plugin.cpp
+++ b/editor/plugins/debugger_editor_plugin.cpp
@@ -40,7 +40,7 @@
#include "editor/plugins/script_editor_plugin.h"
#include "scene/gui/menu_button.h"
-DebuggerEditorPlugin::DebuggerEditorPlugin(MenuButton *p_debug_menu) {
+DebuggerEditorPlugin::DebuggerEditorPlugin(PopupMenu *p_debug_menu) {
EditorDebuggerServer::initialize();
ED_SHORTCUT("debugger/step_into", TTR("Step Into"), Key::F11);
@@ -61,30 +61,29 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(MenuButton *p_debug_menu) {
// Main editor debug menu.
debug_menu = p_debug_menu;
- PopupMenu *p = debug_menu->get_popup();
- p->set_hide_on_checkable_item_selection(false);
- p->add_check_shortcut(ED_SHORTCUT("editor/deploy_with_remote_debug", TTR("Deploy with Remote Debug")), RUN_DEPLOY_REMOTE_DEBUG);
- p->set_item_tooltip(-1,
+ debug_menu->set_hide_on_checkable_item_selection(false);
+ debug_menu->add_check_shortcut(ED_SHORTCUT("editor/deploy_with_remote_debug", TTR("Deploy with Remote Debug")), RUN_DEPLOY_REMOTE_DEBUG);
+ debug_menu->set_item_tooltip(-1,
TTR("When this option is enabled, using one-click deploy will make the executable attempt to connect to this computer's IP so the running project can be debugged.\nThis option is intended to be used for remote debugging (typically with a mobile device).\nYou don't need to enable it to use the GDScript debugger locally."));
- p->add_check_shortcut(ED_SHORTCUT("editor/small_deploy_with_network_fs", TTR("Small Deploy with Network Filesystem")), RUN_FILE_SERVER);
- p->set_item_tooltip(-1,
+ debug_menu->add_check_shortcut(ED_SHORTCUT("editor/small_deploy_with_network_fs", TTR("Small Deploy with Network Filesystem")), RUN_FILE_SERVER);
+ debug_menu->set_item_tooltip(-1,
TTR("When this option is enabled, using one-click deploy for Android will only export an executable without the project data.\nThe filesystem will be provided from the project by the editor over the network.\nOn Android, deploying will use the USB cable for faster performance. This option speeds up testing for projects with large assets."));
- p->add_separator();
- p->add_check_shortcut(ED_SHORTCUT("editor/visible_collision_shapes", TTR("Visible Collision Shapes")), RUN_DEBUG_COLLISONS);
- p->set_item_tooltip(-1,
+ debug_menu->add_separator();
+ debug_menu->add_check_shortcut(ED_SHORTCUT("editor/visible_collision_shapes", TTR("Visible Collision Shapes")), RUN_DEBUG_COLLISONS);
+ debug_menu->set_item_tooltip(-1,
TTR("When this option is enabled, collision shapes and raycast nodes (for 2D and 3D) will be visible in the running project."));
- p->add_check_shortcut(ED_SHORTCUT("editor/visible_paths", TTR("Visible Paths")), RUN_DEBUG_PATHS);
- p->set_item_tooltip(-1,
+ debug_menu->add_check_shortcut(ED_SHORTCUT("editor/visible_paths", TTR("Visible Paths")), RUN_DEBUG_PATHS);
+ debug_menu->set_item_tooltip(-1,
TTR("When this option is enabled, curve resources used by path nodes will be visible in the running project."));
- p->add_check_shortcut(ED_SHORTCUT("editor/visible_navigation", TTR("Visible Navigation")), RUN_DEBUG_NAVIGATION);
- p->set_item_tooltip(-1,
+ debug_menu->add_check_shortcut(ED_SHORTCUT("editor/visible_navigation", TTR("Visible Navigation")), RUN_DEBUG_NAVIGATION);
+ debug_menu->set_item_tooltip(-1,
TTR("When this option is enabled, navigation meshes and polygons will be visible in the running project."));
- p->add_separator();
- p->add_check_shortcut(ED_SHORTCUT("editor/sync_scene_changes", TTR("Synchronize Scene Changes")), RUN_LIVE_DEBUG);
- p->set_item_tooltip(-1,
+ debug_menu->add_separator();
+ debug_menu->add_check_shortcut(ED_SHORTCUT("editor/sync_scene_changes", TTR("Synchronize Scene Changes")), RUN_LIVE_DEBUG);
+ debug_menu->set_item_tooltip(-1,
TTR("When this option is enabled, any changes made to the scene in the editor will be replicated in the running project.\nWhen used remotely on a device, this is more efficient when the network filesystem option is enabled."));
- p->add_check_shortcut(ED_SHORTCUT("editor/sync_script_changes", TTR("Synchronize Script Changes")), RUN_RELOAD_SCRIPTS);
- p->set_item_tooltip(-1,
+ debug_menu->add_check_shortcut(ED_SHORTCUT("editor/sync_script_changes", TTR("Synchronize Script Changes")), RUN_RELOAD_SCRIPTS);
+ debug_menu->set_item_tooltip(-1,
TTR("When this option is enabled, any script that is saved will be reloaded in the running project.\nWhen used remotely on a device, this is more efficient when the network filesystem option is enabled."));
// Multi-instance, start/stop
@@ -92,9 +91,9 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(MenuButton *p_debug_menu) {
instances_menu->set_name("run_instances");
instances_menu->set_hide_on_checkable_item_selection(false);
- p->add_child(instances_menu);
- p->add_separator();
- p->add_submenu_item(TTR("Run Multiple Instances"), "run_instances");
+ debug_menu->add_child(instances_menu);
+ debug_menu->add_separator();
+ debug_menu->add_submenu_item(TTR("Run Multiple Instances"), "run_instances");
instances_menu->add_radio_check_item(TTR("Run 1 Instance"));
instances_menu->set_item_metadata(0, 1);
@@ -106,7 +105,7 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(MenuButton *p_debug_menu) {
instances_menu->set_item_metadata(3, 4);
instances_menu->set_item_checked(0, true);
instances_menu->connect("index_pressed", callable_mp(this, &DebuggerEditorPlugin::_select_run_count));
- p->connect("id_pressed", callable_mp(this, &DebuggerEditorPlugin::_menu_option));
+ debug_menu->connect("id_pressed", callable_mp(this, &DebuggerEditorPlugin::_menu_option));
}
DebuggerEditorPlugin::~DebuggerEditorPlugin() {
@@ -125,7 +124,7 @@ void DebuggerEditorPlugin::_select_run_count(int p_index) {
void DebuggerEditorPlugin::_menu_option(int p_option) {
switch (p_option) {
case RUN_FILE_SERVER: {
- bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_FILE_SERVER));
+ bool ischecked = debug_menu->is_item_checked(debug_menu->get_item_index(RUN_FILE_SERVER));
if (ischecked) {
file_server->stop();
@@ -133,45 +132,45 @@ void DebuggerEditorPlugin::_menu_option(int p_option) {
file_server->start();
}
- debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_FILE_SERVER), !ischecked);
+ debug_menu->set_item_checked(debug_menu->get_item_index(RUN_FILE_SERVER), !ischecked);
EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_file_server", !ischecked);
} break;
case RUN_LIVE_DEBUG: {
- bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_LIVE_DEBUG));
+ bool ischecked = debug_menu->is_item_checked(debug_menu->get_item_index(RUN_LIVE_DEBUG));
- debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_LIVE_DEBUG), !ischecked);
+ debug_menu->set_item_checked(debug_menu->get_item_index(RUN_LIVE_DEBUG), !ischecked);
EditorDebuggerNode::get_singleton()->set_live_debugging(!ischecked);
EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_live_debug", !ischecked);
} break;
case RUN_DEPLOY_REMOTE_DEBUG: {
- bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEPLOY_REMOTE_DEBUG));
- debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEPLOY_REMOTE_DEBUG), !ischecked);
+ bool ischecked = debug_menu->is_item_checked(debug_menu->get_item_index(RUN_DEPLOY_REMOTE_DEBUG));
+ debug_menu->set_item_checked(debug_menu->get_item_index(RUN_DEPLOY_REMOTE_DEBUG), !ischecked);
EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_deploy_remote_debug", !ischecked);
} break;
case RUN_DEBUG_COLLISONS: {
- bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_COLLISONS));
- debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_COLLISONS), !ischecked);
+ bool ischecked = debug_menu->is_item_checked(debug_menu->get_item_index(RUN_DEBUG_COLLISONS));
+ debug_menu->set_item_checked(debug_menu->get_item_index(RUN_DEBUG_COLLISONS), !ischecked);
EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_debug_collisons", !ischecked);
} break;
case RUN_DEBUG_PATHS: {
- bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_PATHS));
- debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_PATHS), !ischecked);
+ bool ischecked = debug_menu->is_item_checked(debug_menu->get_item_index(RUN_DEBUG_PATHS));
+ debug_menu->set_item_checked(debug_menu->get_item_index(RUN_DEBUG_PATHS), !ischecked);
EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_debug_paths", !ischecked);
} break;
case RUN_DEBUG_NAVIGATION: {
- bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_NAVIGATION));
- debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_NAVIGATION), !ischecked);
+ bool ischecked = debug_menu->is_item_checked(debug_menu->get_item_index(RUN_DEBUG_NAVIGATION));
+ debug_menu->set_item_checked(debug_menu->get_item_index(RUN_DEBUG_NAVIGATION), !ischecked);
EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_debug_navigation", !ischecked);
} break;
case RUN_RELOAD_SCRIPTS: {
- bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_RELOAD_SCRIPTS));
- debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_RELOAD_SCRIPTS), !ischecked);
+ bool ischecked = debug_menu->is_item_checked(debug_menu->get_item_index(RUN_RELOAD_SCRIPTS));
+ debug_menu->set_item_checked(debug_menu->get_item_index(RUN_RELOAD_SCRIPTS), !ischecked);
ScriptEditor::get_singleton()->set_live_auto_reload_running_scripts(!ischecked);
EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_reload_scripts", !ischecked);
diff --git a/editor/plugins/debugger_editor_plugin.h b/editor/plugins/debugger_editor_plugin.h
index fb963385cd..d8871128c3 100644
--- a/editor/plugins/debugger_editor_plugin.h
+++ b/editor/plugins/debugger_editor_plugin.h
@@ -41,7 +41,7 @@ class DebuggerEditorPlugin : public EditorPlugin {
GDCLASS(DebuggerEditorPlugin, EditorPlugin);
private:
- MenuButton *debug_menu = nullptr;
+ PopupMenu *debug_menu = nullptr;
EditorFileServer *file_server = nullptr;
PopupMenu *instances_menu = nullptr;
@@ -64,7 +64,7 @@ public:
virtual String get_name() const override { return "Debugger"; }
bool has_main_screen() const override { return false; }
- DebuggerEditorPlugin(MenuButton *p_menu);
+ DebuggerEditorPlugin(PopupMenu *p_menu);
~DebuggerEditorPlugin();
};
diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp
index cadb974345..c7d3e92802 100644
--- a/editor/plugins/font_config_plugin.cpp
+++ b/editor/plugins/font_config_plugin.cpp
@@ -100,11 +100,6 @@ bool EditorPropertyFontOTObject::_get(const StringName &p_name, Variant &r_ret)
return false;
}
-void EditorPropertyFontOTObject::_bind_methods() {
- ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &EditorPropertyFontOTObject::property_can_revert);
- ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorPropertyFontOTObject::property_get_revert);
-}
-
void EditorPropertyFontOTObject::set_dict(const Dictionary &p_dict) {
dict = p_dict;
}
@@ -121,7 +116,7 @@ Dictionary EditorPropertyFontOTObject::get_defaults() {
return defaults_dict;
}
-bool EditorPropertyFontOTObject::property_can_revert(const String &p_name) {
+bool EditorPropertyFontOTObject::_property_can_revert(const StringName &p_name) const {
String name = p_name;
if (name.begins_with("keys")) {
@@ -136,18 +131,19 @@ bool EditorPropertyFontOTObject::property_can_revert(const String &p_name) {
return false;
}
-Variant EditorPropertyFontOTObject::property_get_revert(const String &p_name) {
+bool EditorPropertyFontOTObject::_property_get_revert(const StringName &p_name, Variant &r_property) const {
String name = p_name;
if (name.begins_with("keys")) {
int key = name.get_slicec('/', 1).to_int();
if (defaults_dict.has(key)) {
Vector3i range = defaults_dict[key];
- return range.z;
+ r_property = range.z;
+ return true;
}
}
- return Variant();
+ return false;
}
/*************************************************************************/
diff --git a/editor/plugins/font_config_plugin.h b/editor/plugins/font_config_plugin.h
index 3eaa2fdc17..41dde3cc59 100644
--- a/editor/plugins/font_config_plugin.h
+++ b/editor/plugins/font_config_plugin.h
@@ -66,7 +66,8 @@ class EditorPropertyFontOTObject : public RefCounted {
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
- static void _bind_methods();
+ bool _property_can_revert(const StringName &p_name) const;
+ bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
public:
void set_dict(const Dictionary &p_dict);
@@ -75,9 +76,6 @@ public:
void set_defaults(const Dictionary &p_dict);
Dictionary get_defaults();
- bool property_can_revert(const String &p_name);
- Variant property_get_revert(const String &p_name);
-
EditorPropertyFontOTObject(){};
};
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
index 8e6687c836..1487f8b7bc 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
@@ -34,6 +34,7 @@
#include "core/io/image_loader.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
+#include "editor/editor_undo_redo_manager.h"
#include "editor/scene_tree_dock.h"
#include "scene/2d/cpu_particles_2d.h"
#include "scene/gui/separator.h"
@@ -111,7 +112,7 @@ void GPUParticles2DEditorPlugin::_menu_callback(int p_idx) {
cpu_particles->set_process_mode(particles->get_process_mode());
cpu_particles->set_z_index(particles->get_z_index());
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Convert to CPUParticles2D"));
ur->add_do_method(SceneTreeDock::get_singleton(), "replace_node", particles, cpu_particles, true, false);
ur->add_do_reference(cpu_particles);
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.h b/editor/plugins/gpu_particles_2d_editor_plugin.h
index bf49a82166..0229b57c10 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.h
@@ -38,6 +38,7 @@
#include "scene/gui/spin_box.h"
class EditorFileDialog;
+class EditorUndoRedoManager;
class GPUParticles2DEditorPlugin : public EditorPlugin {
GDCLASS(GPUParticles2DEditorPlugin, EditorPlugin);
@@ -75,7 +76,7 @@ class GPUParticles2DEditorPlugin : public EditorPlugin {
String source_emission_file;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
void _file_selected(const String &p_file);
void _menu_callback(int p_idx);
void _generate_visibility_rect();
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index 6750f1aa9c..335efd6949 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -32,6 +32,7 @@
#include "core/io/resource_loader.h"
#include "editor/editor_node.h"
+#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/node_3d_editor_plugin.h"
#include "editor/scene_tree_dock.h"
#include "scene/3d/cpu_particles_3d.h"
@@ -271,7 +272,7 @@ void GPUParticles3DEditor::_menu_option(int p_option) {
cpu_particles->set_visible(node->is_visible());
cpu_particles->set_process_mode(node->get_process_mode());
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Convert to CPUParticles3D"));
ur->add_do_method(SceneTreeDock::get_singleton(), "replace_node", node, cpu_particles, true, false);
ur->add_do_reference(cpu_particles);
@@ -321,7 +322,7 @@ void GPUParticles3DEditor::_generate_aabb() {
node->set_emitting(false);
}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Generate Visibility AABB"));
ur->add_do_method(node, "set_visibility_aabb", rect);
ur->add_undo_method(node, "set_visibility_aabb", node->get_visibility_aabb());
diff --git a/editor/plugins/gradient_editor_plugin.cpp b/editor/plugins/gradient_editor_plugin.cpp
index 542aee879b..460178490e 100644
--- a/editor/plugins/gradient_editor_plugin.cpp
+++ b/editor/plugins/gradient_editor_plugin.cpp
@@ -34,6 +34,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "node_3d_editor_plugin.h"
Size2 GradientEditor::get_minimum_size() const {
@@ -55,7 +56,7 @@ void GradientEditor::_gradient_changed() {
void GradientEditor::_ramp_changed() {
editing = true;
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Gradient Edited"), UndoRedo::MERGE_ENDS);
undo_redo->add_do_method(gradient.ptr(), "set_offsets", get_offsets());
undo_redo->add_do_method(gradient.ptr(), "set_colors", get_colors());
diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.cpp b/editor/plugins/gradient_texture_2d_editor_plugin.cpp
index df45d6c290..6c463f71cf 100644
--- a/editor/plugins/gradient_texture_2d_editor_plugin.cpp
+++ b/editor/plugins/gradient_texture_2d_editor_plugin.cpp
@@ -32,6 +32,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/box_container.h"
#include "scene/gui/flow_container.h"
#include "scene/gui/separator.h"
@@ -175,7 +176,7 @@ void GradientTexture2DEditorRect::_notification(int p_what) {
}
GradientTexture2DEditorRect::GradientTexture2DEditorRect() {
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ undo_redo = EditorNode::get_undo_redo();
checkerboard = memnew(TextureRect);
checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE);
@@ -222,7 +223,7 @@ void GradientTexture2DEditor::_notification(int p_what) {
}
GradientTexture2DEditor::GradientTexture2DEditor() {
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ undo_redo = EditorNode::get_undo_redo();
HFlowContainer *toolbar = memnew(HFlowContainer);
add_child(toolbar);
diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.h b/editor/plugins/gradient_texture_2d_editor_plugin.h
index 93c49b1e6f..9faf33152a 100644
--- a/editor/plugins/gradient_texture_2d_editor_plugin.h
+++ b/editor/plugins/gradient_texture_2d_editor_plugin.h
@@ -34,6 +34,8 @@
#include "editor/editor_plugin.h"
#include "editor/editor_spin_slider.h"
+class EditorUndoRedoManager;
+
class GradientTexture2DEditorRect : public Control {
GDCLASS(GradientTexture2DEditorRect, Control);
@@ -44,7 +46,7 @@ class GradientTexture2DEditorRect : public Control {
};
Ref<GradientTexture2D> texture;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
bool snap_enabled = false;
float snap_size = 0;
@@ -74,7 +76,7 @@ class GradientTexture2DEditor : public VBoxContainer {
GDCLASS(GradientTexture2DEditor, VBoxContainer);
Ref<GradientTexture2D> texture;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
Button *reverse_button = nullptr;
Button *snap_button = nullptr;
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index 1b4d98fc3f..5d59f62f05 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -33,6 +33,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/subviewport_container.h"
#include "scene/resources/fog_material.h"
#include "scene/resources/particles_material.h"
@@ -261,10 +262,8 @@ void EditorInspectorPluginMaterial::parse_begin(Object *p_object) {
}
void EditorInspectorPluginMaterial::_undo_redo_inspector_callback(Object *p_undo_redo, Object *p_edited, String p_property, Variant p_new_value) {
- UndoRedo *undo_redo = Object::cast_to<UndoRedo>(p_undo_redo);
- if (!undo_redo) {
- return;
- }
+ Ref<EditorUndoRedoManager> undo_redo = Object::cast_to<EditorUndoRedoManager>(p_undo_redo);
+ ERR_FAIL_COND(!undo_redo.is_valid());
// For BaseMaterial3D, if a roughness or metallic textures is being assigned to an empty slot,
// set the respective metallic or roughness factor to 1.0 as a convenience feature
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index 5fb885ad1f..7bd406b869 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -32,6 +32,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_undo_redo_manager.h"
#include "node_3d_editor_plugin.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/navigation_region_3d.h"
@@ -60,7 +61,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
switch (p_option) {
case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: {
EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_singleton()->get_undo_redo();
List<Node *> selection = editor_selection->get_selected_node_list();
@@ -147,7 +148,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
Node *owner = get_tree()->get_edited_scene_root();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Create Trimesh Static Shape"));
@@ -177,7 +178,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
err_dialog->popup_centered();
return;
}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_singleton()->get_undo_redo();
if (simplify) {
ur->create_action(TTR("Create Simplified Convex Shape"));
@@ -217,7 +218,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
err_dialog->popup_centered();
return;
}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Create Multiple Convex Shapes"));
@@ -254,7 +255,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
Node *owner = get_tree()->get_edited_scene_root();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Create Navigation Mesh"));
ur->add_do_method(node, "add_child", nmi, true);
@@ -311,7 +312,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
return;
}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Unwrap UV2"));
ur->add_do_method(node, "set_mesh", unwrapped_mesh);
@@ -470,7 +471,7 @@ void MeshInstance3DEditor::_create_outline_mesh() {
mi->set_mesh(mesho);
Node *owner = get_tree()->get_edited_scene_root();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Create Outline"));
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index e8f143a637..043848080f 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -35,6 +35,7 @@
#include "core/math/geometry_3d.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/node_3d_editor_plugin.h"
#include "scene/3d/audio_listener_3d.h"
#include "scene/3d/audio_stream_player_3d.h"
@@ -51,10 +52,10 @@
#include "scene/3d/light_3d.h"
#include "scene/3d/lightmap_gi.h"
#include "scene/3d/lightmap_probe.h"
+#include "scene/3d/marker_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/navigation_region_3d.h"
#include "scene/3d/occluder_instance_3d.h"
-#include "scene/3d/position_3d.h"
#include "scene/3d/ray_cast_3d.h"
#include "scene/3d/reflection_probe.h"
#include "scene/3d/shape_cast_3d.h"
@@ -1347,13 +1348,13 @@ void Light3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_i
light->set_param(p_id == 0 ? Light3D::PARAM_RANGE : Light3D::PARAM_SPOT_ANGLE, p_restore);
} else if (p_id == 0) {
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Light Radius"));
ur->add_do_method(light, "set_param", Light3D::PARAM_RANGE, light->get_param(Light3D::PARAM_RANGE));
ur->add_undo_method(light, "set_param", Light3D::PARAM_RANGE, p_restore);
ur->commit_action();
} else if (p_id == 1) {
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Light Radius"));
ur->add_do_method(light, "set_param", Light3D::PARAM_SPOT_ANGLE, light->get_param(Light3D::PARAM_SPOT_ANGLE));
ur->add_undo_method(light, "set_param", Light3D::PARAM_SPOT_ANGLE, p_restore);
@@ -1571,7 +1572,7 @@ void AudioStreamPlayer3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gi
player->set_emission_angle(p_restore);
} else {
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change AudioStreamPlayer3D Emission Angle"));
ur->add_do_method(player, "set_emission_angle", player->get_emission_angle());
ur->add_undo_method(player, "set_emission_angle", p_restore);
@@ -1814,7 +1815,7 @@ void Camera3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_
if (p_cancel) {
camera->set("fov", p_restore);
} else {
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Camera FOV"));
ur->add_do_property(camera, "fov", camera->get_fov());
ur->add_undo_property(camera, "fov", p_restore);
@@ -1825,7 +1826,7 @@ void Camera3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_
if (p_cancel) {
camera->set("size", p_restore);
} else {
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Camera Size"));
ur->add_do_property(camera, "size", camera->get_size());
ur->add_undo_property(camera, "size", p_restore);
@@ -2141,7 +2142,7 @@ void OccluderInstance3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_giz
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Sphere Shape Radius"));
ur->add_do_method(so.ptr(), "set_radius", so->get_radius());
ur->add_undo_method(so.ptr(), "set_radius", p_restore);
@@ -2155,7 +2156,7 @@ void OccluderInstance3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_giz
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Box Shape Size"));
ur->add_do_method(bo.ptr(), "set_size", bo->get_size());
ur->add_undo_method(bo.ptr(), "set_size", p_restore);
@@ -2169,7 +2170,7 @@ void OccluderInstance3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_giz
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Box Shape Size"));
ur->add_do_method(qo.ptr(), "set_size", qo->get_size());
ur->add_undo_method(qo.ptr(), "set_size", p_restore);
@@ -2291,7 +2292,7 @@ void Label3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
///
-Position3DGizmoPlugin::Position3DGizmoPlugin() {
+Marker3DGizmoPlugin::Marker3DGizmoPlugin() {
pos3d_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
cursor_points = Vector<Vector3>();
@@ -2315,7 +2316,7 @@ Position3DGizmoPlugin::Position3DGizmoPlugin() {
// Use the axis color which is brighter for the positive axis.
// Use a darkened axis color for the negative axis.
- // This makes it possible to see in which direction the Position3D node is rotated
+ // This makes it possible to see in which direction the Marker3D node is rotated
// (which can be important depending on how it's used).
const Color color_x = EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("axis_x_color"), SNAME("Editor"));
cursor_colors.push_back(color_x);
@@ -2351,19 +2352,19 @@ Position3DGizmoPlugin::Position3DGizmoPlugin() {
pos3d_mesh->surface_set_material(0, mat);
}
-bool Position3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
- return Object::cast_to<Position3D>(p_spatial) != nullptr;
+bool Marker3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
+ return Object::cast_to<Marker3D>(p_spatial) != nullptr;
}
-String Position3DGizmoPlugin::get_gizmo_name() const {
- return "Position3D";
+String Marker3DGizmoPlugin::get_gizmo_name() const {
+ return "Marker3D";
}
-int Position3DGizmoPlugin::get_priority() const {
+int Marker3DGizmoPlugin::get_priority() const {
return -1;
}
-void Position3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
+void Marker3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
p_gizmo->clear();
p_gizmo->add_mesh(pos3d_mesh);
p_gizmo->add_collision_segments(cursor_points);
@@ -2870,7 +2871,7 @@ void VisibleOnScreenNotifier3DGizmoPlugin::commit_handle(const EditorNode3DGizmo
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Notifier AABB"));
ur->add_do_method(notifier, "set_aabb", notifier->get_aabb());
ur->add_undo_method(notifier, "set_aabb", p_restore);
@@ -3061,7 +3062,7 @@ void GPUParticles3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo,
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Particles AABB"));
ur->add_do_method(particles, "set_visibility_aabb", particles->get_visibility_aabb());
ur->add_undo_method(particles, "set_visibility_aabb", p_restore);
@@ -3227,7 +3228,7 @@ void GPUParticlesCollision3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Radius"));
ur->add_do_method(sn, "set_radius", sn->call("get_radius"));
ur->add_undo_method(sn, "set_radius", p_restore);
@@ -3240,7 +3241,7 @@ void GPUParticlesCollision3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Box Shape Extents"));
ur->add_do_method(sn, "set_extents", sn->call("get_extents"));
ur->add_undo_method(sn, "set_extents", p_restore);
@@ -3499,7 +3500,7 @@ void ReflectionProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo,
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Probe Extents"));
ur->add_do_method(probe, "set_extents", probe->get_extents());
ur->add_do_method(probe, "set_origin_offset", probe->get_origin_offset());
@@ -3651,7 +3652,7 @@ void DecalGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id,
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Decal Extents"));
ur->add_do_method(decal, "set_extents", decal->get_extents());
ur->add_undo_method(decal, "set_extents", restore);
@@ -3791,7 +3792,7 @@ void VoxelGIGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_i
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Probe Extents"));
ur->add_do_method(probe, "set_extents", probe->get_extents());
ur->add_undo_method(probe, "set_extents", restore);
@@ -4406,7 +4407,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Sphere Shape Radius"));
ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius());
ur->add_undo_method(ss.ptr(), "set_radius", p_restore);
@@ -4420,7 +4421,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Box Shape Size"));
ur->add_do_method(ss.ptr(), "set_size", ss->get_size());
ur->add_undo_method(ss.ptr(), "set_size", p_restore);
@@ -4437,7 +4438,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
if (p_id == 0) {
ur->create_action(TTR("Change Capsule Shape Radius"));
ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius());
@@ -4462,7 +4463,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
if (p_id == 0) {
ur->create_action(TTR("Change Cylinder Shape Radius"));
ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius());
@@ -4487,7 +4488,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Separation Ray Shape Length"));
ur->add_do_method(ss.ptr(), "set_length", ss->get_length());
ur->add_undo_method(ss.ptr(), "set_length", p_restore);
@@ -5745,7 +5746,7 @@ void FogVolumeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Change Fog Volume Extents"));
ur->add_do_method(sn, "set_extents", sn->call("get_extents"));
ur->add_undo_method(sn, "set_extents", p_restore);
diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h
index 739bf1b929..7dac1bd360 100644
--- a/editor/plugins/node_3d_editor_gizmos.h
+++ b/editor/plugins/node_3d_editor_gizmos.h
@@ -334,8 +334,8 @@ public:
Label3DGizmoPlugin();
};
-class Position3DGizmoPlugin : public EditorNode3DGizmoPlugin {
- GDCLASS(Position3DGizmoPlugin, EditorNode3DGizmoPlugin);
+class Marker3DGizmoPlugin : public EditorNode3DGizmoPlugin {
+ GDCLASS(Marker3DGizmoPlugin, EditorNode3DGizmoPlugin);
Ref<ArrayMesh> pos3d_mesh;
Vector<Vector3> cursor_points;
@@ -346,7 +346,7 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- Position3DGizmoPlugin();
+ Marker3DGizmoPlugin();
};
class PhysicalBone3DGizmoPlugin : public EditorNode3DGizmoPlugin {
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 6afc6798d0..6add9e2e1e 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -46,6 +46,7 @@
#include "editor/scene_tree_dock.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/collision_shape_3d.h"
+#include "scene/3d/decal.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/physics_body_3d.h"
@@ -2972,6 +2973,13 @@ void Node3DEditorViewport::_menu_option(int p_option) {
xform.scale_basis(sp->get_scale());
}
+ if (Object::cast_to<Decal>(E)) {
+ // Adjust rotation to match Decal's default orientation.
+ // This makes the decal "look" in the same direction as the camera,
+ // rather than pointing down relative to the camera orientation.
+ xform.basis.rotate_local(Vector3(1, 0, 0), Math_TAU * 0.25);
+ }
+
undo_redo->add_do_method(sp, "set_global_transform", xform);
undo_redo->add_undo_method(sp, "set_global_transform", sp->get_global_gizmo_transform());
}
@@ -2999,7 +3007,16 @@ void Node3DEditorViewport::_menu_option(int p_option) {
continue;
}
- undo_redo->add_do_method(sp, "set_rotation", camera_transform.basis.get_euler_normalized());
+ Basis basis = camera_transform.basis;
+
+ if (Object::cast_to<Decal>(E)) {
+ // Adjust rotation to match Decal's default orientation.
+ // This makes the decal "look" in the same direction as the camera,
+ // rather than pointing down relative to the camera orientation.
+ basis.rotate_local(Vector3(1, 0, 0), Math_TAU * 0.25);
+ }
+
+ undo_redo->add_do_method(sp, "set_rotation", basis.get_euler_normalized());
undo_redo->add_undo_method(sp, "set_rotation", sp->get_rotation());
}
undo_redo->commit_action();
@@ -4003,15 +4020,15 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po
instantiated_scene->set_scene_file_path(ProjectSettings::get_singleton()->localize_path(path));
}
- editor_data->get_undo_redo().add_do_method(parent, "add_child", instantiated_scene, true);
- editor_data->get_undo_redo().add_do_method(instantiated_scene, "set_owner", EditorNode::get_singleton()->get_edited_scene());
- editor_data->get_undo_redo().add_do_reference(instantiated_scene);
- editor_data->get_undo_redo().add_undo_method(parent, "remove_child", instantiated_scene);
+ editor_data->get_undo_redo()->add_do_method(parent, "add_child", instantiated_scene, true);
+ editor_data->get_undo_redo()->add_do_method(instantiated_scene, "set_owner", EditorNode::get_singleton()->get_edited_scene());
+ editor_data->get_undo_redo()->add_do_reference(instantiated_scene);
+ editor_data->get_undo_redo()->add_undo_method(parent, "remove_child", instantiated_scene);
String new_name = parent->validate_child_name(instantiated_scene);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
- editor_data->get_undo_redo().add_do_method(ed, "live_debug_instance_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent), path, new_name);
- editor_data->get_undo_redo().add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
+ editor_data->get_undo_redo()->add_do_method(ed, "live_debug_instance_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent), path, new_name);
+ editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
Node3D *node3d = Object::cast_to<Node3D>(instantiated_scene);
if (node3d) {
@@ -4024,7 +4041,7 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po
global_transform.origin = spatial_editor->snap_point(_get_instance_position(p_point));
global_transform.basis *= node3d->get_transform().basis;
- editor_data->get_undo_redo().add_do_method(instantiated_scene, "set_global_transform", global_transform);
+ editor_data->get_undo_redo()->add_do_method(instantiated_scene, "set_global_transform", global_transform);
}
return true;
@@ -4035,15 +4052,15 @@ void Node3DEditorViewport::_perform_drop_data() {
GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(ObjectDB::get_instance(spatial_editor->get_preview_material_target()));
MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(ObjectDB::get_instance(spatial_editor->get_preview_material_target()));
if (mesh_instance && spatial_editor->get_preview_material_surface() != -1) {
- editor_data->get_undo_redo().create_action(vformat(TTR("Set Surface %d Override Material"), spatial_editor->get_preview_material_surface()));
- editor_data->get_undo_redo().add_do_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_material());
- editor_data->get_undo_redo().add_undo_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material());
- editor_data->get_undo_redo().commit_action();
+ editor_data->get_undo_redo()->create_action(vformat(TTR("Set Surface %d Override Material"), spatial_editor->get_preview_material_surface()));
+ editor_data->get_undo_redo()->add_do_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_material());
+ editor_data->get_undo_redo()->add_undo_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material());
+ editor_data->get_undo_redo()->commit_action();
} else if (geometry_instance) {
- editor_data->get_undo_redo().create_action(TTR("Set Material Override"));
- editor_data->get_undo_redo().add_do_method(geometry_instance, "set_material_override", spatial_editor->get_preview_material());
- editor_data->get_undo_redo().add_undo_method(geometry_instance, "set_material_override", spatial_editor->get_preview_reset_material());
- editor_data->get_undo_redo().commit_action();
+ editor_data->get_undo_redo()->create_action(TTR("Set Material Override"));
+ editor_data->get_undo_redo()->add_do_method(geometry_instance, "set_material_override", spatial_editor->get_preview_material());
+ editor_data->get_undo_redo()->add_undo_method(geometry_instance, "set_material_override", spatial_editor->get_preview_reset_material());
+ editor_data->get_undo_redo()->commit_action();
}
_remove_preview_material();
@@ -4054,7 +4071,7 @@ void Node3DEditorViewport::_perform_drop_data() {
Vector<String> error_files;
- editor_data->get_undo_redo().create_action(TTR("Create Node"));
+ editor_data->get_undo_redo()->create_action(TTR("Create Node"));
for (int i = 0; i < selected_files.size(); i++) {
String path = selected_files[i];
@@ -4072,7 +4089,7 @@ void Node3DEditorViewport::_perform_drop_data() {
}
}
- editor_data->get_undo_redo().commit_action();
+ editor_data->get_undo_redo()->commit_action();
if (error_files.size() > 0) {
String files_str;
@@ -4113,6 +4130,7 @@ bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant
continue;
}
Ref<PackedScene> scn = res;
+ Ref<Mesh> mesh = res;
Ref<Material> mat = res;
Ref<Texture2D> tex = res;
if (scn.is_valid()) {
@@ -4131,6 +4149,8 @@ bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant
spatial_editor->set_preview_material(mat);
break;
+ } else if (mesh.is_valid()) {
+ // Let the mesh pass.
} else if (tex.is_valid()) {
Ref<StandardMaterial3D> new_mat = memnew(StandardMaterial3D);
new_mat->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, tex);
@@ -7247,6 +7267,14 @@ Vector<int> Node3DEditor::get_subgizmo_selection() {
return ret;
}
+void Node3DEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) {
+ undo_redo = p_undo_redo;
+}
+
+Ref<EditorUndoRedoManager> Node3DEditor::get_undo_redo() {
+ return undo_redo;
+}
+
void Node3DEditor::add_control_to_menu_panel(Control *p_control) {
context_menu_hbox->add_child(p_control);
}
@@ -7487,7 +7515,7 @@ void Node3DEditor::_register_all_gizmos() {
add_gizmo_plugin(Ref<SoftDynamicBody3DGizmoPlugin>(memnew(SoftDynamicBody3DGizmoPlugin)));
add_gizmo_plugin(Ref<Sprite3DGizmoPlugin>(memnew(Sprite3DGizmoPlugin)));
add_gizmo_plugin(Ref<Label3DGizmoPlugin>(memnew(Label3DGizmoPlugin)));
- add_gizmo_plugin(Ref<Position3DGizmoPlugin>(memnew(Position3DGizmoPlugin)));
+ add_gizmo_plugin(Ref<Marker3DGizmoPlugin>(memnew(Marker3DGizmoPlugin)));
add_gizmo_plugin(Ref<RayCast3DGizmoPlugin>(memnew(RayCast3DGizmoPlugin)));
add_gizmo_plugin(Ref<ShapeCast3DGizmoPlugin>(memnew(ShapeCast3DGizmoPlugin)));
add_gizmo_plugin(Ref<SpringArm3DGizmoPlugin>(memnew(SpringArm3DGizmoPlugin)));
@@ -7607,7 +7635,7 @@ void Node3DEditor::_load_default_preview_settings() {
environ_tonemap_button->set_pressed(true);
environ_ao_button->set_pressed(false);
environ_gi_button->set_pressed(false);
- sun_max_distance->set_value(250);
+ sun_max_distance->set_value(100);
sun_color->set_pick_color(Color(1, 1, 1));
sun_energy->set_value(1.0);
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 4469271a38..e0298ebd5f 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -53,6 +53,7 @@ class Node3DEditorViewport;
class SubViewportContainer;
class DirectionalLight3D;
class WorldEnvironment;
+class EditorUndoRedoManager;
class ViewportRotationControl : public Control {
GDCLASS(ViewportRotationControl, Control);
@@ -201,7 +202,7 @@ private:
EditorData *editor_data = nullptr;
EditorSelection *editor_selection = nullptr;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
CheckBox *preview_camera = nullptr;
SubViewportContainer *subviewport_container = nullptr;
@@ -682,7 +683,7 @@ private:
HBoxContainer *context_menu_hbox = nullptr;
void _generate_selection_boxes();
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
int camera_override_viewport_id;
@@ -820,13 +821,13 @@ public:
void select_gizmo_highlight_axis(int p_axis);
void set_custom_camera(Node *p_camera) { custom_camera = p_camera; }
- void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; }
Dictionary get_state() const;
void set_state(const Dictionary &p_state);
Ref<Environment> get_viewport_environment() { return viewport_environment; }
- UndoRedo *get_undo_redo() { return undo_redo; }
+ void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo);
+ Ref<EditorUndoRedoManager> get_undo_redo();
void add_control_to_menu_panel(Control *p_control);
void remove_control_from_menu_panel(Control *p_control);
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index fd331c4127..1d8a3f5c81 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -36,6 +36,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
void Path2DEditor::_notification(int p_what) {
switch (p_what) {
diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h
index 720f5c090f..13eca79010 100644
--- a/editor/plugins/path_2d_editor_plugin.h
+++ b/editor/plugins/path_2d_editor_plugin.h
@@ -36,11 +36,12 @@
#include "scene/gui/separator.h"
class CanvasItemEditor;
+class EditorUndoRedoManager;
class Path2DEditor : public HBoxContainer {
GDCLASS(Path2DEditor, HBoxContainer);
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
CanvasItemEditor *canvas_item_editor = nullptr;
Panel *panel = nullptr;
diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp
index 65b15a6001..084c0c2bb0 100644
--- a/editor/plugins/path_3d_editor_plugin.cpp
+++ b/editor/plugins/path_3d_editor_plugin.cpp
@@ -35,6 +35,7 @@
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "node_3d_editor_plugin.h"
#include "scene/resources/curve.h"
@@ -172,7 +173,7 @@ void Path3DGizmo::commit_handle(int p_id, bool p_secondary, const Variant &p_res
return;
}
- UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
if (!p_secondary) {
if (p_cancel) {
@@ -385,7 +386,7 @@ EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_spatial_gui_input(Camera
}
}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
if (closest_seg != -1) {
//subdivide
@@ -427,21 +428,21 @@ EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_spatial_gui_input(Camera
// Find the offset and point index of the place to break up.
// Also check for the control points.
if (dist_to_p < click_dist) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Remove Path Point"));
ur->add_do_method(c.ptr(), "remove_point", i);
ur->add_undo_method(c.ptr(), "add_point", c->get_point_position(i), c->get_point_in(i), c->get_point_out(i), i);
ur->commit_action();
return EditorPlugin::AFTER_GUI_INPUT_STOP;
} else if (dist_to_p_out < click_dist) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Remove Out-Control Point"));
ur->add_do_method(c.ptr(), "set_point_out", i, Vector3());
ur->add_undo_method(c.ptr(), "set_point_out", i, c->get_point_out(i));
ur->commit_action();
return EditorPlugin::AFTER_GUI_INPUT_STOP;
} else if (dist_to_p_in < click_dist) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Remove In-Control Point"));
ur->add_do_method(c.ptr(), "set_point_in", i, Vector3());
ur->add_undo_method(c.ptr(), "set_point_in", i, c->get_point_in(i));
@@ -520,7 +521,7 @@ void Path3DEditorPlugin::_close_curve() {
if (c->get_point_position(0) == c->get_point_position(c->get_point_count() - 1)) {
return;
}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Close Curve"));
ur->add_do_method(c.ptr(), "add_point", c->get_point_position(0), c->get_point_in(0), c->get_point_out(0), -1);
ur->add_undo_method(c.ptr(), "remove_point", c->get_point_count());
diff --git a/editor/plugins/polygon_3d_editor_plugin.cpp b/editor/plugins/polygon_3d_editor_plugin.cpp
index 83092f990f..2b3a5c3e23 100644
--- a/editor/plugins/polygon_3d_editor_plugin.cpp
+++ b/editor/plugins/polygon_3d_editor_plugin.cpp
@@ -38,6 +38,7 @@
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "node_3d_editor_plugin.h"
#include "scene/3d/camera_3d.h"
diff --git a/editor/plugins/polygon_3d_editor_plugin.h b/editor/plugins/polygon_3d_editor_plugin.h
index e1e1261250..0eb02a39e2 100644
--- a/editor/plugins/polygon_3d_editor_plugin.h
+++ b/editor/plugins/polygon_3d_editor_plugin.h
@@ -37,11 +37,12 @@
#include "scene/resources/immediate_mesh.h"
class CanvasItemEditor;
+class EditorUndoRedoManager;
class Polygon3DEditor : public HBoxContainer {
GDCLASS(Polygon3DEditor, HBoxContainer);
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
enum Mode {
MODE_CREATE,
MODE_EDIT,
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index 4e528ef066..201a3af539 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -234,6 +234,10 @@ void ResourcePreloaderEditor::_cell_button_pressed(Object *p_item, int p_column,
}
}
+void ResourcePreloaderEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) {
+ undo_redo = p_undo_redo;
+}
+
void ResourcePreloaderEditor::edit(ResourcePreloader *p_preloader) {
preloader = p_preloader;
@@ -387,7 +391,7 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() {
}
void ResourcePreloaderEditorPlugin::edit(Object *p_object) {
- preloader_editor->set_undo_redo(&get_undo_redo());
+ preloader_editor->set_undo_redo(EditorNode::get_undo_redo());
ResourcePreloader *s = Object::cast_to<ResourcePreloader>(p_object);
if (!s) {
return;
diff --git a/editor/plugins/resource_preloader_editor_plugin.h b/editor/plugins/resource_preloader_editor_plugin.h
index 96cef3de21..ef80283dae 100644
--- a/editor/plugins/resource_preloader_editor_plugin.h
+++ b/editor/plugins/resource_preloader_editor_plugin.h
@@ -37,6 +37,7 @@
#include "scene/main/resource_preloader.h"
class EditorFileDialog;
+class EditorUndoRedoManager;
class ResourcePreloaderEditor : public PanelContainer {
GDCLASS(ResourcePreloaderEditor, PanelContainer);
@@ -66,7 +67,7 @@ class ResourcePreloaderEditor : public PanelContainer {
void _cell_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button);
void _item_edited();
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
@@ -78,7 +79,7 @@ protected:
static void _bind_methods();
public:
- void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; }
+ void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo);
void edit(ResourcePreloader *p_preloader);
ResourcePreloaderEditor();
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index c53ac59c11..a0c9ddb14b 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -49,7 +49,6 @@
#include "editor/find_in_files.h"
#include "editor/node_dock.h"
#include "editor/plugins/shader_editor_plugin.h"
-#include "modules/visual_script/editor/visual_script_editor.h"
#include "scene/main/window.h"
#include "scene/scene_string_names.h"
#include "script_text_editor.h"
@@ -66,12 +65,12 @@ String EditorSyntaxHighlighter::_get_name() const {
return "Unnamed";
}
-Array EditorSyntaxHighlighter::_get_supported_languages() const {
- Array ret;
+PackedStringArray EditorSyntaxHighlighter::_get_supported_languages() const {
+ PackedStringArray ret;
if (GDVIRTUAL_CALL(_get_supported_languages, ret)) {
return ret;
}
- return Array();
+ return PackedStringArray();
}
Ref<EditorSyntaxHighlighter> EditorSyntaxHighlighter::_create() const {
@@ -1156,8 +1155,8 @@ Ref<Script> ScriptEditor::_get_current_script() {
}
}
-Array ScriptEditor::_get_open_scripts() const {
- Array ret;
+TypedArray<Script> ScriptEditor::_get_open_scripts() const {
+ TypedArray<Script> ret;
Vector<Ref<Script>> scripts = get_open_scripts();
int scrits_amount = scripts.size();
for (int idx_script = 0; idx_script < scrits_amount; idx_script++) {
@@ -1408,8 +1407,6 @@ void ScriptEditor::_menu_option(int p_option) {
es->set_editor(EditorNode::get_singleton());
es->_run();
-
- EditorNode::get_undo_redo()->clear_history();
} break;
case FILE_CLOSE: {
if (current->is_unsaved()) {
@@ -1734,7 +1731,7 @@ void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) {
continue;
}
- Array bpoints = se->get_breakpoints();
+ PackedInt32Array bpoints = se->get_breakpoints();
for (int j = 0; j < bpoints.size(); j++) {
p_breakpoints->push_back(base + ":" + itos((int)bpoints[j] + 1));
}
@@ -2382,8 +2379,8 @@ bool ScriptEditor::edit(const Ref<Resource> &p_resource, int p_line, int p_col,
se->add_syntax_highlighter(highlighter);
if (script != nullptr && !highlighter_set) {
- Array languages = highlighter->_get_supported_languages();
- if (languages.find(script->get_language()->get_name()) > -1) {
+ PackedStringArray languages = highlighter->_get_supported_languages();
+ if (languages.has(script->get_language()->get_name())) {
se->set_syntax_highlighter(highlighter);
highlighter_set = true;
}
@@ -3448,8 +3445,8 @@ Vector<Ref<Script>> ScriptEditor::get_open_scripts() const {
return out_scripts;
}
-Array ScriptEditor::_get_open_script_editors() const {
- Array script_editors;
+TypedArray<ScriptEditorBase> ScriptEditor::_get_open_script_editors() const {
+ TypedArray<ScriptEditorBase> script_editors;
for (int i = 0; i < tab_container->get_tab_count(); i++) {
ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_tab_control(i));
if (!se) {
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 9f088aac49..d1898efb69 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -59,11 +59,11 @@ protected:
static void _bind_methods();
GDVIRTUAL0RC(String, _get_name)
- GDVIRTUAL0RC(Array, _get_supported_languages)
+ GDVIRTUAL0RC(PackedStringArray, _get_supported_languages)
public:
virtual String _get_name() const;
- virtual Array _get_supported_languages() const;
+ virtual PackedStringArray _get_supported_languages() const;
void _set_edited_resource(const Ref<Resource> &p_res) { edited_resourse = p_res; }
Ref<RefCounted> _get_edited_resource() { return edited_resourse; }
@@ -156,7 +156,7 @@ public:
virtual void ensure_focus() = 0;
virtual void tag_saved_version() = 0;
virtual void reload(bool p_soft) {}
- virtual Array get_breakpoints() = 0;
+ virtual PackedInt32Array get_breakpoints() = 0;
virtual void set_breakpoint(int p_line, bool p_enabled) = 0;
virtual void clear_breakpoints() = 0;
virtual void add_callback(const String &p_function, PackedStringArray p_args) = 0;
@@ -386,7 +386,7 @@ class ScriptEditor : public PanelContainer {
Array _get_cached_breakpoints_for_script(const String &p_path) const;
ScriptEditorBase *_get_current_editor() const;
- Array _get_open_script_editors() const;
+ TypedArray<ScriptEditorBase> _get_open_script_editors() const;
Ref<ConfigFile> script_editor_cache;
void _save_editor_state(ScriptEditorBase *p_editor);
@@ -452,7 +452,7 @@ class ScriptEditor : public PanelContainer {
void _file_dialog_action(String p_file);
Ref<Script> _get_current_script();
- Array _get_open_scripts() const;
+ TypedArray<Script> _get_open_scripts() const;
HashSet<String> textfile_extensions;
Ref<TextFile> _load_text_file(const String &p_path, Error *r_error) const;
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 5d5f452390..5e7db17edf 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -596,7 +596,7 @@ void ScriptTextEditor::_update_bookmark_list() {
bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT);
bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV);
- Array bookmark_list = code_editor->get_text_editor()->get_bookmarked_lines();
+ PackedInt32Array bookmark_list = code_editor->get_text_editor()->get_bookmarked_lines();
if (bookmark_list.size() == 0) {
return;
}
@@ -751,7 +751,7 @@ void ScriptTextEditor::_update_breakpoint_list() {
breakpoints_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_breakpoint"), DEBUG_GOTO_NEXT_BREAKPOINT);
breakpoints_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_breakpoint"), DEBUG_GOTO_PREV_BREAKPOINT);
- Array breakpoint_list = code_editor->get_text_editor()->get_breakpointed_lines();
+ PackedInt32Array breakpoint_list = code_editor->get_text_editor()->get_breakpointed_lines();
if (breakpoint_list.size() == 0) {
return;
}
@@ -1264,7 +1264,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak);
} break;
case DEBUG_REMOVE_ALL_BREAKPOINTS: {
- Array bpoints = tx->get_breakpointed_lines();
+ PackedInt32Array bpoints = tx->get_breakpointed_lines();
for (int i = 0; i < bpoints.size(); i++) {
int line = bpoints[i];
@@ -1274,7 +1274,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
}
} break;
case DEBUG_GOTO_NEXT_BREAKPOINT: {
- Array bpoints = tx->get_breakpointed_lines();
+ PackedInt32Array bpoints = tx->get_breakpointed_lines();
if (bpoints.size() <= 0) {
return;
}
@@ -1300,7 +1300,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
} break;
case DEBUG_GOTO_PREV_BREAKPOINT: {
- Array bpoints = tx->get_breakpointed_lines();
+ PackedInt32Array bpoints = tx->get_breakpointed_lines();
if (bpoints.size() <= 0) {
return;
}
@@ -1441,7 +1441,7 @@ void ScriptTextEditor::reload(bool p_soft) {
scr->get_language()->reload_tool_script(scr, soft);
}
-Array ScriptTextEditor::get_breakpoints() {
+PackedInt32Array ScriptTextEditor::get_breakpoints() {
return code_editor->get_text_editor()->get_breakpointed_lines();
}
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index fc87c84a2c..8d2fb98721 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -229,7 +229,7 @@ public:
virtual void clear_executing_line() override;
virtual void reload(bool p_soft) override;
- virtual Array get_breakpoints() override;
+ virtual PackedInt32Array get_breakpoints() override;
virtual void set_breakpoint(int p_line, bool p_enabled) override;
virtual void clear_breakpoints() override;
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index d70c50f72a..4641df3dca 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -994,7 +994,7 @@ void ShaderEditor::_update_bookmark_list() {
bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT);
bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV);
- Array bookmark_list = shader_editor->get_text_editor()->get_bookmarked_lines();
+ PackedInt32Array bookmark_list = shader_editor->get_text_editor()->get_bookmarked_lines();
if (bookmark_list.size() == 0) {
return;
}
diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp
index 5a1505c232..3dc068a72a 100644
--- a/editor/plugins/skeleton_2d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_2d_editor_plugin.cpp
@@ -32,6 +32,7 @@
#include "canvas_item_editor_plugin.h"
#include "editor/editor_node.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/2d/mesh_instance_2d.h"
#include "scene/gui/box_container.h"
#include "thirdparty/misc/clipper.hpp"
@@ -59,7 +60,7 @@ void Skeleton2DEditor::_menu_option(int p_option) {
err_dialog->popup_centered();
return;
}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Set Rest Pose to Bones"));
for (int i = 0; i < node->get_bone_count(); i++) {
Bone2D *bone = node->get_bone(i);
@@ -75,7 +76,7 @@ void Skeleton2DEditor::_menu_option(int p_option) {
err_dialog->popup_centered();
return;
}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Create Rest Pose from Bones"));
for (int i = 0; i < node->get_bone_count(); i++) {
Bone2D *bone = node->get_bone(i);
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index c453ed26aa..c25f2bb25c 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -31,10 +31,10 @@
#include "skeleton_3d_editor_plugin.h"
#include "core/io/resource_saver.h"
-#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
#include "editor/editor_scale.h"
+#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/animation_player_editor_plugin.h"
#include "node_3d_editor_plugin.h"
#include "scene/3d/collision_shape_3d.h"
@@ -221,7 +221,7 @@ void Skeleton3DEditor::set_keyable(const bool p_keyable) {
};
void Skeleton3DEditor::set_bone_options_enabled(const bool p_bone_options_enabled) {
- skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_INIT_SELECTED_POSES, !p_bone_options_enabled);
+ skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_RESET_SELECTED_POSES, !p_bone_options_enabled);
skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_SELECTED_POSES_TO_RESTS, !p_bone_options_enabled);
};
@@ -231,12 +231,12 @@ void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) {
}
switch (p_skeleton_option) {
- case SKELETON_OPTION_INIT_ALL_POSES: {
- init_pose(true);
+ case SKELETON_OPTION_RESET_ALL_POSES: {
+ reset_pose(true);
break;
}
- case SKELETON_OPTION_INIT_SELECTED_POSES: {
- init_pose(false);
+ case SKELETON_OPTION_RESET_SELECTED_POSES: {
+ reset_pose(false);
break;
}
case SKELETON_OPTION_ALL_POSES_TO_RESTS: {
@@ -258,7 +258,7 @@ void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) {
}
}
-void Skeleton3DEditor::init_pose(const bool p_all_bones) {
+void Skeleton3DEditor::reset_pose(const bool p_all_bones) {
if (!skeleton) {
return;
}
@@ -267,31 +267,25 @@ void Skeleton3DEditor::init_pose(const bool p_all_bones) {
return;
}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS);
if (p_all_bones) {
for (int i = 0; i < bone_len; i++) {
- Transform3D rest = skeleton->get_bone_rest(i);
- ur->add_do_method(skeleton, "set_bone_pose_position", i, rest.origin);
- ur->add_do_method(skeleton, "set_bone_pose_rotation", i, rest.basis.get_rotation_quaternion());
- ur->add_do_method(skeleton, "set_bone_pose_scale", i, rest.basis.get_scale());
ur->add_undo_method(skeleton, "set_bone_pose_position", i, skeleton->get_bone_pose_position(i));
ur->add_undo_method(skeleton, "set_bone_pose_rotation", i, skeleton->get_bone_pose_rotation(i));
ur->add_undo_method(skeleton, "set_bone_pose_scale", i, skeleton->get_bone_pose_scale(i));
}
+ ur->add_do_method(skeleton, "reset_bone_poses");
} else {
// Todo: Do method with multiple bone selection.
if (selected_bone == -1) {
ur->commit_action();
return;
}
- Transform3D rest = skeleton->get_bone_rest(selected_bone);
- ur->add_do_method(skeleton, "set_bone_pose_position", selected_bone, rest.origin);
- ur->add_do_method(skeleton, "set_bone_pose_rotation", selected_bone, rest.basis.get_rotation_quaternion());
- ur->add_do_method(skeleton, "set_bone_pose_scale", selected_bone, rest.basis.get_scale());
ur->add_undo_method(skeleton, "set_bone_pose_position", selected_bone, skeleton->get_bone_pose_position(selected_bone));
ur->add_undo_method(skeleton, "set_bone_pose_rotation", selected_bone, skeleton->get_bone_pose_rotation(selected_bone));
ur->add_undo_method(skeleton, "set_bone_pose_scale", selected_bone, skeleton->get_bone_pose_scale(selected_bone));
+ ur->add_do_method(skeleton, "reset_bone_pose", selected_bone);
}
ur->commit_action();
}
@@ -340,7 +334,7 @@ void Skeleton3DEditor::pose_to_rest(const bool p_all_bones) {
return;
}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Set Bone Rest"), UndoRedo::MERGE_ENDS);
if (p_all_bones) {
for (int i = 0; i < bone_len; i++) {
@@ -360,7 +354,7 @@ void Skeleton3DEditor::pose_to_rest(const bool p_all_bones) {
}
void Skeleton3DEditor::create_physical_skeleton() {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ERR_FAIL_COND(!get_tree());
Node *owner = get_tree()->get_edited_scene_root();
@@ -593,7 +587,7 @@ void Skeleton3DEditor::move_skeleton_bone(NodePath p_skeleton_path, int32_t p_se
Node *node = get_node_or_null(p_skeleton_path);
Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node);
ERR_FAIL_NULL(skeleton);
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Set Bone Parentage"));
// If the target is a child of ourselves, we move only *us* and not our children.
if (skeleton->is_bone_parent_of(p_target_boneidx, p_selected_boneidx)) {
@@ -721,8 +715,8 @@ void Skeleton3DEditor::create_editors() {
// Skeleton options.
PopupMenu *p = skeleton_options->get_popup();
- p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/init_all_poses", TTR("Init all Poses")), SKELETON_OPTION_INIT_ALL_POSES);
- p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/init_selected_poses", TTR("Init selected Poses")), SKELETON_OPTION_INIT_SELECTED_POSES);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/reset_all_poses", TTR("Reset all bone Poses")), SKELETON_OPTION_RESET_ALL_POSES);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/reset_selected_poses", TTR("Reset selected Poses")), SKELETON_OPTION_RESET_SELECTED_POSES);
p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/all_poses_to_rests", TTR("Apply all poses to rests")), SKELETON_OPTION_ALL_POSES_TO_RESTS);
p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/selected_poses_to_rests", TTR("Apply selected poses to rests")), SKELETON_OPTION_SELECTED_POSES_TO_RESTS);
p->add_item(TTR("Create physical skeleton"), SKELETON_OPTION_CREATE_PHYSICAL_SKELETON);
@@ -1315,7 +1309,7 @@ void Skeleton3DGizmoPlugin::commit_subgizmos(const EditorNode3DGizmo *p_gizmo, c
Skeleton3DEditor *se = Skeleton3DEditor::get_singleton();
Node3DEditor *ne = Node3DEditor::get_singleton();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Set Bone Transform"));
if (ne->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || ne->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) {
for (int i = 0; i < p_ids.size(); i++) {
diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h
index 975b54fa77..9747ed8374 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.h
+++ b/editor/plugins/skeleton_3d_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef SKELETON_3D_EDITOR_PLUGIN_H
#define SKELETON_3D_EDITOR_PLUGIN_H
+#include "editor/editor_file_dialog.h"
#include "editor/editor_plugin.h"
#include "editor/editor_properties.h"
#include "node_3d_editor_plugin.h"
@@ -40,6 +41,7 @@
#include "scene/resources/immediate_mesh.h"
class EditorInspectorPluginSkeleton;
+class EditorUndoRedoManager;
class Joint;
class PhysicalBone3D;
class Skeleton3DEditorPlugin;
@@ -63,7 +65,7 @@ class BoneTransformEditor : public VBoxContainer {
Skeleton3D *skeleton = nullptr;
// String property;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
bool toggle_enabled = false;
bool updating = false;
@@ -96,8 +98,8 @@ class Skeleton3DEditor : public VBoxContainer {
friend class Skeleton3DEditorPlugin;
enum SkeletonOption {
- SKELETON_OPTION_INIT_ALL_POSES,
- SKELETON_OPTION_INIT_SELECTED_POSES,
+ SKELETON_OPTION_RESET_ALL_POSES,
+ SKELETON_OPTION_RESET_SELECTED_POSES,
SKELETON_OPTION_ALL_POSES_TO_RESTS,
SKELETON_OPTION_SELECTED_POSES_TO_RESTS,
SKELETON_OPTION_CREATE_PHYSICAL_SKELETON,
@@ -148,7 +150,7 @@ class Skeleton3DEditor : public VBoxContainer {
void create_editors();
- void init_pose(const bool p_all_bones);
+ void reset_pose(const bool p_all_bones);
void pose_to_rest(const bool p_all_bones);
void insert_keys(const bool p_all_bones);
diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp
index 7d350fd46f..e45c907e86 100644
--- a/editor/plugins/sprite_2d_editor_plugin.cpp
+++ b/editor/plugins/sprite_2d_editor_plugin.cpp
@@ -34,6 +34,7 @@
#include "core/math/geometry_2d.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_undo_redo_manager.h"
#include "editor/scene_tree_dock.h"
#include "scene/2d/collision_polygon_2d.h"
#include "scene/2d/light_occluder_2d.h"
@@ -342,7 +343,7 @@ void Sprite2DEditor::_convert_to_mesh_2d_node() {
MeshInstance2D *mesh_instance = memnew(MeshInstance2D);
mesh_instance->set_mesh(mesh);
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Convert to MeshInstance2D"));
ur->add_do_method(SceneTreeDock::get_singleton(), "replace_node", node, mesh_instance, true, false);
ur->add_do_reference(mesh_instance);
@@ -400,7 +401,7 @@ void Sprite2DEditor::_convert_to_polygon_2d_node() {
polygon_2d_instance->set_polygon(polygon);
polygon_2d_instance->set_polygons(polys);
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Convert to Polygon2D"));
ur->add_do_method(SceneTreeDock::get_singleton(), "replace_node", node, polygon_2d_instance, true, false);
ur->add_do_reference(polygon_2d_instance);
@@ -422,7 +423,7 @@ void Sprite2DEditor::_create_collision_polygon_2d_node() {
CollisionPolygon2D *collision_polygon_2d_instance = memnew(CollisionPolygon2D);
collision_polygon_2d_instance->set_polygon(outline);
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Create CollisionPolygon2D Sibling"));
ur->add_do_method(this, "_add_as_sibling_or_child", node, collision_polygon_2d_instance);
ur->add_do_reference(collision_polygon_2d_instance);
@@ -455,7 +456,7 @@ void Sprite2DEditor::_create_light_occluder_2d_node() {
LightOccluder2D *light_occluder_2d_instance = memnew(LightOccluder2D);
light_occluder_2d_instance->set_occluder_polygon(polygon);
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Create LightOccluder2D Sibling"));
ur->add_do_method(this, "_add_as_sibling_or_child", node, light_occluder_2d_instance);
ur->add_do_reference(light_occluder_2d_instance);
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index a39d24a167..205fed48b4 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "editor/scene_tree_dock.h"
#include "scene/3d/sprite_3d.h"
#include "scene/gui/center_container.h"
@@ -1010,6 +1011,10 @@ void SpriteFramesEditor::edit(SpriteFrames *p_frames) {
}
}
+void SpriteFramesEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) {
+ undo_redo = p_undo_redo;
+}
+
Variant SpriteFramesEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
if (!frames->has_animation(edited_anim)) {
return false;
@@ -1471,7 +1476,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
}
void SpriteFramesEditorPlugin::edit(Object *p_object) {
- frames_editor->set_undo_redo(&get_undo_redo());
+ frames_editor->set_undo_redo(get_undo_redo());
SpriteFrames *s;
AnimatedSprite2D *animated_sprite = Object::cast_to<AnimatedSprite2D>(p_object);
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index 6352259b73..f2530b732f 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -45,6 +45,7 @@
#include "scene/gui/tree.h"
class EditorFileDialog;
+class EditorUndoRedoManager;
class SpriteFramesEditor : public HSplitContainer {
GDCLASS(SpriteFramesEditor, HSplitContainer);
@@ -151,7 +152,7 @@ class SpriteFramesEditor : public HSplitContainer {
bool updating;
bool updating_split_settings = false; // Skip SpinBox/Range callback when setting value by code.
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
@@ -176,7 +177,7 @@ protected:
static void _bind_methods();
public:
- void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; }
+ void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo);
void edit(SpriteFrames *p_frames);
SpriteFramesEditor();
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index 196d87da36..0900415b04 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -128,8 +128,8 @@ Control *TextEditor::get_base_editor() const {
return code_editor->get_text_editor();
}
-Array TextEditor::get_breakpoints() {
- return Array();
+PackedInt32Array TextEditor::get_breakpoints() {
+ return PackedInt32Array();
}
void TextEditor::reload_text() {
@@ -165,7 +165,7 @@ void TextEditor::_update_bookmark_list() {
bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT);
bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV);
- Array bookmark_list = code_editor->get_text_editor()->get_bookmarked_lines();
+ PackedInt32Array bookmark_list = code_editor->get_text_editor()->get_bookmarked_lines();
if (bookmark_list.size() == 0) {
return;
}
diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h
index 4f0121da52..15f7c45653 100644
--- a/editor/plugins/text_editor.h
+++ b/editor/plugins/text_editor.h
@@ -118,7 +118,7 @@ public:
virtual Variant get_edit_state() override;
virtual void set_edit_state(const Variant &p_state) override;
virtual Vector<String> get_functions() override;
- virtual Array get_breakpoints() override;
+ virtual PackedInt32Array get_breakpoints() override;
virtual void set_breakpoint(int p_line, bool p_enabled) override{};
virtual void clear_breakpoints() override{};
virtual void goto_line(int p_line, bool p_with_error = false) override;
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 0bd8a8a484..772bae6544 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -36,6 +36,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/check_box.h"
#include "scene/gui/separator.h"
#include "scene/gui/view_panner.h"
diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h
index a18c87f153..e3bbaf49fc 100644
--- a/editor/plugins/texture_region_editor_plugin.h
+++ b/editor/plugins/texture_region_editor_plugin.h
@@ -40,6 +40,7 @@
#include "scene/resources/texture.h"
class ViewPanner;
+class EditorUndoRedoManager;
class TextureRegionEditor : public AcceptDialog {
GDCLASS(TextureRegionEditor, AcceptDialog);
@@ -68,7 +69,7 @@ class TextureRegionEditor : public AcceptDialog {
VScrollBar *vscroll = nullptr;
HScrollBar *hscroll = nullptr;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
Vector2 draw_ofs;
float draw_zoom = 0.0;
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index bbc22c8622..af3959d47c 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -35,6 +35,7 @@
#include "editor/editor_node.h"
#include "editor/editor_resource_picker.h"
#include "editor/editor_scale.h"
+#include "editor/editor_undo_redo_manager.h"
#include "editor/progress_dialog.h"
#include "scene/gui/color_picker.h"
@@ -796,7 +797,7 @@ void ThemeItemImportTree::_import_selected() {
ProgressDialog::get_singleton()->end_task("import_theme_items");
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Import Theme Items"));
ur->add_do_method(*edited_theme, "clear");
@@ -1494,7 +1495,7 @@ void ThemeItemEditorDialog::_item_tree_button_pressed(Object *p_item, int p_colu
String item_name = item->get_text(0);
int data_type = item->get_parent()->get_metadata(0);
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Remove Theme Item"));
ur->add_do_method(*edited_theme, "clear_theme_item", (Theme::DataType)data_type, item_name, edited_item_type);
ur->add_undo_method(*edited_theme, "set_theme_item", (Theme::DataType)data_type, item_name, edited_item_type, edited_theme->get_theme_item((Theme::DataType)data_type, item_name, edited_item_type));
@@ -1513,7 +1514,7 @@ void ThemeItemEditorDialog::_add_theme_type(const String &p_new_text) {
const String new_type = edit_add_type_value->get_text().strip_edges();
edit_add_type_value->clear();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Add Theme Type"));
ur->add_do_method(*edited_theme, "add_type", new_type);
@@ -1525,7 +1526,7 @@ void ThemeItemEditorDialog::_add_theme_type(const String &p_new_text) {
}
void ThemeItemEditorDialog::_add_theme_item(Theme::DataType p_data_type, String p_item_name, String p_item_type) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Create Theme Item"));
switch (p_data_type) {
@@ -1570,7 +1571,7 @@ void ThemeItemEditorDialog::_remove_theme_type(const String &p_theme_type) {
Ref<Theme> old_snapshot = edited_theme->duplicate();
Ref<Theme> new_snapshot = edited_theme->duplicate();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Remove Theme Type"));
new_snapshot->remove_type(p_theme_type);
@@ -1593,7 +1594,7 @@ void ThemeItemEditorDialog::_remove_data_type_items(Theme::DataType p_data_type,
Ref<Theme> old_snapshot = edited_theme->duplicate();
Ref<Theme> new_snapshot = edited_theme->duplicate();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Remove Data Type Items From Theme"));
new_snapshot->get_theme_item_list(p_data_type, p_item_type, &names);
@@ -1622,7 +1623,7 @@ void ThemeItemEditorDialog::_remove_class_items() {
Ref<Theme> old_snapshot = edited_theme->duplicate();
Ref<Theme> new_snapshot = edited_theme->duplicate();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Remove Class Items From Theme"));
for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) {
@@ -1658,7 +1659,7 @@ void ThemeItemEditorDialog::_remove_custom_items() {
Ref<Theme> old_snapshot = edited_theme->duplicate();
Ref<Theme> new_snapshot = edited_theme->duplicate();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Remove Custom Items From Theme"));
for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) {
@@ -1694,7 +1695,7 @@ void ThemeItemEditorDialog::_remove_all_items() {
Ref<Theme> old_snapshot = edited_theme->duplicate();
Ref<Theme> new_snapshot = edited_theme->duplicate();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Remove All Items From Theme"));
for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) {
@@ -1798,7 +1799,7 @@ void ThemeItemEditorDialog::_confirm_edit_theme_item() {
if (item_popup_mode == CREATE_THEME_ITEM) {
_add_theme_item(edit_item_data_type, theme_item_name->get_text(), edited_item_type);
} else if (item_popup_mode == RENAME_THEME_ITEM) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Rename Theme Item"));
ur->add_do_method(*edited_theme, "rename_theme_item", edit_item_data_type, edit_item_old_name, theme_item_name->get_text(), edited_item_type);
@@ -2824,7 +2825,7 @@ void ThemeTypeEditor::_add_default_type_items() {
updating = false;
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Override All Default Theme Items"));
ur->add_do_method(*edited_theme, "merge_with", new_snapshot);
@@ -2844,7 +2845,7 @@ void ThemeTypeEditor::_item_add_cbk(int p_data_type, Control *p_control) {
}
String item_name = le->get_text().strip_edges();
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Add Theme Item"));
switch (p_data_type) {
@@ -2889,7 +2890,7 @@ void ThemeTypeEditor::_item_add_lineedit_cbk(String p_value, int p_data_type, Co
}
void ThemeTypeEditor::_item_override_cbk(int p_data_type, String p_item_name) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Override Theme Item"));
switch (p_data_type) {
@@ -2928,7 +2929,7 @@ void ThemeTypeEditor::_item_override_cbk(int p_data_type, String p_item_name) {
}
void ThemeTypeEditor::_item_remove_cbk(int p_data_type, String p_item_name) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Remove Theme Item"));
switch (p_data_type) {
@@ -3002,7 +3003,7 @@ void ThemeTypeEditor::_item_rename_confirmed(int p_data_type, String p_item_name
return;
}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Rename Theme Item"));
switch (p_data_type) {
@@ -3058,7 +3059,7 @@ void ThemeTypeEditor::_item_rename_canceled(int p_data_type, String p_item_name,
}
void ThemeTypeEditor::_color_item_changed(Color p_value, String p_item_name) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Set Color Item in Theme"), UndoRedo::MERGE_ENDS);
ur->add_do_method(*edited_theme, "set_color", p_item_name, edited_type, p_value);
ur->add_undo_method(*edited_theme, "set_color", p_item_name, edited_type, edited_theme->get_color(p_item_name, edited_type));
@@ -3066,7 +3067,7 @@ void ThemeTypeEditor::_color_item_changed(Color p_value, String p_item_name) {
}
void ThemeTypeEditor::_constant_item_changed(float p_value, String p_item_name) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Set Constant Item in Theme"));
ur->add_do_method(*edited_theme, "set_constant", p_item_name, edited_type, p_value);
ur->add_undo_method(*edited_theme, "set_constant", p_item_name, edited_type, edited_theme->get_constant(p_item_name, edited_type));
@@ -3074,7 +3075,7 @@ void ThemeTypeEditor::_constant_item_changed(float p_value, String p_item_name)
}
void ThemeTypeEditor::_font_size_item_changed(float p_value, String p_item_name) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Set Font Size Item in Theme"));
ur->add_do_method(*edited_theme, "set_font_size", p_item_name, edited_type, p_value);
ur->add_undo_method(*edited_theme, "set_font_size", p_item_name, edited_type, edited_theme->get_font_size(p_item_name, edited_type));
@@ -3086,7 +3087,7 @@ void ThemeTypeEditor::_edit_resource_item(Ref<Resource> p_resource, bool p_edit)
}
void ThemeTypeEditor::_font_item_changed(Ref<Font> p_value, String p_item_name) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Set Font Item in Theme"));
ur->add_do_method(*edited_theme, "set_font", p_item_name, edited_type, p_value.is_valid() ? p_value : Ref<Font>());
@@ -3103,7 +3104,7 @@ void ThemeTypeEditor::_font_item_changed(Ref<Font> p_value, String p_item_name)
}
void ThemeTypeEditor::_icon_item_changed(Ref<Texture2D> p_value, String p_item_name) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Set Icon Item in Theme"));
ur->add_do_method(*edited_theme, "set_icon", p_item_name, edited_type, p_value.is_valid() ? p_value : Ref<Texture2D>());
@@ -3120,7 +3121,7 @@ void ThemeTypeEditor::_icon_item_changed(Ref<Texture2D> p_value, String p_item_n
}
void ThemeTypeEditor::_stylebox_item_changed(Ref<StyleBox> p_value, String p_item_name) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Set Stylebox Item in Theme"));
ur->add_do_method(*edited_theme, "set_stylebox", p_item_name, edited_type, p_value.is_valid() ? p_value : Ref<StyleBox>());
@@ -3163,7 +3164,7 @@ void ThemeTypeEditor::_on_pin_leader_button_pressed(Control *p_editor, String p_
stylebox = Object::cast_to<EditorResourcePicker>(p_editor)->get_edited_resource();
}
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Pin Stylebox"));
ur->add_do_method(this, "_pin_leading_stylebox", p_item_name, stylebox);
@@ -3196,7 +3197,7 @@ void ThemeTypeEditor::_pin_leading_stylebox(String p_item_name, Ref<StyleBox> p_
}
void ThemeTypeEditor::_on_unpin_leader_button_pressed() {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Unpin Stylebox"));
ur->add_do_method(this, "_unpin_leading_stylebox");
ur->add_undo_method(this, "_pin_leading_stylebox", leading_stylebox.item_name, leading_stylebox.stylebox);
@@ -3265,7 +3266,7 @@ void ThemeTypeEditor::_update_stylebox_from_leading() {
}
void ThemeTypeEditor::_type_variation_changed(const String p_value) {
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
ur->create_action(TTR("Set Theme Type Variation"));
if (p_value.is_empty()) {
diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp
index 3fe6778f48..de4f3f7989 100644
--- a/editor/plugins/tiles/atlas_merging_dialog.cpp
+++ b/editor/plugins/tiles/atlas_merging_dialog.cpp
@@ -33,6 +33,7 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/control.h"
#include "scene/gui/split_container.h"
diff --git a/editor/plugins/tiles/atlas_merging_dialog.h b/editor/plugins/tiles/atlas_merging_dialog.h
index c54e259594..c7e4635d16 100644
--- a/editor/plugins/tiles/atlas_merging_dialog.h
+++ b/editor/plugins/tiles/atlas_merging_dialog.h
@@ -38,6 +38,7 @@
#include "scene/resources/tile_set.h"
class EditorFileDialog;
+class EditorUndoRedoManager;
class AtlasMergingDialog : public ConfirmationDialog {
GDCLASS(AtlasMergingDialog, ConfirmationDialog);
@@ -49,7 +50,7 @@ private:
LocalVector<HashMap<Vector2i, Vector2i>> merged_mapping;
Ref<TileSet> tile_set;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
// Settings.
int next_line_after_column = 30;
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index a00e1ed9e8..b44b6fcc53 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -38,6 +38,7 @@
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
#include "editor/editor_scale.h"
+#include "editor/editor_undo_redo_manager.h"
void TileDataEditor::_tile_set_changed_plan_update() {
_tile_set_changed_update_needed = true;
@@ -248,7 +249,14 @@ void GenericTilePolygonEditor::_zoom_changed() {
}
void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) {
- UndoRedo *undo_redo = use_undo_redo ? editor_undo_redo : memnew(UndoRedo);
+ Ref<EditorUndoRedoManager> undo_redo;
+ if (use_undo_redo) {
+ undo_redo = editor_undo_redo;
+ } else {
+ // This nice hack allows for discarding undo actions without making code too complex.
+ undo_redo.instantiate();
+ }
+
switch (p_item_pressed) {
case RESET_TO_DEFAULT_TILE: {
undo_redo->create_action(TTR("Reset Polygons"));
@@ -322,9 +330,6 @@ void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) {
default:
break;
}
- if (!use_undo_redo) {
- memdelete(undo_redo);
- }
}
void GenericTilePolygonEditor::_grab_polygon_point(Vector2 p_pos, const Transform2D &p_polygon_xform, int &r_polygon_index, int &r_point_index) {
@@ -409,7 +414,14 @@ void GenericTilePolygonEditor::_snap_to_half_pixel(Point2 &r_point) {
}
void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event) {
- UndoRedo *undo_redo = use_undo_redo ? editor_undo_redo : memnew(UndoRedo);
+ Ref<EditorUndoRedoManager> undo_redo;
+ if (use_undo_redo) {
+ undo_redo = editor_undo_redo;
+ } else {
+ // This nice hack allows for discarding undo actions without making code too complex.
+ undo_redo.instantiate();
+ }
+
real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius");
hovered_polygon_index = -1;
@@ -600,10 +612,6 @@ void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event)
}
base_control->update();
-
- if (!use_undo_redo) {
- memdelete(undo_redo);
- }
}
void GenericTilePolygonEditor::set_use_undo_redo(bool p_use_undo_redo) {
diff --git a/editor/plugins/tiles/tile_data_editors.h b/editor/plugins/tiles/tile_data_editors.h
index f9b8948d0a..c1560138b2 100644
--- a/editor/plugins/tiles/tile_data_editors.h
+++ b/editor/plugins/tiles/tile_data_editors.h
@@ -39,6 +39,8 @@
#include "scene/gui/control.h"
#include "scene/gui/label.h"
+class EditorUndoRedoManager;
+
class TileDataEditor : public VBoxContainer {
GDCLASS(TileDataEditor, VBoxContainer);
@@ -93,7 +95,7 @@ private:
bool multiple_polygon_mode = false;
bool use_undo_redo = true;
- UndoRedo *editor_undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> editor_undo_redo;
// UI
int hovered_polygon_index = -1;
@@ -214,7 +216,7 @@ private:
protected:
DummyObject *dummy_object = memnew(DummyObject);
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
StringName type;
String property;
@@ -279,7 +281,7 @@ private:
virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) override;
protected:
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
virtual void _tile_set_changed() override;
@@ -314,7 +316,7 @@ class TileDataCollisionEditor : public TileDataDefaultEditor {
virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) override;
protected:
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
virtual void _tile_set_changed() override;
@@ -366,7 +368,7 @@ protected:
void _notification(int p_what);
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
public:
virtual Control *get_toolbar() override { return toolbar; };
@@ -399,7 +401,7 @@ private:
virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) override;
protected:
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
virtual void _tile_set_changed() override;
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 1bf24a7393..3f355a1ed2 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -35,6 +35,7 @@
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_scale.h"
+#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "scene/2d/camera_2d.h"
@@ -3697,8 +3698,8 @@ void TileMapEditor::_update_layers_selection() {
}
void TileMapEditor::_move_tile_map_array_element(Object *p_undo_redo, Object *p_edited, String p_array_prefix, int p_from_index, int p_to_pos) {
- UndoRedo *undo_redo = Object::cast_to<UndoRedo>(p_undo_redo);
- ERR_FAIL_COND(!undo_redo);
+ Ref<EditorUndoRedoManager> undo_redo = Object::cast_to<EditorUndoRedoManager>(p_undo_redo);
+ ERR_FAIL_COND(undo_redo.is_null());
TileMap *tile_map = Object::cast_to<TileMap>(p_edited);
if (!tile_map) {
diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h
index 605fbe4823..9a47d8bbc4 100644
--- a/editor/plugins/tiles/tile_map_editor.h
+++ b/editor/plugins/tiles/tile_map_editor.h
@@ -47,7 +47,7 @@
#include "scene/gui/tab_bar.h"
#include "scene/gui/tree.h"
-class UndoRedo;
+class EditorUndoRedoManager;
class TileMapEditorPlugin : public Object {
public:
@@ -70,7 +70,7 @@ class TileMapEditorTilesPlugin : public TileMapEditorPlugin {
GDCLASS(TileMapEditorTilesPlugin, TileMapEditorPlugin);
private:
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
ObjectID tile_map_id;
int tile_map_layer = -1;
virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer) override;
@@ -223,7 +223,7 @@ class TileMapEditorTerrainsPlugin : public TileMapEditorPlugin {
GDCLASS(TileMapEditorTerrainsPlugin, TileMapEditorPlugin);
private:
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
ObjectID tile_map_id;
int tile_map_layer = -1;
virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer) override;
@@ -317,7 +317,7 @@ class TileMapEditor : public VBoxContainer {
GDCLASS(TileMapEditor, VBoxContainer);
private:
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
bool tileset_changed_needs_update = false;
ObjectID tile_map_id;
int tile_map_layer = -1;
diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
index 12e1615484..9e4c29fa79 100644
--- a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
+++ b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
@@ -32,6 +32,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_undo_redo_manager.h"
void TileProxiesManagerDialog::_right_clicked(int p_item, Vector2 p_local_mouse_pos, Object *p_item_list, MouseButton p_mouse_button_index) {
if (p_mouse_button_index != MouseButton::RIGHT) {
diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.h b/editor/plugins/tiles/tile_proxies_manager_dialog.h
index 44de708898..511e442a10 100644
--- a/editor/plugins/tiles/tile_proxies_manager_dialog.h
+++ b/editor/plugins/tiles/tile_proxies_manager_dialog.h
@@ -43,7 +43,7 @@ private:
int commited_actions_count = 0;
Ref<TileSet> tile_set;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
TileMapCell from;
TileMapCell to;
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index 6950f57a00..09722d3d65 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -2058,14 +2058,16 @@ void TileSetAtlasSourceEditor::_atlas_source_proxy_object_changed(String p_what)
}
void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo, Object *p_edited, String p_property, Variant p_new_value) {
- UndoRedo *undo_redo = Object::cast_to<UndoRedo>(p_undo_redo);
- ERR_FAIL_COND(!undo_redo);
+ Ref<EditorUndoRedoManager> undo_redo = Object::cast_to<EditorUndoRedoManager>(p_undo_redo);
+ ERR_FAIL_COND(!undo_redo.is_valid());
#define ADD_UNDO(obj, property) undo_redo->add_undo_property(obj, property, obj->get(property));
- undo_redo->start_force_keep_in_merge_ends();
AtlasTileProxyObject *tile_data_proxy = Object::cast_to<AtlasTileProxyObject>(p_edited);
if (tile_data_proxy) {
+ UndoRedo *internal_undo_redo = undo_redo->get_history_for_object(tile_data_proxy).undo_redo;
+ internal_undo_redo->start_force_keep_in_merge_ends();
+
Vector<String> components = String(p_property).split("/", true, 2);
if (components.size() == 2 && components[1] == "polygons_count") {
int layer_index = components[0].trim_prefix("physics_layer_").to_int();
@@ -2088,6 +2090,7 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo
}
}
}
+ internal_undo_redo->end_force_keep_in_merge_ends();
}
TileSetAtlasSourceProxyObject *atlas_source_proxy = Object::cast_to<TileSetAtlasSourceProxyObject>(p_edited);
@@ -2095,6 +2098,9 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo
TileSetAtlasSource *atlas_source = atlas_source_proxy->get_edited();
ERR_FAIL_COND(!atlas_source);
+ UndoRedo *internal_undo_redo = undo_redo->get_history_for_object(atlas_source).undo_redo;
+ internal_undo_redo->start_force_keep_in_merge_ends();
+
PackedVector2Array arr;
if (p_property == "texture") {
arr = atlas_source->get_tiles_to_be_removed_on_change(p_new_value, atlas_source->get_margins(), atlas_source->get_separation(), atlas_source->get_texture_region_size());
@@ -2121,8 +2127,8 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo
}
}
}
+ internal_undo_redo->end_force_keep_in_merge_ends();
}
- undo_redo->end_force_keep_in_merge_ends();
#undef ADD_UNDO
}
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h
index 738fe1044d..badb702e29 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.h
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h
@@ -114,7 +114,7 @@ private:
TileSetAtlasSource *tile_set_atlas_source = nullptr;
int tile_set_atlas_source_id = TileSet::INVALID_SOURCE;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
bool tile_set_changed_needs_update = false;
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index 81804710b4..8d04dd3121 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -36,6 +36,7 @@
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_undo_redo_manager.h"
#include "scene/gui/box_container.h"
#include "scene/gui/control.h"
@@ -405,8 +406,8 @@ void TileSetEditor::_tab_changed(int p_tab_changed) {
}
void TileSetEditor::_move_tile_set_array_element(Object *p_undo_redo, Object *p_edited, String p_array_prefix, int p_from_index, int p_to_pos) {
- UndoRedo *undo_redo = Object::cast_to<UndoRedo>(p_undo_redo);
- ERR_FAIL_COND(!undo_redo);
+ Ref<EditorUndoRedoManager> undo_redo = Object::cast_to<EditorUndoRedoManager>(p_undo_redo);
+ ERR_FAIL_COND(undo_redo.is_null());
TileSet *tile_set = Object::cast_to<TileSet>(p_edited);
if (!tile_set) {
@@ -586,8 +587,8 @@ void TileSetEditor::_move_tile_set_array_element(Object *p_undo_redo, Object *p_
}
void TileSetEditor::_undo_redo_inspector_callback(Object *p_undo_redo, Object *p_edited, String p_property, Variant p_new_value) {
- UndoRedo *undo_redo = Object::cast_to<UndoRedo>(p_undo_redo);
- ERR_FAIL_COND(!undo_redo);
+ Ref<EditorUndoRedoManager> undo_redo = Object::cast_to<EditorUndoRedoManager>(p_undo_redo);
+ ERR_FAIL_COND(undo_redo.is_null());
#define ADD_UNDO(obj, property) undo_redo->add_undo_property(obj, property, obj->get(property));
TileSet *tile_set = Object::cast_to<TileSet>(p_edited);
diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h
index c45240043e..3b9b80dac4 100644
--- a/editor/plugins/tiles/tile_set_editor.h
+++ b/editor/plugins/tiles/tile_set_editor.h
@@ -39,6 +39,8 @@
#include "tile_set_atlas_source_editor.h"
#include "tile_set_scenes_collection_source_editor.h"
+class EditorUndoRedoManager;
+
class TileSetEditor : public VBoxContainer {
GDCLASS(TileSetEditor, VBoxContainer);
@@ -58,7 +60,7 @@ private:
TileSetAtlasSourceEditor *tile_set_atlas_source_editor = nullptr;
TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor = nullptr;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
void _drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
bool _can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
index 77a583e522..0284b45c0f 100644
--- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
@@ -97,7 +97,7 @@ private:
TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr;
int tile_set_source_id = -1;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
bool tile_set_scenes_collection_source_changed_needs_update = false;
diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp
index cf55465417..6db499f2c7 100644
--- a/editor/plugins/version_control_editor_plugin.cpp
+++ b/editor/plugins/version_control_editor_plugin.cpp
@@ -242,7 +242,7 @@ void VersionControlEditorPlugin::_view_file_diff() {
}
void VersionControlEditorPlugin::_display_file_diff(String p_file_path) {
- Array diff_content = EditorVCSInterface::get_singleton()->get_file_diff(p_file_path);
+ TypedArray<Dictionary> diff_content = EditorVCSInterface::get_singleton()->get_file_diff(p_file_path);
diff_file_name->set_text(p_file_path);
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 4a144bc391..961f092650 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -40,6 +40,7 @@
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
#include "editor/editor_scale.h"
+#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/curve_editor_plugin.h"
#include "editor/plugins/shader_editor_plugin.h"
#include "scene/animation/animation_player.h"
@@ -4063,7 +4064,7 @@ void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> p_input,
bool type_changed = next_input_type != prev_input_type;
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Visual Shader Input Type Changed"));
undo_redo->add_do_method(p_input.ptr(), "set_input_name", p_name);
@@ -4132,7 +4133,7 @@ void VisualShaderEditor::_uniform_select_item(Ref<VisualShaderNodeUniformRef> p_
bool type_changed = p_uniform_ref->get_uniform_type_by_name(p_name) != p_uniform_ref->get_uniform_type_by_name(prev_name);
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("UniformRef Name Changed"));
undo_redo->add_do_method(p_uniform_ref.ptr(), "set_uniform_name", p_name);
@@ -4176,7 +4177,7 @@ void VisualShaderEditor::_varying_select_item(Ref<VisualShaderNodeVarying> p_var
bool is_getter = Ref<VisualShaderNodeVaryingGetter>(p_varying.ptr()).is_valid();
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Varying Name Changed"));
undo_redo->add_do_method(p_varying.ptr(), "set_varying_name", p_name);
@@ -5668,7 +5669,7 @@ VisualShaderEditor::VisualShaderEditor() {
_update_options_menu();
- undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ undo_redo = EditorNode::get_undo_redo();
Ref<VisualShaderNodePluginDefault> default_plugin;
default_plugin.instantiate();
@@ -5876,7 +5877,7 @@ public:
return;
}
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo();
updating = true;
undo_redo->create_action(TTR("Edit Visual Property:") + " " + p_property, UndoRedo::MERGE_ENDS);
@@ -6063,7 +6064,7 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_par
return editor;
}
-void EditorPropertyShaderMode::_option_selected(int p_which) {
+void EditorPropertyVisualShaderMode::_option_selected(int p_which) {
Ref<VisualShader> visual_shader(Object::cast_to<VisualShader>(get_edited_object()));
if (visual_shader->get_mode() == p_which) {
return;
@@ -6078,7 +6079,7 @@ void EditorPropertyShaderMode::_option_selected(int p_which) {
return;
}
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo();
undo_redo->create_action(TTR("Visual Shader Mode Changed"));
//do is easy
undo_redo->add_do_method(visual_shader.ptr(), "set_mode", p_which);
@@ -6149,39 +6150,39 @@ void EditorPropertyShaderMode::_option_selected(int p_which) {
undo_redo->commit_action();
}
-void EditorPropertyShaderMode::update_property() {
+void EditorPropertyVisualShaderMode::update_property() {
int which = get_edited_object()->get(get_edited_property());
options->select(which);
}
-void EditorPropertyShaderMode::setup(const Vector<String> &p_options) {
+void EditorPropertyVisualShaderMode::setup(const Vector<String> &p_options) {
for (int i = 0; i < p_options.size(); i++) {
options->add_item(p_options[i], i);
}
}
-void EditorPropertyShaderMode::set_option_button_clip(bool p_enable) {
+void EditorPropertyVisualShaderMode::set_option_button_clip(bool p_enable) {
options->set_clip_text(p_enable);
}
-void EditorPropertyShaderMode::_bind_methods() {
+void EditorPropertyVisualShaderMode::_bind_methods() {
}
-EditorPropertyShaderMode::EditorPropertyShaderMode() {
+EditorPropertyVisualShaderMode::EditorPropertyVisualShaderMode() {
options = memnew(OptionButton);
options->set_clip_text(true);
add_child(options);
add_focusable(options);
- options->connect("item_selected", callable_mp(this, &EditorPropertyShaderMode::_option_selected));
+ options->connect("item_selected", callable_mp(this, &EditorPropertyVisualShaderMode::_option_selected));
}
-bool EditorInspectorShaderModePlugin::can_handle(Object *p_object) {
+bool EditorInspectorVisualShaderModePlugin::can_handle(Object *p_object) {
return true; // Can handle everything.
}
-bool EditorInspectorShaderModePlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
+bool EditorInspectorVisualShaderModePlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
if (p_path == "mode" && p_object->is_class("VisualShader") && p_type == Variant::INT) {
- EditorPropertyShaderMode *mode_editor = memnew(EditorPropertyShaderMode);
+ EditorPropertyVisualShaderMode *mode_editor = memnew(EditorPropertyVisualShaderMode);
Vector<String> options = p_hint_text.split(",");
mode_editor->setup(options);
add_property_editor(p_path, mode_editor);
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index b846c34f9e..ede6513b83 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -48,6 +48,7 @@ class TextEdit;
class Tree;
class VisualShaderEditor;
+class EditorUndoRedoManager;
class VisualShaderNodePlugin : public RefCounted {
GDCLASS(VisualShaderNodePlugin, RefCounted);
@@ -192,7 +193,7 @@ class VisualShaderEditor : public VBoxContainer {
PanelContainer *error_panel = nullptr;
Label *error_label = nullptr;
- UndoRedo *undo_redo = nullptr;
+ Ref<EditorUndoRedoManager> undo_redo;
Point2 saved_node_pos;
bool saved_node_pos_dirty = false;
@@ -529,8 +530,8 @@ public:
virtual Control *create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) override;
};
-class EditorPropertyShaderMode : public EditorProperty {
- GDCLASS(EditorPropertyShaderMode, EditorProperty);
+class EditorPropertyVisualShaderMode : public EditorProperty {
+ GDCLASS(EditorPropertyVisualShaderMode, EditorProperty);
OptionButton *options = nullptr;
void _option_selected(int p_which);
@@ -542,11 +543,11 @@ public:
void setup(const Vector<String> &p_options);
virtual void update_property() override;
void set_option_button_clip(bool p_enable);
- EditorPropertyShaderMode();
+ EditorPropertyVisualShaderMode();
};
-class EditorInspectorShaderModePlugin : public EditorInspectorPlugin {
- GDCLASS(EditorInspectorShaderModePlugin, EditorInspectorPlugin);
+class EditorInspectorVisualShaderModePlugin : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorVisualShaderModePlugin, EditorInspectorPlugin);
public:
virtual bool can_handle(Object *p_object) override;