Add ui for Tree search
This commit is contained in:
parent
134bb3214a
commit
7c4a462a69
|
@ -799,6 +799,9 @@ void LimboAIEditor::_misc_option_selected(int p_id) {
|
||||||
EDITOR_FILE_SYSTEM()->scan();
|
EDITOR_FILE_SYSTEM()->scan();
|
||||||
EDIT_SCRIPT(template_path);
|
EDIT_SCRIPT(template_path);
|
||||||
} break;
|
} break;
|
||||||
|
case MISC_SEARCH_TREE: {
|
||||||
|
UtilityFunctions::print("Search Tree");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1319,6 +1322,9 @@ 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_icon_item(theme_cache.search_icon, ("Search Tree"), MISC_SEARCH_TREE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimboAIEditor::_update_banners() {
|
void LimboAIEditor::_update_banners() {
|
||||||
|
@ -1381,6 +1387,7 @@ void LimboAIEditor::_do_update_theme_item_cache() {
|
||||||
theme_cache.cut_icon = get_theme_icon(LW_NAME(ActionCut), LW_NAME(EditorIcons));
|
theme_cache.cut_icon = get_theme_icon(LW_NAME(ActionCut), LW_NAME(EditorIcons));
|
||||||
theme_cache.copy_icon = get_theme_icon(LW_NAME(ActionCopy), LW_NAME(EditorIcons));
|
theme_cache.copy_icon = get_theme_icon(LW_NAME(ActionCopy), LW_NAME(EditorIcons));
|
||||||
theme_cache.paste_icon = get_theme_icon(LW_NAME(ActionPaste), LW_NAME(EditorIcons));
|
theme_cache.paste_icon = get_theme_icon(LW_NAME(ActionPaste), LW_NAME(EditorIcons));
|
||||||
|
theme_cache.search_icon = get_theme_icon(LW_NAME(Search), LW_NAME(EditorIcons));
|
||||||
|
|
||||||
theme_cache.behavior_tree_icon = LimboUtility::get_singleton()->get_task_icon("BehaviorTree");
|
theme_cache.behavior_tree_icon = LimboUtility::get_singleton()->get_task_icon("BehaviorTree");
|
||||||
theme_cache.percent_icon = LimboUtility::get_singleton()->get_task_icon("LimboPercent");
|
theme_cache.percent_icon = LimboUtility::get_singleton()->get_task_icon("LimboPercent");
|
||||||
|
@ -1512,6 +1519,7 @@ LimboAIEditor::LimboAIEditor() {
|
||||||
LW_SHORTCUT("limbo_ai/open_debugger", TTR("Open Debugger"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY_MASK(ALT) | LW_KEY(D)));
|
LW_SHORTCUT("limbo_ai/open_debugger", TTR("Open Debugger"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY_MASK(ALT) | LW_KEY(D)));
|
||||||
LW_SHORTCUT("limbo_ai/jump_to_owner", TTR("Jump to Owner"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(J)));
|
LW_SHORTCUT("limbo_ai/jump_to_owner", TTR("Jump to Owner"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(J)));
|
||||||
LW_SHORTCUT("limbo_ai/close_tab", TTR("Close Tab"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(W)));
|
LW_SHORTCUT("limbo_ai/close_tab", TTR("Close Tab"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(W)));
|
||||||
|
LW_SHORTCUT("limbo_ai/find_task", TTR("Find Task"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(F)));
|
||||||
|
|
||||||
set_process_shortcut_input(true);
|
set_process_shortcut_input(true);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "owner_picker.h"
|
#include "owner_picker.h"
|
||||||
#include "task_palette.h"
|
#include "task_palette.h"
|
||||||
#include "task_tree.h"
|
#include "task_tree.h"
|
||||||
|
#include "tree_search.h"
|
||||||
|
|
||||||
#ifdef LIMBOAI_MODULE
|
#ifdef LIMBOAI_MODULE
|
||||||
#include "core/object/class_db.h"
|
#include "core/object/class_db.h"
|
||||||
|
@ -100,6 +101,7 @@ private:
|
||||||
MISC_LAYOUT_WIDESCREEN_OPTIMIZED,
|
MISC_LAYOUT_WIDESCREEN_OPTIMIZED,
|
||||||
MISC_PROJECT_SETTINGS,
|
MISC_PROJECT_SETTINGS,
|
||||||
MISC_CREATE_SCRIPT_TEMPLATE,
|
MISC_CREATE_SCRIPT_TEMPLATE,
|
||||||
|
MISC_SEARCH_TREE
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TabMenu {
|
enum TabMenu {
|
||||||
|
@ -134,6 +136,7 @@ private:
|
||||||
Ref<Texture2D> cut_icon;
|
Ref<Texture2D> cut_icon;
|
||||||
Ref<Texture2D> copy_icon;
|
Ref<Texture2D> copy_icon;
|
||||||
Ref<Texture2D> paste_icon;
|
Ref<Texture2D> paste_icon;
|
||||||
|
Ref<Texture2D> search_icon;
|
||||||
} theme_cache;
|
} theme_cache;
|
||||||
|
|
||||||
EditorPlugin *plugin;
|
EditorPlugin *plugin;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "../bt/tasks/composites/bt_probability_selector.h"
|
#include "../bt/tasks/composites/bt_probability_selector.h"
|
||||||
#include "../util/limbo_compat.h"
|
#include "../util/limbo_compat.h"
|
||||||
#include "../util/limbo_utility.h"
|
#include "../util/limbo_utility.h"
|
||||||
|
#include "tree_search.h"
|
||||||
|
|
||||||
#ifdef LIMBOAI_MODULE
|
#ifdef LIMBOAI_MODULE
|
||||||
#include "core/object/script_language.h"
|
#include "core/object/script_language.h"
|
||||||
|
@ -124,6 +125,7 @@ void TaskTree::_update_tree() {
|
||||||
for (const Ref<BTTask> &task : selection) {
|
for (const Ref<BTTask> &task : selection) {
|
||||||
add_selection(task);
|
add_selection(task);
|
||||||
}
|
}
|
||||||
|
tree_search.apply_search(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeItem *TaskTree::_find_item(const Ref<BTTask> &p_task) const {
|
TreeItem *TaskTree::_find_item(const Ref<BTTask> &p_task) const {
|
||||||
|
@ -566,8 +568,15 @@ TaskTree::TaskTree() {
|
||||||
editable = true;
|
editable = true;
|
||||||
updating_tree = false;
|
updating_tree = false;
|
||||||
|
|
||||||
|
// for Tree + TreeSearch, we want a VBoxContainer. For now, rather than changing this classes type, let's do nesting:
|
||||||
|
// TaskTree -> VBoxContainer -> [Tree, TreeSearchPanel]
|
||||||
|
VBoxContainer * vbox_container = memnew(VBoxContainer);
|
||||||
|
add_child(vbox_container);
|
||||||
|
vbox_container->set_anchors_preset(PRESET_FULL_RECT);
|
||||||
|
|
||||||
tree = memnew(Tree);
|
tree = memnew(Tree);
|
||||||
add_child(tree);
|
tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
|
vbox_container->add_child(tree);
|
||||||
tree->set_columns(2);
|
tree->set_columns(2);
|
||||||
tree->set_column_expand(0, true);
|
tree->set_column_expand(0, true);
|
||||||
tree->set_column_expand(1, false);
|
tree->set_column_expand(1, false);
|
||||||
|
@ -578,6 +587,7 @@ TaskTree::TaskTree() {
|
||||||
tree->set_select_mode(Tree::SelectMode::SELECT_MULTI);
|
tree->set_select_mode(Tree::SelectMode::SELECT_MULTI);
|
||||||
|
|
||||||
tree->set_drag_forwarding(callable_mp(this, &TaskTree::_get_drag_data_fw), callable_mp(this, &TaskTree::_can_drop_data_fw), callable_mp(this, &TaskTree::_drop_data_fw));
|
tree->set_drag_forwarding(callable_mp(this, &TaskTree::_get_drag_data_fw), callable_mp(this, &TaskTree::_can_drop_data_fw), callable_mp(this, &TaskTree::_drop_data_fw));
|
||||||
|
vbox_container->add_child(tree_search.search_panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskTree::~TaskTree() {
|
TaskTree::~TaskTree() {
|
||||||
|
|
|
@ -9,9 +9,13 @@
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef TASK_TREE_H
|
||||||
|
#define TASK_TREE_H
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
|
|
||||||
#include "../bt/behavior_tree.h"
|
#include "../bt/behavior_tree.h"
|
||||||
|
#include "tree_search.h"
|
||||||
|
|
||||||
#ifdef LIMBOAI_MODULE
|
#ifdef LIMBOAI_MODULE
|
||||||
#include "scene/gui/control.h"
|
#include "scene/gui/control.h"
|
||||||
|
@ -42,6 +46,7 @@ private:
|
||||||
bool editable;
|
bool editable;
|
||||||
bool updating_tree;
|
bool updating_tree;
|
||||||
HashMap<RECT_CACHE_KEY, Rect2> probability_rect_cache;
|
HashMap<RECT_CACHE_KEY, Rect2> probability_rect_cache;
|
||||||
|
TreeSearch tree_search;
|
||||||
|
|
||||||
struct ThemeCache {
|
struct ThemeCache {
|
||||||
Ref<Font> comment_font;
|
Ref<Font> comment_font;
|
||||||
|
@ -109,3 +114,4 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ! TOOLS_ENABLED
|
#endif // ! TOOLS_ENABLED
|
||||||
|
#endif // ! TASK_TREE_H
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/**
|
||||||
|
* tree_search.cpp
|
||||||
|
* =============================================================================
|
||||||
|
* Copyright 2021-2024 Serhii Snitsaruk
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style
|
||||||
|
* license that can be found in the LICENSE file or at
|
||||||
|
* https://opensource.org/licenses/MIT.
|
||||||
|
* =============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tree_search.h"
|
||||||
|
|
||||||
|
#include "../util/limbo_compat.h" // for edge scale
|
||||||
|
#include "../util/limbo_string_names.h"
|
||||||
|
#include "../util/limbo_utility.h"
|
||||||
|
#include <godot_cpp/classes/h_separator.hpp>
|
||||||
|
#include <godot_cpp/classes/editor_interface.hpp> // for edge scale
|
||||||
|
#include <godot_cpp/templates/vector.hpp>
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
|
||||||
|
/* ------- TreeSearchPanel ------- */
|
||||||
|
|
||||||
|
void TreeSearchPanel::_initialize_controls() {
|
||||||
|
line_edit_search = memnew(LineEdit);
|
||||||
|
check_button_filter_highlight = memnew(CheckButton);
|
||||||
|
close_button = memnew(Button);
|
||||||
|
label_highlight = memnew(Label);
|
||||||
|
label_filter = memnew(Label);
|
||||||
|
|
||||||
|
line_edit_search->set_placeholder(TTR("Search tree"));
|
||||||
|
|
||||||
|
label_highlight->set_text(TTR("Highlight"));
|
||||||
|
label_filter->set_text(TTR("Filter"));
|
||||||
|
|
||||||
|
close_button->set_button_icon(get_theme_icon(LW_NAME(Close), LW_NAME(EditorIcons)));
|
||||||
|
// positioning and sizing
|
||||||
|
this->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_WIDE);
|
||||||
|
this->set_v_size_flags(SIZE_SHRINK_CENTER); // Do not expand vertically
|
||||||
|
|
||||||
|
// hack add separator to the left so line edit doesn't clip.
|
||||||
|
line_edit_search->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
|
||||||
|
add_spacer(0.25); // otherwise the lineedits expand margin touches the left border.
|
||||||
|
add_child(line_edit_search);
|
||||||
|
add_spacer();
|
||||||
|
add_child(label_highlight);
|
||||||
|
add_child(check_button_filter_highlight);
|
||||||
|
add_child(label_filter);
|
||||||
|
add_child(close_button);
|
||||||
|
add_spacer(0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeSearchPanel::add_spacer(float width_multiplier) {
|
||||||
|
Control *spacer = memnew(Control);
|
||||||
|
spacer->set_custom_minimum_size(Vector2(8.0 * EDSCALE * width_multiplier, 0.0));
|
||||||
|
add_child(spacer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* !TreeSearchPanel */
|
||||||
|
|
||||||
|
TreeSearchPanel::TreeSearchPanel() {
|
||||||
|
_initialize_controls();
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeSearchMode TreeSearchPanel::get_search_mode() {
|
||||||
|
if (!check_button_filter_highlight || !check_button_filter_highlight->is_pressed()) {
|
||||||
|
return TreeSearchMode::HIGHLIGHT;
|
||||||
|
}
|
||||||
|
return TreeSearchMode::FILTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
String TreeSearchPanel::get_text() {
|
||||||
|
if (!line_edit_search)
|
||||||
|
return String();
|
||||||
|
return line_edit_search->get_text();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------- TreeSearch ------- */
|
||||||
|
|
||||||
|
void TreeSearch::filter_tree(TreeItem *tree_item, String search_mask) {
|
||||||
|
PRINT_LINE("filter tree not yet implemented!", search_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeSearch::highlight_tree(TreeItem *tree_item, String search_mask) {
|
||||||
|
PRINT_LINE("highlight tree not yet implemented! ", search_mask);
|
||||||
|
// queue/iterative instead of recursive approach. dsf
|
||||||
|
Vector<TreeItem> queue;
|
||||||
|
Vector<TreeItem> hits;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call this as a post-processing step for the already constructed tree.
|
||||||
|
void TreeSearch::apply_search(Tree *tree) {
|
||||||
|
if (!search_panel || !search_panel->is_visible()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeItem * tree_root = tree->get_root();
|
||||||
|
String search_mask = search_panel->get_text();
|
||||||
|
TreeSearchMode search_mode = search_panel->get_search_mode();
|
||||||
|
if (search_mode == TreeSearchMode::HIGHLIGHT){
|
||||||
|
highlight_tree(tree_root, search_mask);
|
||||||
|
}
|
||||||
|
if (search_mode == TreeSearchMode::FILTER){
|
||||||
|
filter_tree(tree_root, search_mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeSearch::TreeSearch() {
|
||||||
|
search_panel = memnew(TreeSearchPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeSearch::~TreeSearch() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* !TreeSearch */
|
||||||
|
|
||||||
|
#endif // ! TOOLS_ENABLED
|
|
@ -0,0 +1,84 @@
|
||||||
|
/**
|
||||||
|
* tree_search.h
|
||||||
|
* =============================================================================
|
||||||
|
* Copyright 2021-2024 Serhii Snitsaruk
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style
|
||||||
|
* license that can be found in the LICENSE file or at
|
||||||
|
* https://opensource.org/licenses/MIT.
|
||||||
|
* =============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
|
||||||
|
#ifndef TREE_SEARCH_H
|
||||||
|
#define TREE_SEARCH_H
|
||||||
|
|
||||||
|
#include "../bt/tasks/bt_task.h" // for tree item parsing
|
||||||
|
|
||||||
|
#ifdef LIMBOAI_GDEXTENSION
|
||||||
|
#include <godot_cpp/classes/check_button.hpp>
|
||||||
|
#include <godot_cpp/classes/control.hpp>
|
||||||
|
#include <godot_cpp/classes/h_box_container.hpp>
|
||||||
|
#include <godot_cpp/classes/line_edit.hpp>
|
||||||
|
#include <godot_cpp/classes/tree.hpp>
|
||||||
|
#include <godot_cpp/variant/signal.hpp>
|
||||||
|
#include <godot_cpp/classes/label.hpp>
|
||||||
|
#endif // LIMBOAI_GDEXTENSION
|
||||||
|
|
||||||
|
#ifdef LIMBOAI_MODULE
|
||||||
|
// TODO: Add includes for godot module variant.
|
||||||
|
#endif // LIMBOAI_MODULE
|
||||||
|
|
||||||
|
using namespace godot;
|
||||||
|
|
||||||
|
enum TreeSearchMode {
|
||||||
|
HIGHLIGHT = 0,
|
||||||
|
FILTER = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
class TreeSearchPanel : public HBoxContainer {
|
||||||
|
GDCLASS(TreeSearchPanel, HBoxContainer)
|
||||||
|
private:
|
||||||
|
Button *toggle_button_filter_highlight;
|
||||||
|
Button *close_button;
|
||||||
|
Label * label_highlight;
|
||||||
|
Label * label_filter;
|
||||||
|
LineEdit *line_edit_search;
|
||||||
|
CheckButton *check_button_filter_highlight;
|
||||||
|
|
||||||
|
void _initialize_controls();
|
||||||
|
void add_spacer(float width_multiplier = 1.f);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods(){}; // we don't need anything exposed.
|
||||||
|
|
||||||
|
public:
|
||||||
|
TreeSearchMode get_search_mode();
|
||||||
|
String get_text();
|
||||||
|
|
||||||
|
TreeSearchPanel();
|
||||||
|
};
|
||||||
|
|
||||||
|
class TreeSearch {
|
||||||
|
private:
|
||||||
|
void filter_tree(TreeItem *tree_item, String search_mask);
|
||||||
|
void highlight_tree(TreeItem *tree_item, String search_mask);
|
||||||
|
|
||||||
|
void highlight_item(TreeItem * tree_item, String search_mask);
|
||||||
|
Vector<TreeItem *> find_matching_entries(TreeItem * tree_item, Vector<TreeItem * > buffer = Vector<TreeItem *>());
|
||||||
|
|
||||||
|
public:
|
||||||
|
// we will add everything from TaskTree.h
|
||||||
|
void apply_search(Tree *tree);
|
||||||
|
void set_search_evaluation_method(Callable method);
|
||||||
|
TreeSearchPanel *search_panel;
|
||||||
|
|
||||||
|
TreeSearch();
|
||||||
|
~TreeSearch();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TREE_SEARCH_H
|
||||||
|
#endif // ! TOOLS_ENABLED
|
|
@ -106,6 +106,7 @@
|
||||||
#include "util/limbo_string_names.h"
|
#include "util/limbo_string_names.h"
|
||||||
#include "util/limbo_task_db.h"
|
#include "util/limbo_task_db.h"
|
||||||
#include "util/limbo_utility.h"
|
#include "util/limbo_utility.h"
|
||||||
|
#include "editor/tree_search.h"
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
#include "editor/debugger/behavior_tree_view.h"
|
#include "editor/debugger/behavior_tree_view.h"
|
||||||
|
@ -267,6 +268,7 @@ void initialize_limboai_module(ModuleInitializationLevel p_level) {
|
||||||
GDREGISTER_CLASS(OwnerPicker);
|
GDREGISTER_CLASS(OwnerPicker);
|
||||||
GDREGISTER_CLASS(LimboAIEditor);
|
GDREGISTER_CLASS(LimboAIEditor);
|
||||||
GDREGISTER_CLASS(LimboAIEditorPlugin);
|
GDREGISTER_CLASS(LimboAIEditorPlugin);
|
||||||
|
GDREGISTER_INTERNAL_CLASS(TreeSearchPanel);
|
||||||
#endif // LIMBOAI_GDEXTENSION
|
#endif // LIMBOAI_GDEXTENSION
|
||||||
|
|
||||||
EditorPlugins::add_by_type<LimboAIEditorPlugin>();
|
EditorPlugins::add_by_type<LimboAIEditorPlugin>();
|
||||||
|
|
|
@ -46,6 +46,7 @@ LimboStringNames::LimboStringNames() {
|
||||||
button_up = SN("button_up");
|
button_up = SN("button_up");
|
||||||
call_deferred = SN("call_deferred");
|
call_deferred = SN("call_deferred");
|
||||||
changed = SN("changed");
|
changed = SN("changed");
|
||||||
|
Close = SN("Close");
|
||||||
dark_color_2 = SN("dark_color_2");
|
dark_color_2 = SN("dark_color_2");
|
||||||
Debug = SN("Debug");
|
Debug = SN("Debug");
|
||||||
disabled_font_color = SN("disabled_font_color");
|
disabled_font_color = SN("disabled_font_color");
|
||||||
|
|
|
@ -62,6 +62,7 @@ public:
|
||||||
StringName button_up;
|
StringName button_up;
|
||||||
StringName call_deferred;
|
StringName call_deferred;
|
||||||
StringName changed;
|
StringName changed;
|
||||||
|
StringName Close;
|
||||||
StringName dark_color_2;
|
StringName dark_color_2;
|
||||||
StringName Debug;
|
StringName Debug;
|
||||||
StringName disabled_font_color;
|
StringName disabled_font_color;
|
||||||
|
|
Loading…
Reference in New Issue