Compare commits
5 Commits
380f80c2b3
...
cd85e6dd30
Author | SHA1 | Date |
---|---|---|
Alexander Montag | cd85e6dd30 | |
Alexander Montag | 3b73f24f33 | |
Alexander Montag | 329e90dfc6 | |
Alexander Montag | 84b2a60521 | |
Alexander Montag | cc8f099d82 |
|
@ -457,7 +457,7 @@ void LimboAIEditor::_process_shortcut_input(const Ref<InputEvent> &p_event) {
|
||||||
_on_save_pressed();
|
_on_save_pressed();
|
||||||
} else if (LW_IS_SHORTCUT("limbo_ai/load_behavior_tree", p_event)) {
|
} else if (LW_IS_SHORTCUT("limbo_ai/load_behavior_tree", p_event)) {
|
||||||
_popup_file_dialog(load_dialog);
|
_popup_file_dialog(load_dialog);
|
||||||
} else if (LW_IS_SHORTCUT("limbo_ai/search_tree", p_event)) {
|
} else if (LW_IS_SHORTCUT("limbo_ai/find_task", p_event)) {
|
||||||
task_tree->tree_search_show_and_focus();
|
task_tree->tree_search_show_and_focus();
|
||||||
} else {
|
} else {
|
||||||
handled = false;
|
handled = false;
|
||||||
|
@ -1326,7 +1326,7 @@ void LimboAIEditor::_update_misc_menu() {
|
||||||
MISC_CREATE_SCRIPT_TEMPLATE);
|
MISC_CREATE_SCRIPT_TEMPLATE);
|
||||||
|
|
||||||
misc_menu->add_separator();
|
misc_menu->add_separator();
|
||||||
misc_menu->add_icon_item(theme_cache.search_icon, ("Search Tree"), MISC_SEARCH_TREE);
|
misc_menu->add_icon_shortcut(theme_cache.search_icon, LW_GET_SHORTCUT("limbo_ai/find_task"), MISC_SEARCH_TREE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimboAIEditor::_update_banners() {
|
void LimboAIEditor::_update_banners() {
|
||||||
|
@ -1522,8 +1522,7 @@ LimboAIEditor::LimboAIEditor() {
|
||||||
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)));
|
LW_SHORTCUT("limbo_ai/find_task", TTR("Find Task"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(F)));
|
||||||
LW_SHORTCUT("limbo_ai/hide_tree_search", TTR("Hide BehaviorTrees Search Panel"), (Key)(LW_KEY(ESCAPE)));
|
LW_SHORTCUT("limbo_ai/hide_tree_search", TTR("Close Search"), (Key)(LW_KEY(ESCAPE)));
|
||||||
LW_SHORTCUT("limbo_ai/search_tree", TTR("Shows the BehaviorTree Search Panel"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(F)));
|
|
||||||
|
|
||||||
set_process_shortcut_input(true);
|
set_process_shortcut_input(true);
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ void TaskTree::_update_item(TreeItem *p_item) {
|
||||||
if (!warning_text.is_empty()) {
|
if (!warning_text.is_empty()) {
|
||||||
p_item->add_button(0, theme_cache.task_warning_icon, 0, false, warning_text);
|
p_item->add_button(0, theme_cache.task_warning_icon, 0, false, warning_text);
|
||||||
}
|
}
|
||||||
tree_search->on_item_edited(p_item); // this is necessary to preserve custom drawing from tree search.
|
tree_search->notify_item_edited(p_item); // this is necessary to preserve custom drawing from tree search.
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskTree::_update_tree() {
|
void TaskTree::_update_tree() {
|
||||||
|
@ -582,8 +582,6 @@ 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);
|
VBoxContainer *vbox_container = memnew(VBoxContainer);
|
||||||
add_child(vbox_container);
|
add_child(vbox_container);
|
||||||
vbox_container->set_anchors_preset(PRESET_FULL_RECT);
|
vbox_container->set_anchors_preset(PRESET_FULL_RECT);
|
||||||
|
|
|
@ -51,12 +51,11 @@ void TreeSearchPanel::_initialize_controls() {
|
||||||
|
|
||||||
label_filter->set_text(TTR("Filter"));
|
label_filter->set_text(TTR("Filter"));
|
||||||
|
|
||||||
BUTTON_SET_ICON(close_button, get_theme_icon(LW_NAME(Close), LW_NAME(EditorIcons)));
|
|
||||||
close_button->set_theme_type_variation("FlatButton");
|
close_button->set_theme_type_variation("FlatButton");
|
||||||
|
|
||||||
// positioning and sizing
|
// positioning and sizing
|
||||||
this->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_WIDE);
|
set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_WIDE);
|
||||||
this->set_v_size_flags(SIZE_SHRINK_CENTER); // Do not expand vertically
|
set_v_size_flags(SIZE_SHRINK_CENTER); // Do not expand vertically
|
||||||
|
|
||||||
line_edit_search->set_h_size_flags(SIZE_EXPAND_FILL);
|
line_edit_search->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
|
||||||
|
@ -72,34 +71,28 @@ void TreeSearchPanel::_initialize_controls() {
|
||||||
_add_spacer(0.25);
|
_add_spacer(0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeSearchPanel::_initialize_close_callbacks() {
|
|
||||||
Callable calleable_set_invisible = Callable(this, "set_visible").bind(false); // don't need a custom bind.
|
|
||||||
close_button->connect("pressed", calleable_set_invisible);
|
|
||||||
close_button->set_shortcut(LW_GET_SHORTCUT("limbo_ai/hide_tree_search"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TreeSearchPanel::_add_spacer(float p_width_multiplier) {
|
void TreeSearchPanel::_add_spacer(float p_width_multiplier) {
|
||||||
Control *spacer = memnew(Control);
|
Control *spacer = memnew(Control);
|
||||||
spacer->set_custom_minimum_size(Vector2(8.0 * EDSCALE * p_width_multiplier, 0.0));
|
spacer->set_custom_minimum_size(Vector2(8.0 * EDSCALE * p_width_multiplier, 0.0));
|
||||||
add_child(spacer);
|
add_child(spacer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeSearchPanel::_emit_text_submitted(const String &p_text) {
|
|
||||||
this->emit_signal("text_submitted");
|
|
||||||
}
|
|
||||||
|
|
||||||
void TreeSearchPanel::_emit_update_requested() {
|
|
||||||
emit_signal("update_requested");
|
|
||||||
}
|
|
||||||
|
|
||||||
void TreeSearchPanel::_notification(int p_what) {
|
void TreeSearchPanel::_notification(int p_what) {
|
||||||
switch (p_what) {
|
switch (p_what) {
|
||||||
case NOTIFICATION_READY: {
|
case NOTIFICATION_READY: {
|
||||||
_initialize_controls();
|
BUTTON_SET_ICON(close_button, get_theme_icon(LW_NAME(Close), LW_NAME(EditorIcons)));
|
||||||
line_edit_search->connect("text_changed", callable_mp(this, &TreeSearchPanel::_emit_update_requested).unbind(1));
|
|
||||||
_initialize_close_callbacks();
|
// close callbacks
|
||||||
line_edit_search->connect("text_submitted", callable_mp(this, &TreeSearchPanel::_emit_text_submitted));
|
close_button->connect("pressed", Callable(this, "set_visible").bind(false));
|
||||||
check_button_filter_highlight->connect("pressed", callable_mp(this, &TreeSearchPanel::_emit_update_requested));
|
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");
|
||||||
|
|
||||||
|
line_edit_search->connect("text_changed", c_update_requested.unbind(1));
|
||||||
|
check_button_filter_highlight->connect("pressed", c_update_requested);
|
||||||
|
line_edit_search->connect("text_submitted", c_text_submitted.unbind(1));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,28 +104,26 @@ void TreeSearchPanel::_bind_methods() {
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeSearchPanel::TreeSearchPanel() {
|
TreeSearchPanel::TreeSearchPanel() {
|
||||||
this->set_visible(false);
|
_initialize_controls();
|
||||||
|
set_visible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TreeSearchPanel::has_focus() {
|
TreeSearch::TreeSearchMode TreeSearchPanel::get_search_mode() {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TreeSearchMode TreeSearchPanel::get_search_mode() {
|
|
||||||
if (!check_button_filter_highlight || !check_button_filter_highlight->is_pressed()) {
|
if (!check_button_filter_highlight || !check_button_filter_highlight->is_pressed()) {
|
||||||
return TreeSearchMode::HIGHLIGHT;
|
return TreeSearch::TreeSearchMode::HIGHLIGHT;
|
||||||
}
|
}
|
||||||
return TreeSearchMode::FILTER;
|
return TreeSearch::TreeSearchMode::FILTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
String TreeSearchPanel::get_text() {
|
String TreeSearchPanel::get_text() {
|
||||||
if (!line_edit_search)
|
if (!line_edit_search) {
|
||||||
return String();
|
return String();
|
||||||
|
}
|
||||||
return line_edit_search->get_text();
|
return line_edit_search->get_text();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeSearchPanel::show_and_focus() {
|
void TreeSearchPanel::show_and_focus() {
|
||||||
this->set_visible(true);
|
set_visible(true);
|
||||||
line_edit_search->grab_focus();
|
line_edit_search->grab_focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +191,7 @@ void TreeSearch::_highlight_tree(const String &p_search_mask) {
|
||||||
|
|
||||||
// custom draw callback for highlighting (bind the parent_drw_method to this)
|
// custom draw callback for highlighting (bind the parent_drw_method to this)
|
||||||
void TreeSearch::_draw_highlight_item(TreeItem *p_tree_item, Rect2 p_rect, Callable p_parent_draw_method) {
|
void TreeSearch::_draw_highlight_item(TreeItem *p_tree_item, Rect2 p_rect, Callable p_parent_draw_method) {
|
||||||
if (!p_tree_item){
|
if (!p_tree_item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// call any parent draw methods such as for probability FIRST.
|
// call any parent draw methods such as for probability FIRST.
|
||||||
|
@ -320,12 +311,18 @@ Vector<TreeItem *> TreeSearch::_find_matching_entries(TreeItem *p_tree_item, con
|
||||||
return p_accum;
|
return p_accum;
|
||||||
StringSearchIndices item_search_indices = _substring_bounds(p_tree_item->get_text(0), p_search_mask);
|
StringSearchIndices item_search_indices = _substring_bounds(p_tree_item->get_text(0), p_search_mask);
|
||||||
if (item_search_indices.hit())
|
if (item_search_indices.hit())
|
||||||
p_accum.insert(p_accum.bsearch(p_tree_item, true), p_tree_item);
|
p_accum.push_back(p_tree_item);
|
||||||
|
|
||||||
for (int i = 0; i < p_tree_item->get_child_count(); i++) {
|
for (int i = 0; i < p_tree_item->get_child_count(); i++) {
|
||||||
TreeItem *child = p_tree_item->get_child(i);
|
TreeItem *child = p_tree_item->get_child(i);
|
||||||
_find_matching_entries(child, p_search_mask, p_accum);
|
_find_matching_entries(child, p_search_mask, p_accum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sort the result if we are at the root
|
||||||
|
if (p_tree_item == p_tree_item->get_tree()->get_root()) {
|
||||||
|
p_accum.sort();
|
||||||
|
}
|
||||||
|
|
||||||
return p_accum;
|
return p_accum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,7 +439,7 @@ inline bool TreeSearch::_vector_has_bsearch(Vector<T *> p_vec, T *element) {
|
||||||
return in_array && p_vec[idx] == element;
|
return in_array && p_vec[idx] == element;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeSearch::on_item_edited(TreeItem *item) {
|
void TreeSearch::notify_item_edited(TreeItem *item) {
|
||||||
if (item->get_cell_mode(0) != TreeItem::CELL_MODE_CUSTOM) {
|
if (item->get_cell_mode(0) != TreeItem::CELL_MODE_CUSTOM) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -480,7 +477,6 @@ void TreeSearch::update_search(Tree *p_tree) {
|
||||||
if (search_mode == TreeSearchMode::FILTER) {
|
if (search_mode == TreeSearchMode::FILTER) {
|
||||||
_filter_tree(search_mask);
|
_filter_tree(search_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeSearch::TreeSearch(TreeSearchPanel *p_search_panel) {
|
TreeSearch::TreeSearch(TreeSearchPanel *p_search_panel) {
|
||||||
|
|
|
@ -24,48 +24,17 @@
|
||||||
#endif // LIMBOAI_GDEXTENSION
|
#endif // LIMBOAI_GDEXTENSION
|
||||||
|
|
||||||
#ifdef LIMBOAI_MODULE
|
#ifdef LIMBOAI_MODULE
|
||||||
|
#include "core/templates/hash_map.h"
|
||||||
#include "scene/gui/check_box.h"
|
#include "scene/gui/check_box.h"
|
||||||
#include "scene/gui/flow_container.h"
|
#include "scene/gui/flow_container.h"
|
||||||
#include "scene/gui/label.h"
|
#include "scene/gui/label.h"
|
||||||
#include "scene/gui/line_edit.h"
|
#include "scene/gui/line_edit.h"
|
||||||
#include "scene/gui/tree.h"
|
#include "scene/gui/tree.h"
|
||||||
#include "core/templates/hash_map.h"
|
|
||||||
#endif // LIMBOAI_MODULE
|
#endif // LIMBOAI_MODULE
|
||||||
|
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
|
||||||
enum TreeSearchMode {
|
class TreeSearchPanel;
|
||||||
HIGHLIGHT = 0,
|
|
||||||
FILTER = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
class TreeSearchPanel : public HFlowContainer {
|
|
||||||
GDCLASS(TreeSearchPanel, HFlowContainer)
|
|
||||||
private:
|
|
||||||
Button *toggle_button_filter_highlight;
|
|
||||||
Button *close_button;
|
|
||||||
Label *label_filter;
|
|
||||||
LineEdit *line_edit_search;
|
|
||||||
CheckBox *check_button_filter_highlight;
|
|
||||||
void _initialize_controls();
|
|
||||||
void _initialize_close_callbacks();
|
|
||||||
void _add_spacer(float width_multiplier = 1.f);
|
|
||||||
|
|
||||||
void _on_draw_highlight(TreeItem *p_item, Rect2 p_rect);
|
|
||||||
void _emit_text_submitted(const String &p_text);
|
|
||||||
void _emit_update_requested();
|
|
||||||
void _notification(int p_what);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static void _bind_methods();
|
|
||||||
|
|
||||||
public:
|
|
||||||
TreeSearchMode get_search_mode();
|
|
||||||
String get_text();
|
|
||||||
void show_and_focus();
|
|
||||||
TreeSearchPanel();
|
|
||||||
bool has_focus();
|
|
||||||
};
|
|
||||||
|
|
||||||
class TreeSearch : public RefCounted {
|
class TreeSearch : public RefCounted {
|
||||||
GDCLASS(TreeSearch, RefCounted)
|
GDCLASS(TreeSearch, RefCounted)
|
||||||
|
@ -115,11 +84,41 @@ protected:
|
||||||
static void _bind_methods() {}
|
static void _bind_methods() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void update_search(Tree *p_tree);
|
enum TreeSearchMode {
|
||||||
void on_item_edited(TreeItem *p_item);
|
HIGHLIGHT = 0,
|
||||||
|
FILTER = 1
|
||||||
|
};
|
||||||
|
|
||||||
TreeSearch(){ERR_FAIL_MSG("TreeSearch needs a TreeSearchPanel to work properly");}
|
void update_search(Tree *p_tree);
|
||||||
TreeSearch(TreeSearchPanel * p_search_panel);
|
void notify_item_edited(TreeItem *p_item);
|
||||||
|
|
||||||
|
TreeSearch() { ERR_FAIL_MSG("TreeSearch needs a TreeSearchPanel to work properly"); }
|
||||||
|
TreeSearch(TreeSearchPanel *p_search_panel);
|
||||||
|
};
|
||||||
|
|
||||||
|
class TreeSearchPanel : public HFlowContainer {
|
||||||
|
GDCLASS(TreeSearchPanel, HFlowContainer)
|
||||||
|
|
||||||
|
private:
|
||||||
|
Button *toggle_button_filter_highlight;
|
||||||
|
Button *close_button;
|
||||||
|
Label *label_filter;
|
||||||
|
LineEdit *line_edit_search;
|
||||||
|
CheckBox *check_button_filter_highlight;
|
||||||
|
void _initialize_controls();
|
||||||
|
void _add_spacer(float width_multiplier = 1.f);
|
||||||
|
|
||||||
|
void _on_draw_highlight(TreeItem *p_item, Rect2 p_rect);
|
||||||
|
void _notification(int p_what);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
TreeSearch::TreeSearchMode get_search_mode();
|
||||||
|
String get_text();
|
||||||
|
void show_and_focus();
|
||||||
|
TreeSearchPanel();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TREE_SEARCH_H
|
#endif // TREE_SEARCH_H
|
||||||
|
|
Loading…
Reference in New Issue