diff --git a/editor/limbo_ai_editor_plugin.cpp b/editor/limbo_ai_editor_plugin.cpp index 57becb6..648f89a 100644 --- a/editor/limbo_ai_editor_plugin.cpp +++ b/editor/limbo_ai_editor_plugin.cpp @@ -261,6 +261,10 @@ void LimboAIEditor::edit_bt(const Ref &p_behavior_tree, bool p_for p_behavior_tree->editor_set_section_unfold("blackboard_plan", true); p_behavior_tree->notify_property_list_changed(); #endif // LIMBOAI_MODULE + // Remember current search info. + if (idx_history >= 0 && idx_history < history.size()) { + tab_search_context.insert(history[idx_history], task_tree->tree_search_get_search_info()); + } task_tree->load_bt(p_behavior_tree); @@ -280,6 +284,18 @@ void LimboAIEditor::edit_bt(const Ref &p_behavior_tree, bool p_for task_tree->show(); task_palette->show(); + // Restore search info from [tab_search_context]. + if (idx_history >= 0 && idx_history < history.size()) { + // info for BehaviorTree available. Restore! + if (tab_search_context.has(history[idx_history])) { + task_tree->tree_search_set_search_info(tab_search_context[history[idx_history]]); + } + // new SearchContext. + else { + task_tree->tree_search_set_search_info(TreeSearch::SearchInfo()); + } + } + _update_tabs(); } @@ -1324,7 +1340,7 @@ void LimboAIEditor::_update_misc_menu() { misc_menu->add_item( FILE_EXISTS(_get_script_template_path()) ? TTR("Edit Script Template") : TTR("Create Script Template"), MISC_CREATE_SCRIPT_TEMPLATE); - + misc_menu->add_separator(); misc_menu->add_icon_shortcut(theme_cache.search_icon, LW_GET_SHORTCUT("limbo_ai/find_task"), MISC_SEARCH_TREE); } diff --git a/editor/limbo_ai_editor_plugin.h b/editor/limbo_ai_editor_plugin.h index 1868175..42e2839 100644 --- a/editor/limbo_ai_editor_plugin.h +++ b/editor/limbo_ai_editor_plugin.h @@ -48,6 +48,7 @@ #ifdef LIMBOAI_GDEXTENSION #include "godot_cpp/classes/accept_dialog.hpp" +#include #include #include #include @@ -64,7 +65,6 @@ #include #include #include -#include using namespace godot; @@ -143,6 +143,7 @@ private: EditorLayout editor_layout; Vector> history; int idx_history; + HashMap, TreeSearch::SearchInfo> tab_search_context; bool updating_tabs = false; bool request_update_tabs = false; HashSet> dirty; diff --git a/editor/task_tree.cpp b/editor/task_tree.cpp index a976ca0..efd57b2 100644 --- a/editor/task_tree.cpp +++ b/editor/task_tree.cpp @@ -47,9 +47,9 @@ TreeItem *TaskTree::_create_tree(const Ref &p_task, TreeItem *p_parent, _create_tree(p_task->get_child(i), item); } _update_item(item); - + // update TreeSearch if root task was created - if (tree->get_root() == item){ + if (tree->get_root() == item) { tree_search->update_search(tree); } @@ -546,7 +546,6 @@ void TaskTree::_notification(int p_what) { _update_tree(); } break; } - } void TaskTree::_bind_methods() { @@ -573,11 +572,27 @@ void TaskTree::_bind_methods() { PropertyInfo(Variant::INT, "type"))); } +// TreeSearch API void TaskTree::tree_search_show_and_focus() { ERR_FAIL_NULL(tree_search); - tree_search_panel->show_and_focus(); + tree_search_panel->set_visible(true); + tree_search_panel->focus_editor(); } +TreeSearch::SearchInfo TaskTree::tree_search_get_search_info() const { + if (!tree_search.is_valid()) { + return TreeSearch::SearchInfo(); + } + return tree_search_panel->get_search_info(); +} + +void TaskTree::tree_search_set_search_info(const TreeSearch::SearchInfo &p_search_info) { + ERR_FAIL_NULL(tree_search); + tree_search_panel->set_search_info(p_search_info); +} + +// TreeSearch Api ^ + TaskTree::TaskTree() { editable = true; updating_tree = false; diff --git a/editor/task_tree.h b/editor/task_tree.h index 2373e7f..efb7241 100644 --- a/editor/task_tree.h +++ b/editor/task_tree.h @@ -103,13 +103,16 @@ public: Ref get_selected() const; Vector> get_selected_tasks() const; void clear_selection(); - void tree_search_show_and_focus(); - Rect2 get_selected_probability_rect() const; double get_selected_probability_weight() const; double get_selected_probability_percent() const; bool selected_has_probability() const; + // TreeSearch API + void tree_search_show_and_focus(); + TreeSearch::SearchInfo tree_search_get_search_info() const; + void tree_search_set_search_info(const TreeSearch::SearchInfo &p_search_info); + virtual bool editor_can_reload_from_file() { return false; } TaskTree(); diff --git a/editor/tree_search.cpp b/editor/tree_search.cpp index 160c614..70959b3 100644 --- a/editor/tree_search.cpp +++ b/editor/tree_search.cpp @@ -383,10 +383,11 @@ void TreeSearch::_select_next_match() { _select_first_match(); } -void TreeSearch::_on_search_panel_visibility_changed() { - if (tree_reference && !search_panel->is_visible()) { - tree_reference->grab_focus(); +void TreeSearch::_on_search_panel_closed() { + if (!tree_reference) { + return; } + tree_reference->grab_focus(); } template @@ -445,7 +446,7 @@ void TreeSearch::update_search(Tree *p_tree) { TreeSearch::TreeSearch(TreeSearchPanel *p_search_panel) { search_panel = p_search_panel; search_panel->connect("text_submitted", callable_mp(this, &TreeSearch::_select_next_match)); - search_panel->connect("visibility_changed", callable_mp(this, &TreeSearch::_on_search_panel_visibility_changed)); + search_panel->connect("closed", callable_mp(this, &TreeSearch::_on_search_panel_closed)); } /* !TreeSearch */ @@ -491,8 +492,8 @@ void TreeSearchPanel::_notification(int p_what) { case NOTIFICATION_READY: { // close callbacks close_button->connect("pressed", Callable(this, "set_visible").bind(false)); + close_button->connect("pressed", Callable(this, "emit_signal").bind("closed")); close_button->set_shortcut(LW_GET_SHORTCUT("limbo_ai/hide_tree_search")); - // search callbacks Callable c_update_requested = Callable(this, "emit_signal").bind("update_requested"); Callable c_text_submitted = Callable((Object *)this, "emit_signal").bind("text_submitted"); @@ -513,6 +514,7 @@ void TreeSearchPanel::_notification(int p_what) { void TreeSearchPanel::_bind_methods() { ADD_SIGNAL(MethodInfo("update_requested")); ADD_SIGNAL(MethodInfo("text_submitted")); + ADD_SIGNAL(MethodInfo("closed")); } TreeSearchPanel::TreeSearchPanel() { @@ -534,8 +536,26 @@ String TreeSearchPanel::get_text() const { return line_edit_search->get_text(); } -void TreeSearchPanel::show_and_focus() { - set_visible(true); +TreeSearch::SearchInfo TreeSearchPanel::get_search_info() const { + TreeSearch::SearchInfo result; + result.search_mask = get_text(); + result.search_mode = get_search_mode(); + result.visible = is_visible(); + return result; +} + +void TreeSearchPanel::set_search_info(TreeSearch::SearchInfo p_search_info) { + line_edit_search->set_text(p_search_info.search_mask); + check_button_filter_highlight->set_pressed(p_search_info.search_mode == TreeSearch::TreeSearchMode::FILTER); + set_visible(p_search_info.visible); + emit_signal("update_requested"); +} + +void TreeSearchPanel::set_text(const String &p_text) { + line_edit_search->set_text(p_text); +} + +void TreeSearchPanel::focus_editor() { line_edit_search->grab_focus(); } diff --git a/editor/tree_search.h b/editor/tree_search.h index 2b7cf63..917be16 100644 --- a/editor/tree_search.h +++ b/editor/tree_search.h @@ -90,7 +90,7 @@ private: void _select_first_match(); void _select_next_match(); - void _on_search_panel_visibility_changed(); + void _on_search_panel_closed(); // TODO: make p_vec ref `const` once Vector::bsearch is const. See: https://github.com/godotengine/godot/pull/90341 template @@ -105,6 +105,12 @@ public: FILTER = 1 }; + struct SearchInfo { + String search_mask; + TreeSearchMode search_mode; + bool visible; + }; + void update_search(Tree *p_tree); void notify_item_edited(TreeItem *p_item); @@ -134,7 +140,10 @@ protected: public: TreeSearch::TreeSearchMode get_search_mode() const; String get_text() const; - void show_and_focus(); + TreeSearch::SearchInfo get_search_info() const; + void set_search_info(TreeSearch::SearchInfo p_search_info); + void set_text(const String &p_text); + void focus_editor(); TreeSearchPanel(); };