From c94ec7613d2f18b75a491ca5157cceb34607e91d Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 21 Aug 2024 15:23:27 +0200 Subject: [PATCH] Add hack to associate undo-redo actions with global history --- editor/limbo_ai_editor_plugin.cpp | 48 +++++++++++++++++-------------- editor/limbo_ai_editor_plugin.h | 13 +++++---- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/editor/limbo_ai_editor_plugin.cpp b/editor/limbo_ai_editor_plugin.cpp index 403d710..0a546b4 100644 --- a/editor/limbo_ai_editor_plugin.cpp +++ b/editor/limbo_ai_editor_plugin.cpp @@ -37,7 +37,6 @@ #include "editor/editor_interface.h" #include "editor/editor_paths.h" #include "editor/editor_settings.h" -#include "editor/editor_undo_redo_manager.h" #include "editor/filesystem_dock.h" #include "editor/gui/editor_bottom_panel.h" #include "editor/inspector_dock.h" @@ -58,7 +57,6 @@ #include #include #include -#include #include #include #include @@ -82,14 +80,25 @@ _FORCE_INLINE_ String _get_script_template_path() { return templates_search_path.path_join("BTTask").path_join("custom_task.gd"); } +EditorUndoRedoManager *LimboAIEditor::_new_undo_redo_action(const String &p_name, UndoRedo::MergeMode p_mode) { +#ifdef LIMBOAI_MODULE + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); +#elif LIMBOAI_GDEXTENSION + EditorUndoRedoManager *undo_redo = plugin->get_undo_redo(); +#endif + // ! HACK: Force global history to be used for resources without a set path. + undo_redo->create_action(p_name, p_mode, dummy_history_context); + undo_redo->force_fixed_history(); + return undo_redo; +} + void LimboAIEditor::_add_task(const Ref &p_task, bool p_as_sibling) { if (task_tree->get_bt().is_null()) { return; } ERR_FAIL_COND(p_task.is_null()); - EditorUndoRedoManager *undo_redo = GET_UNDO_REDO(); - undo_redo->create_action(TTR("Add BT Task")); + EditorUndoRedoManager *undo_redo = _new_undo_redo_action(TTR("Add BT Task")); int insert_idx = -1; Ref selected = task_tree->get_selected(); @@ -169,8 +178,7 @@ void LimboAIEditor::_add_task_by_class_or_path(const String &p_class_or_path) { void LimboAIEditor::_remove_task(const Ref &p_task) { ERR_FAIL_COND(p_task.is_null()); ERR_FAIL_COND(task_tree->get_bt().is_null()); - EditorUndoRedoManager *undo_redo = GET_UNDO_REDO(); - undo_redo->create_action(TTR("Remove BT Task")); + EditorUndoRedoManager *undo_redo = _new_undo_redo_action(TTR("Remove BT Task")); if (p_task->get_parent() == nullptr) { ERR_FAIL_COND(task_tree->get_bt()->get_root_task() != p_task); undo_redo->add_do_method(task_tree->get_bt().ptr(), LW_NAME(set_root_task), Variant()); @@ -226,7 +234,7 @@ void LimboAIEditor::_disable_editing() { usage_hint->show(); } -void LimboAIEditor::edit_bt(Ref p_behavior_tree, bool p_force_refresh) { +void LimboAIEditor::edit_bt(const Ref &p_behavior_tree, bool p_force_refresh) { ERR_FAIL_COND_MSG(p_behavior_tree.is_null(), "p_behavior_tree is null"); if (!p_force_refresh && task_tree->get_bt() == p_behavior_tree) { @@ -327,8 +335,7 @@ void LimboAIEditor::_extract_subtree(const String &p_path) { Ref selected = task_tree->get_selected(); ERR_FAIL_COND(selected.is_null()); - EditorUndoRedoManager *undo_redo = GET_UNDO_REDO(); - undo_redo->create_action(TTR("Extract Subtree")); + EditorUndoRedoManager *undo_redo = _new_undo_redo_action(TTR("Extract Subtree")); Ref bt = memnew(BehaviorTree); bt->set_root_task(selected->clone()); @@ -459,7 +466,6 @@ void LimboAIEditor::_on_tree_rmb(const Vector2 &p_menu_pos) { } void LimboAIEditor::_action_selected(int p_id) { - EditorUndoRedoManager *undo_redo = GET_UNDO_REDO(); switch (p_id) { case ACTION_RENAME: { if (!task_tree->get_selected().is_valid()) { @@ -537,7 +543,7 @@ void LimboAIEditor::_action_selected(int p_id) { Ref parent = sel->get_parent(); int idx = sel->get_index(); if (idx > 0 && idx < parent->get_child_count()) { - undo_redo->create_action(TTR("Move BT Task")); + EditorUndoRedoManager *undo_redo = _new_undo_redo_action(TTR("Move BT Task")); undo_redo->add_do_method(parent.ptr(), LW_NAME(remove_child), sel); undo_redo->add_do_method(parent.ptr(), LW_NAME(add_child_at_index), sel, idx - 1); undo_redo->add_undo_method(parent.ptr(), LW_NAME(remove_child), sel); @@ -555,7 +561,7 @@ void LimboAIEditor::_action_selected(int p_id) { Ref parent = sel->get_parent(); int idx = sel->get_index(); if (idx >= 0 && idx < (parent->get_child_count() - 1)) { - undo_redo->create_action(TTR("Move BT Task")); + EditorUndoRedoManager *undo_redo = _new_undo_redo_action(TTR("Move BT Task")); undo_redo->add_do_method(parent.ptr(), LW_NAME(remove_child), sel); undo_redo->add_do_method(parent.ptr(), LW_NAME(add_child_at_index), sel, idx + 1); undo_redo->add_undo_method(parent.ptr(), LW_NAME(remove_child), sel); @@ -570,7 +576,7 @@ void LimboAIEditor::_action_selected(int p_id) { case ACTION_DUPLICATE: { Ref sel = task_tree->get_selected(); if (sel.is_valid()) { - undo_redo->create_action(TTR("Duplicate BT Task")); + EditorUndoRedoManager *undo_redo = _new_undo_redo_action(TTR("Duplicate BT Task")); Ref parent = sel->get_parent(); if (parent.is_null()) { parent = sel; @@ -589,7 +595,7 @@ void LimboAIEditor::_action_selected(int p_id) { if (sel.is_valid() && task_tree->get_bt()->get_root_task() != sel) { Ref parent = sel->get_parent(); ERR_FAIL_COND(parent.is_null()); - undo_redo->create_action(TTR("Make Root")); + EditorUndoRedoManager *undo_redo = _new_undo_redo_action(TTR("Make Root")); undo_redo->add_do_method(parent.ptr(), LW_NAME(remove_child), sel); Ref old_root = task_tree->get_bt()->get_root_task(); undo_redo->add_do_method(task_tree->get_bt().ptr(), LW_NAME(set_root_task), sel); @@ -616,8 +622,7 @@ void LimboAIEditor::_action_selected(int p_id) { if (p_id == ACTION_CUT) { clipboard_task = sel->clone(); } - - undo_redo->create_action(TTR("Remove BT Task")); + EditorUndoRedoManager *undo_redo = _new_undo_redo_action(TTR("Remove BT Task")); if (sel->is_root()) { undo_redo->add_do_method(task_tree->get_bt().ptr(), LW_NAME(set_root_task), Variant()); undo_redo->add_undo_method(task_tree->get_bt().ptr(), LW_NAME(set_root_task), task_tree->get_bt()->get_root_task()); @@ -848,8 +853,7 @@ void LimboAIEditor::_on_task_dragged(Ref p_task, Ref p_to_task, return; } - EditorUndoRedoManager *undo_redo = GET_UNDO_REDO(); - undo_redo->create_action(TTR("Drag BT Task")); + EditorUndoRedoManager *undo_redo = _new_undo_redo_action(TTR("Drag BT Task")); undo_redo->add_do_method(p_task->get_parent().ptr(), LW_NAME(remove_child), p_task); if (p_type == 0) { @@ -943,8 +947,7 @@ void LimboAIEditor::_task_type_selected(const String &p_class_or_path) { Ref new_task = _create_task_by_class_or_path(p_class_or_path); ERR_FAIL_COND_MSG(new_task.is_null(), "LimboAI: Unable to construct task."); - EditorUndoRedoManager *undo_redo = GET_UNDO_REDO(); - undo_redo->create_action(TTR("Change BT task type")); + EditorUndoRedoManager *undo_redo = _new_undo_redo_action(TTR("Change BT task type")); undo_redo->add_do_method(this, LW_NAME(_replace_task), selected_task, new_task); undo_redo->add_undo_method(this, LW_NAME(_replace_task), new_task, selected_task); undo_redo->add_do_method(task_tree, LW_NAME(update_tree)); @@ -1198,8 +1201,7 @@ void LimboAIEditor::_rename_task_confirmed() { ERR_FAIL_COND(!task_tree->get_selected().is_valid()); rename_dialog->hide(); - EditorUndoRedoManager *undo_redo = GET_UNDO_REDO(); - undo_redo->create_action(TTR("Set Custom Name")); + EditorUndoRedoManager *undo_redo = _new_undo_redo_action(TTR("Set Custom Name")); undo_redo->add_do_method(task_tree->get_selected().ptr(), LW_NAME(set_custom_name), rename_edit->get_text()); undo_redo->add_undo_method(task_tree->get_selected().ptr(), LW_NAME(set_custom_name), task_tree->get_selected()->get_custom_name()); undo_redo->add_do_method(task_tree, LW_NAME(update_task), task_tree->get_selected()); @@ -1462,6 +1464,7 @@ void LimboAIEditor::_bind_methods() { LimboAIEditor::LimboAIEditor() { plugin = nullptr; idx_history = 0; + dummy_history_context = memnew(Object); EDITOR_DEF("limbo_ai/editor/prefer_online_documentation", false); @@ -1795,6 +1798,7 @@ LimboAIEditor::LimboAIEditor() { } LimboAIEditor::~LimboAIEditor() { + memdelete(dummy_history_context); } //**** LimboAIEditor ^ diff --git a/editor/limbo_ai_editor_plugin.h b/editor/limbo_ai_editor_plugin.h index 0b9f337..85238fc 100644 --- a/editor/limbo_ai_editor_plugin.h +++ b/editor/limbo_ai_editor_plugin.h @@ -26,6 +26,7 @@ #include "core/object/object.h" #include "core/templates/hash_set.h" #include "editor/editor_node.h" +#include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_spin_slider.h" #include "editor/plugins/editor_plugin.h" #include "scene/gui/box_container.h" @@ -42,9 +43,6 @@ #include "scene/gui/split_container.h" #include "scene/gui/tree.h" #include "scene/resources/texture.h" - -#define GET_UNDO_REDO() EditorUndoRedoManager::get_singleton() - #endif // LIMBOAI_MODULE #ifdef LIMBOAI_GDEXTENSION @@ -52,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -67,8 +66,6 @@ using namespace godot; -#define GET_UNDO_REDO() plugin->get_undo_redo() - #endif // LIMBOAI_GDEXTENSION class LimboAIEditor : public Control { @@ -189,6 +186,10 @@ private: AcceptDialog *info_dialog; + // ! HACK: Force global history to be used for resources without a set path. + Object *dummy_history_context = nullptr; + EditorUndoRedoManager *_new_undo_redo_action(const String &p_name = "", UndoRedo::MergeMode p_mode = UndoRedo::MERGE_DISABLE); + void _add_task(const Ref &p_task, bool p_as_sibling); void _add_task_with_prototype(const Ref &p_prototype); Ref _create_task_by_class_or_path(const String &p_class_or_path) const; @@ -258,7 +259,7 @@ protected: public: void set_plugin(EditorPlugin *p_plugin) { plugin = p_plugin; }; - void edit_bt(Ref p_behavior_tree, bool p_force_refresh = false); + void edit_bt(const Ref &p_behavior_tree, bool p_force_refresh = false); Ref get_edited_blackboard_plan(); void apply_changes();