Compare commits
4 Commits
20be87904a
...
e6e1addbcb
Author | SHA1 | Date |
---|---|---|
Alexander Montag | e6e1addbcb | |
Alexander Montag | 8d781da1a6 | |
Alexander Montag | 683834f58e | |
Alexander Montag | 10c8f58ca9 |
|
@ -261,6 +261,10 @@ void LimboAIEditor::edit_bt(const Ref<BehaviorTree> &p_behavior_tree, bool p_for
|
||||||
p_behavior_tree->editor_set_section_unfold("blackboard_plan", true);
|
p_behavior_tree->editor_set_section_unfold("blackboard_plan", true);
|
||||||
p_behavior_tree->notify_property_list_changed();
|
p_behavior_tree->notify_property_list_changed();
|
||||||
#endif // LIMBOAI_MODULE
|
#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);
|
task_tree->load_bt(p_behavior_tree);
|
||||||
|
|
||||||
|
@ -280,6 +284,18 @@ void LimboAIEditor::edit_bt(const Ref<BehaviorTree> &p_behavior_tree, bool p_for
|
||||||
task_tree->show();
|
task_tree->show();
|
||||||
task_palette->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();
|
_update_tabs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1324,7 +1340,7 @@ void LimboAIEditor::_update_misc_menu() {
|
||||||
misc_menu->add_item(
|
misc_menu->add_item(
|
||||||
FILE_EXISTS(_get_script_template_path()) ? TTR("Edit Script Template") : TTR("Create Script Template"),
|
FILE_EXISTS(_get_script_template_path()) ? TTR("Edit Script Template") : TTR("Create Script Template"),
|
||||||
MISC_CREATE_SCRIPT_TEMPLATE);
|
MISC_CREATE_SCRIPT_TEMPLATE);
|
||||||
|
|
||||||
misc_menu->add_separator();
|
misc_menu->add_separator();
|
||||||
misc_menu->add_icon_shortcut(theme_cache.search_icon, LW_GET_SHORTCUT("limbo_ai/find_task"), MISC_SEARCH_TREE);
|
misc_menu->add_icon_shortcut(theme_cache.search_icon, LW_GET_SHORTCUT("limbo_ai/find_task"), MISC_SEARCH_TREE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
|
|
||||||
#ifdef LIMBOAI_GDEXTENSION
|
#ifdef LIMBOAI_GDEXTENSION
|
||||||
#include "godot_cpp/classes/accept_dialog.hpp"
|
#include "godot_cpp/classes/accept_dialog.hpp"
|
||||||
|
#include <godot_cpp/classes/config_file.hpp>
|
||||||
#include <godot_cpp/classes/control.hpp>
|
#include <godot_cpp/classes/control.hpp>
|
||||||
#include <godot_cpp/classes/editor_plugin.hpp>
|
#include <godot_cpp/classes/editor_plugin.hpp>
|
||||||
#include <godot_cpp/classes/editor_spin_slider.hpp>
|
#include <godot_cpp/classes/editor_spin_slider.hpp>
|
||||||
|
@ -64,7 +65,6 @@
|
||||||
#include <godot_cpp/classes/texture2d.hpp>
|
#include <godot_cpp/classes/texture2d.hpp>
|
||||||
#include <godot_cpp/variant/packed_string_array.hpp>
|
#include <godot_cpp/variant/packed_string_array.hpp>
|
||||||
#include <godot_cpp/variant/variant.hpp>
|
#include <godot_cpp/variant/variant.hpp>
|
||||||
#include <godot_cpp/classes/config_file.hpp>
|
|
||||||
|
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
|
||||||
|
@ -143,6 +143,7 @@ private:
|
||||||
EditorLayout editor_layout;
|
EditorLayout editor_layout;
|
||||||
Vector<Ref<BehaviorTree>> history;
|
Vector<Ref<BehaviorTree>> history;
|
||||||
int idx_history;
|
int idx_history;
|
||||||
|
HashMap<Ref<BehaviorTree>, TreeSearch::SearchInfo> tab_search_context;
|
||||||
bool updating_tabs = false;
|
bool updating_tabs = false;
|
||||||
bool request_update_tabs = false;
|
bool request_update_tabs = false;
|
||||||
HashSet<Ref<BehaviorTree>> dirty;
|
HashSet<Ref<BehaviorTree>> dirty;
|
||||||
|
|
|
@ -47,9 +47,9 @@ TreeItem *TaskTree::_create_tree(const Ref<BTTask> &p_task, TreeItem *p_parent,
|
||||||
_create_tree(p_task->get_child(i), item);
|
_create_tree(p_task->get_child(i), item);
|
||||||
}
|
}
|
||||||
_update_item(item);
|
_update_item(item);
|
||||||
|
|
||||||
// update TreeSearch if root task was created
|
// update TreeSearch if root task was created
|
||||||
if (tree->get_root() == item){
|
if (tree->get_root() == item) {
|
||||||
tree_search->update_search(tree);
|
tree_search->update_search(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,7 +546,6 @@ void TaskTree::_notification(int p_what) {
|
||||||
_update_tree();
|
_update_tree();
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskTree::_bind_methods() {
|
void TaskTree::_bind_methods() {
|
||||||
|
@ -573,11 +572,27 @@ void TaskTree::_bind_methods() {
|
||||||
PropertyInfo(Variant::INT, "type")));
|
PropertyInfo(Variant::INT, "type")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TreeSearch API
|
||||||
void TaskTree::tree_search_show_and_focus() {
|
void TaskTree::tree_search_show_and_focus() {
|
||||||
ERR_FAIL_NULL(tree_search);
|
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() {
|
TaskTree::TaskTree() {
|
||||||
editable = true;
|
editable = true;
|
||||||
updating_tree = false;
|
updating_tree = false;
|
||||||
|
|
|
@ -103,13 +103,16 @@ public:
|
||||||
Ref<BTTask> get_selected() const;
|
Ref<BTTask> get_selected() const;
|
||||||
Vector<Ref<BTTask>> get_selected_tasks() const;
|
Vector<Ref<BTTask>> get_selected_tasks() const;
|
||||||
void clear_selection();
|
void clear_selection();
|
||||||
void tree_search_show_and_focus();
|
|
||||||
|
|
||||||
Rect2 get_selected_probability_rect() const;
|
Rect2 get_selected_probability_rect() const;
|
||||||
double get_selected_probability_weight() const;
|
double get_selected_probability_weight() const;
|
||||||
double get_selected_probability_percent() const;
|
double get_selected_probability_percent() const;
|
||||||
bool selected_has_probability() 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; }
|
virtual bool editor_can_reload_from_file() { return false; }
|
||||||
|
|
||||||
TaskTree();
|
TaskTree();
|
||||||
|
|
|
@ -68,10 +68,16 @@ void TreeSearch::_filter_tree(const String &p_search_mask) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeItem *first_counting_ancestor = cur_item;
|
TreeItem *first_counting_ancestor = cur_item;
|
||||||
|
bool parents_visible = true;
|
||||||
while (first_counting_ancestor && !number_matches.has(first_counting_ancestor)) {
|
while (first_counting_ancestor && !number_matches.has(first_counting_ancestor)) {
|
||||||
|
// Performance: we only need to check the first visible ancestor. This is already optimal because of the ordering in ordered_tree_items.
|
||||||
|
if (!first_counting_ancestor->is_visible()){
|
||||||
|
parents_visible = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
first_counting_ancestor = first_counting_ancestor->get_parent();
|
first_counting_ancestor = first_counting_ancestor->get_parent();
|
||||||
}
|
}
|
||||||
if (!first_counting_ancestor || !_vector_has_bsearch(matching_entries, first_counting_ancestor)) {
|
if (!parents_visible || !first_counting_ancestor || !_vector_has_bsearch(matching_entries, first_counting_ancestor)) {
|
||||||
cur_item->set_visible(false);
|
cur_item->set_visible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,10 +389,11 @@ void TreeSearch::_select_next_match() {
|
||||||
_select_first_match();
|
_select_first_match();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeSearch::_on_search_panel_visibility_changed() {
|
void TreeSearch::_on_search_panel_closed() {
|
||||||
if (tree_reference && !search_panel->is_visible()) {
|
if (!tree_reference) {
|
||||||
tree_reference->grab_focus();
|
return;
|
||||||
}
|
}
|
||||||
|
tree_reference->grab_focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -444,8 +451,8 @@ void TreeSearch::update_search(Tree *p_tree) {
|
||||||
|
|
||||||
TreeSearch::TreeSearch(TreeSearchPanel *p_search_panel) {
|
TreeSearch::TreeSearch(TreeSearchPanel *p_search_panel) {
|
||||||
search_panel = p_search_panel;
|
search_panel = p_search_panel;
|
||||||
search_panel->connect("text_submitted", callable_mp(this, &TreeSearch::_select_next_match));
|
search_panel->connect(LW_NAME(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(LW_NAME(Close), callable_mp(this, &TreeSearch::_on_search_panel_closed));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* !TreeSearch */
|
/* !TreeSearch */
|
||||||
|
@ -490,16 +497,16 @@ void TreeSearchPanel::_notification(int p_what) {
|
||||||
switch (p_what) {
|
switch (p_what) {
|
||||||
case NOTIFICATION_READY: {
|
case NOTIFICATION_READY: {
|
||||||
// close callbacks
|
// close callbacks
|
||||||
close_button->connect("pressed", Callable(this, "set_visible").bind(false));
|
close_button->connect(LW_NAME(pressed), Callable(this, LW_NAME(set_visible)).bind(false));
|
||||||
|
close_button->connect(LW_NAME(pressed), Callable(this, LW_NAME(emit_signal)).bind(LW_NAME(Close)));
|
||||||
close_button->set_shortcut(LW_GET_SHORTCUT("limbo_ai/hide_tree_search"));
|
close_button->set_shortcut(LW_GET_SHORTCUT("limbo_ai/hide_tree_search"));
|
||||||
|
|
||||||
// search callbacks
|
// search callbacks
|
||||||
Callable c_update_requested = Callable(this, "emit_signal").bind("update_requested");
|
Callable c_update_requested = Callable(this, LW_NAME(emit_signal)).bind("update_requested");
|
||||||
Callable c_text_submitted = Callable((Object *)this, "emit_signal").bind("text_submitted");
|
Callable c_text_submitted = Callable((Object *)this, LW_NAME(emit_signal)).bind(LW_NAME(text_submitted));
|
||||||
|
|
||||||
line_edit_search->connect("text_changed", c_update_requested.unbind(1));
|
line_edit_search->connect(LW_NAME(text_changed), c_update_requested.unbind(1));
|
||||||
check_button_filter_highlight->connect("pressed", c_update_requested);
|
check_button_filter_highlight->connect(LW_NAME(pressed), c_update_requested);
|
||||||
line_edit_search->connect("text_submitted", c_text_submitted.unbind(1));
|
line_edit_search->connect(LW_NAME(text_submitted), c_text_submitted.unbind(1));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NOTIFICATION_THEME_CHANGED: {
|
case NOTIFICATION_THEME_CHANGED: {
|
||||||
|
@ -512,7 +519,8 @@ void TreeSearchPanel::_notification(int p_what) {
|
||||||
|
|
||||||
void TreeSearchPanel::_bind_methods() {
|
void TreeSearchPanel::_bind_methods() {
|
||||||
ADD_SIGNAL(MethodInfo("update_requested"));
|
ADD_SIGNAL(MethodInfo("update_requested"));
|
||||||
ADD_SIGNAL(MethodInfo("text_submitted"));
|
ADD_SIGNAL(MethodInfo(LW_NAME(text_submitted)));
|
||||||
|
ADD_SIGNAL(MethodInfo(LW_NAME(Close)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeSearchPanel::TreeSearchPanel() {
|
TreeSearchPanel::TreeSearchPanel() {
|
||||||
|
@ -534,8 +542,22 @@ String TreeSearchPanel::get_text() const {
|
||||||
return line_edit_search->get_text();
|
return line_edit_search->get_text();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeSearchPanel::show_and_focus() {
|
TreeSearch::SearchInfo TreeSearchPanel::get_search_info() const {
|
||||||
set_visible(true);
|
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(const 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::focus_editor() {
|
||||||
line_edit_search->grab_focus();
|
line_edit_search->grab_focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ private:
|
||||||
void _select_first_match();
|
void _select_first_match();
|
||||||
void _select_next_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
|
// TODO: make p_vec ref `const` once Vector::bsearch is const. See: https://github.com/godotengine/godot/pull/90341
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -105,6 +105,12 @@ public:
|
||||||
FILTER = 1
|
FILTER = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SearchInfo {
|
||||||
|
String search_mask;
|
||||||
|
TreeSearchMode search_mode;
|
||||||
|
bool visible;
|
||||||
|
};
|
||||||
|
|
||||||
void update_search(Tree *p_tree);
|
void update_search(Tree *p_tree);
|
||||||
void notify_item_edited(TreeItem *p_item);
|
void notify_item_edited(TreeItem *p_item);
|
||||||
|
|
||||||
|
@ -132,9 +138,11 @@ protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TreeSearch::TreeSearchMode get_search_mode() const;
|
|
||||||
String get_text() const;
|
String get_text() const;
|
||||||
void show_and_focus();
|
TreeSearch::TreeSearchMode get_search_mode() const;
|
||||||
|
TreeSearch::SearchInfo get_search_info() const;
|
||||||
|
void set_search_info(const TreeSearch::SearchInfo &p_search_info);
|
||||||
|
void focus_editor();
|
||||||
TreeSearchPanel();
|
TreeSearchPanel();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ LimboStringNames::LimboStringNames() {
|
||||||
EditorFonts = SN("EditorFonts");
|
EditorFonts = SN("EditorFonts");
|
||||||
EditorIcons = SN("EditorIcons");
|
EditorIcons = SN("EditorIcons");
|
||||||
EditorStyles = SN("EditorStyles");
|
EditorStyles = SN("EditorStyles");
|
||||||
|
emit_signal = SN("emit_signal");
|
||||||
entered = SN("entered");
|
entered = SN("entered");
|
||||||
error_value = SN("error_value");
|
error_value = SN("error_value");
|
||||||
EVENT_FAILURE = SN("failure");
|
EVENT_FAILURE = SN("failure");
|
||||||
|
@ -124,6 +125,7 @@ LimboStringNames::LimboStringNames() {
|
||||||
separation = SN("separation");
|
separation = SN("separation");
|
||||||
set_custom_name = SN("set_custom_name");
|
set_custom_name = SN("set_custom_name");
|
||||||
set_root_task = SN("set_root_task");
|
set_root_task = SN("set_root_task");
|
||||||
|
set_visible = SN("set_visible");
|
||||||
set_v_scroll = SN("set_v_scroll");
|
set_v_scroll = SN("set_v_scroll");
|
||||||
setup = SN("setup");
|
setup = SN("setup");
|
||||||
started = SN("started");
|
started = SN("started");
|
||||||
|
|
|
@ -75,6 +75,7 @@ public:
|
||||||
StringName EditorFonts;
|
StringName EditorFonts;
|
||||||
StringName EditorIcons;
|
StringName EditorIcons;
|
||||||
StringName EditorStyles;
|
StringName EditorStyles;
|
||||||
|
StringName emit_signal;
|
||||||
StringName entered;
|
StringName entered;
|
||||||
StringName error_value;
|
StringName error_value;
|
||||||
StringName EVENT_FAILURE;
|
StringName EVENT_FAILURE;
|
||||||
|
@ -140,6 +141,7 @@ public:
|
||||||
StringName separation;
|
StringName separation;
|
||||||
StringName set_custom_name;
|
StringName set_custom_name;
|
||||||
StringName set_root_task;
|
StringName set_root_task;
|
||||||
|
StringName set_visible;
|
||||||
StringName set_v_scroll;
|
StringName set_v_scroll;
|
||||||
StringName setup;
|
StringName setup;
|
||||||
StringName started;
|
StringName started;
|
||||||
|
|
Loading…
Reference in New Issue