Editor: Add "Extract Subtree" action
Supports undo-redo, but it doesn't remove the newly created file automatically.
This commit is contained in:
parent
a2a2ba1f7b
commit
35f1dabe93
|
@ -14,9 +14,11 @@
|
||||||
#include "limbo_ai_editor_plugin.h"
|
#include "limbo_ai_editor_plugin.h"
|
||||||
|
|
||||||
#include "action_banner.h"
|
#include "action_banner.h"
|
||||||
|
#include "modules/limboai/bt/behavior_tree.h"
|
||||||
#include "modules/limboai/bt/tasks/bt_comment.h"
|
#include "modules/limboai/bt/tasks/bt_comment.h"
|
||||||
#include "modules/limboai/bt/tasks/composites/bt_probability_selector.h"
|
#include "modules/limboai/bt/tasks/composites/bt_probability_selector.h"
|
||||||
#include "modules/limboai/bt/tasks/composites/bt_selector.h"
|
#include "modules/limboai/bt/tasks/composites/bt_selector.h"
|
||||||
|
#include "modules/limboai/bt/tasks/decorators/bt_subtree.h"
|
||||||
#include "modules/limboai/editor/debugger/limbo_debugger_plugin.h"
|
#include "modules/limboai/editor/debugger/limbo_debugger_plugin.h"
|
||||||
#include "modules/limboai/editor/editor_property_bb_param.h"
|
#include "modules/limboai/editor/editor_property_bb_param.h"
|
||||||
#include "modules/limboai/util/limbo_utility.h"
|
#include "modules/limboai/util/limbo_utility.h"
|
||||||
|
@ -244,6 +246,39 @@ void LimboAIEditor::_remove_task_from_favorite(const String &p_task) {
|
||||||
ProjectSettings::get_singleton()->save();
|
ProjectSettings::get_singleton()->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LimboAIEditor::_extract_subtree(const String &p_path) {
|
||||||
|
Ref<BTTask> selected = task_tree->get_selected();
|
||||||
|
ERR_FAIL_COND(selected.is_null());
|
||||||
|
|
||||||
|
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
|
||||||
|
undo_redo->create_action(TTR("Extract Subtree"));
|
||||||
|
|
||||||
|
Ref<BehaviorTree> bt = memnew(BehaviorTree);
|
||||||
|
bt->set_root_task(selected->clone());
|
||||||
|
bt->set_path(p_path);
|
||||||
|
ResourceSaver::save(bt, p_path, ResourceSaver::FLAG_CHANGE_PATH);
|
||||||
|
|
||||||
|
Ref<BTSubtree> subtree = memnew(BTSubtree);
|
||||||
|
subtree->set_subtree(bt);
|
||||||
|
|
||||||
|
if (selected->is_root()) {
|
||||||
|
undo_redo->add_do_method(task_tree->get_bt().ptr(), SNAME("set_root_task"), subtree);
|
||||||
|
undo_redo->add_undo_method(task_tree->get_bt().ptr(), SNAME("set_root_task"), selected);
|
||||||
|
} else {
|
||||||
|
int idx = selected->get_index();
|
||||||
|
undo_redo->add_do_method(selected->get_parent().ptr(), SNAME("remove_child"), selected);
|
||||||
|
undo_redo->add_do_method(selected->get_parent().ptr(), SNAME("add_child_at_index"), subtree, idx);
|
||||||
|
undo_redo->add_undo_method(selected->get_parent().ptr(), SNAME("remove_child"), subtree);
|
||||||
|
undo_redo->add_undo_method(selected->get_parent().ptr(), SNAME("add_child_at_index"), selected, idx);
|
||||||
|
}
|
||||||
|
undo_redo->add_do_method(task_tree, SNAME("update_tree"));
|
||||||
|
undo_redo->add_undo_method(task_tree, SNAME("update_tree"));
|
||||||
|
|
||||||
|
undo_redo->commit_action();
|
||||||
|
EditorNode::get_singleton()->edit_resource(task_tree->get_selected());
|
||||||
|
_mark_as_dirty(true);
|
||||||
|
}
|
||||||
|
|
||||||
void LimboAIEditor::shortcut_input(const Ref<InputEvent> &p_event) {
|
void LimboAIEditor::shortcut_input(const Ref<InputEvent> &p_event) {
|
||||||
if (!p_event->is_pressed()) {
|
if (!p_event->is_pressed()) {
|
||||||
return;
|
return;
|
||||||
|
@ -305,6 +340,7 @@ void LimboAIEditor::_on_tree_rmb(const Vector2 &p_menu_pos) {
|
||||||
menu->add_icon_shortcut(theme_cache.move_task_down_icon, ED_GET_SHORTCUT("limbo_ai/move_task_down"), ACTION_MOVE_DOWN);
|
menu->add_icon_shortcut(theme_cache.move_task_down_icon, ED_GET_SHORTCUT("limbo_ai/move_task_down"), ACTION_MOVE_DOWN);
|
||||||
menu->add_icon_shortcut(theme_cache.duplicate_task_icon, ED_GET_SHORTCUT("limbo_ai/duplicate_task"), ACTION_DUPLICATE);
|
menu->add_icon_shortcut(theme_cache.duplicate_task_icon, ED_GET_SHORTCUT("limbo_ai/duplicate_task"), ACTION_DUPLICATE);
|
||||||
menu->add_icon_item(theme_cache.make_root_icon, TTR("Make Root"), ACTION_MAKE_ROOT);
|
menu->add_icon_item(theme_cache.make_root_icon, TTR("Make Root"), ACTION_MAKE_ROOT);
|
||||||
|
menu->add_icon_item(theme_cache.extract_subtree_icon, TTR("Extract Subtree"), ACTION_EXTRACT_SUBTREE);
|
||||||
|
|
||||||
menu->add_separator();
|
menu->add_separator();
|
||||||
menu->add_icon_shortcut(theme_cache.remove_task_icon, ED_GET_SHORTCUT("limbo_ai/remove_task"), ACTION_REMOVE);
|
menu->add_icon_shortcut(theme_cache.remove_task_icon, ED_GET_SHORTCUT("limbo_ai/remove_task"), ACTION_REMOVE);
|
||||||
|
@ -441,11 +477,17 @@ void LimboAIEditor::_action_selected(int p_id) {
|
||||||
_mark_as_dirty(true);
|
_mark_as_dirty(true);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case ACTION_EXTRACT_SUBTREE: {
|
||||||
|
Ref<BTTask> sel = task_tree->get_selected();
|
||||||
|
if (sel.is_valid() && !sel->is_class_ptr(BTSubtree::get_class_ptr_static())) {
|
||||||
|
extract_dialog->popup_centered_ratio();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case ACTION_REMOVE: {
|
case ACTION_REMOVE: {
|
||||||
Ref<BTTask> sel = task_tree->get_selected();
|
Ref<BTTask> sel = task_tree->get_selected();
|
||||||
if (sel.is_valid()) {
|
if (sel.is_valid()) {
|
||||||
undo_redo->create_action(TTR("Remove BT Task"));
|
undo_redo->create_action(TTR("Remove BT Task"));
|
||||||
if (sel->get_parent().is_null()) {
|
if (sel->is_root()) {
|
||||||
undo_redo->add_do_method(task_tree->get_bt().ptr(), SNAME("set_root_task"), Variant());
|
undo_redo->add_do_method(task_tree->get_bt().ptr(), SNAME("set_root_task"), Variant());
|
||||||
undo_redo->add_undo_method(task_tree->get_bt().ptr(), SNAME("set_root_task"), task_tree->get_bt()->get_root_task());
|
undo_redo->add_undo_method(task_tree->get_bt().ptr(), SNAME("set_root_task"), task_tree->get_bt()->get_root_task());
|
||||||
} else {
|
} else {
|
||||||
|
@ -899,6 +941,7 @@ void LimboAIEditor::_update_theme_item_cache() {
|
||||||
theme_cache.remove_task_icon = get_editor_theme_icon(SNAME("Remove"));
|
theme_cache.remove_task_icon = get_editor_theme_icon(SNAME("Remove"));
|
||||||
theme_cache.rename_task_icon = get_editor_theme_icon(SNAME("Rename"));
|
theme_cache.rename_task_icon = get_editor_theme_icon(SNAME("Rename"));
|
||||||
theme_cache.change_type_icon = get_editor_theme_icon(SNAME("Reload"));
|
theme_cache.change_type_icon = get_editor_theme_icon(SNAME("Reload"));
|
||||||
|
theme_cache.extract_subtree_icon = get_editor_theme_icon(SNAME("LimboExtractSubtree"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimboAIEditor::_notification(int p_what) {
|
void LimboAIEditor::_notification(int p_what) {
|
||||||
|
@ -966,7 +1009,7 @@ LimboAIEditor::LimboAIEditor() {
|
||||||
|
|
||||||
save_dialog = memnew(FileDialog);
|
save_dialog = memnew(FileDialog);
|
||||||
save_dialog->set_file_mode(FileDialog::FILE_MODE_SAVE_FILE);
|
save_dialog->set_file_mode(FileDialog::FILE_MODE_SAVE_FILE);
|
||||||
save_dialog->set_title("Save Behavior Tree");
|
save_dialog->set_title(TTR("Save Behavior Tree"));
|
||||||
save_dialog->add_filter("*.tres");
|
save_dialog->add_filter("*.tres");
|
||||||
save_dialog->connect("file_selected", callable_mp(this, &LimboAIEditor::_save_bt));
|
save_dialog->connect("file_selected", callable_mp(this, &LimboAIEditor::_save_bt));
|
||||||
save_dialog->hide();
|
save_dialog->hide();
|
||||||
|
@ -974,12 +1017,20 @@ LimboAIEditor::LimboAIEditor() {
|
||||||
|
|
||||||
load_dialog = memnew(FileDialog);
|
load_dialog = memnew(FileDialog);
|
||||||
load_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE);
|
load_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE);
|
||||||
load_dialog->set_title("Load Behavior Tree");
|
load_dialog->set_title(TTR("Load Behavior Tree"));
|
||||||
load_dialog->add_filter("*.tres");
|
load_dialog->add_filter("*.tres");
|
||||||
load_dialog->connect("file_selected", callable_mp(this, &LimboAIEditor::_load_bt));
|
load_dialog->connect("file_selected", callable_mp(this, &LimboAIEditor::_load_bt));
|
||||||
load_dialog->hide();
|
load_dialog->hide();
|
||||||
add_child(load_dialog);
|
add_child(load_dialog);
|
||||||
|
|
||||||
|
extract_dialog = memnew(FileDialog);
|
||||||
|
extract_dialog->set_file_mode(FileDialog::FILE_MODE_SAVE_FILE);
|
||||||
|
extract_dialog->set_title(TTR("Save Extracted Tree"));
|
||||||
|
extract_dialog->add_filter("*.tres");
|
||||||
|
extract_dialog->connect("file_selected", callable_mp(this, &LimboAIEditor::_extract_subtree));
|
||||||
|
extract_dialog->hide();
|
||||||
|
add_child(extract_dialog);
|
||||||
|
|
||||||
vbox = memnew(VBoxContainer);
|
vbox = memnew(VBoxContainer);
|
||||||
vbox->set_anchor(SIDE_RIGHT, ANCHOR_END);
|
vbox->set_anchor(SIDE_RIGHT, ANCHOR_END);
|
||||||
vbox->set_anchor(SIDE_BOTTOM, ANCHOR_END);
|
vbox->set_anchor(SIDE_BOTTOM, ANCHOR_END);
|
||||||
|
@ -1216,8 +1267,10 @@ LimboAIEditor::LimboAIEditor() {
|
||||||
GLOBAL_DEF(PropertyInfo(Variant::STRING, "limbo_ai/behavior_tree/user_task_dir_2", PROPERTY_HINT_DIR), "");
|
GLOBAL_DEF(PropertyInfo(Variant::STRING, "limbo_ai/behavior_tree/user_task_dir_2", PROPERTY_HINT_DIR), "");
|
||||||
GLOBAL_DEF(PropertyInfo(Variant::STRING, "limbo_ai/behavior_tree/user_task_dir_3", PROPERTY_HINT_DIR), "");
|
GLOBAL_DEF(PropertyInfo(Variant::STRING, "limbo_ai/behavior_tree/user_task_dir_3", PROPERTY_HINT_DIR), "");
|
||||||
|
|
||||||
save_dialog->set_current_dir(GLOBAL_GET("limbo_ai/behavior_tree/behavior_tree_default_dir"));
|
String bt_default_dir = GLOBAL_GET("limbo_ai/behavior_tree/behavior_tree_default_dir");
|
||||||
load_dialog->set_current_dir(GLOBAL_GET("limbo_ai/behavior_tree/behavior_tree_default_dir"));
|
save_dialog->set_current_dir(bt_default_dir);
|
||||||
|
load_dialog->set_current_dir(bt_default_dir);
|
||||||
|
extract_dialog->set_current_dir(bt_default_dir);
|
||||||
new_script_btn->connect("pressed", callable_mp(ScriptEditor::get_singleton(), &ScriptEditor::open_script_create_dialog).bind("BTAction", String(GLOBAL_GET("limbo_ai/behavior_tree/user_task_dir_1")).path_join("new_task")));
|
new_script_btn->connect("pressed", callable_mp(ScriptEditor::get_singleton(), &ScriptEditor::open_script_create_dialog).bind("BTAction", String(GLOBAL_GET("limbo_ai/behavior_tree/user_task_dir_1")).path_join("new_task")));
|
||||||
|
|
||||||
EditorFileSystem::get_singleton()->connect("resources_reload", callable_mp(this, &LimboAIEditor::_on_resources_reload));
|
EditorFileSystem::get_singleton()->connect("resources_reload", callable_mp(this, &LimboAIEditor::_on_resources_reload));
|
||||||
|
|
|
@ -42,15 +42,16 @@ class LimboAIEditor : public Control {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Action {
|
enum Action {
|
||||||
|
ACTION_EDIT_PROBABILITY,
|
||||||
ACTION_RENAME,
|
ACTION_RENAME,
|
||||||
ACTION_CHANGE_TYPE,
|
ACTION_CHANGE_TYPE,
|
||||||
ACTION_EDIT_PROBABILITY,
|
|
||||||
ACTION_EDIT_SCRIPT,
|
ACTION_EDIT_SCRIPT,
|
||||||
ACTION_OPEN_DOC,
|
ACTION_OPEN_DOC,
|
||||||
ACTION_MOVE_UP,
|
ACTION_MOVE_UP,
|
||||||
ACTION_MOVE_DOWN,
|
ACTION_MOVE_DOWN,
|
||||||
ACTION_DUPLICATE,
|
ACTION_DUPLICATE,
|
||||||
ACTION_MAKE_ROOT,
|
ACTION_MAKE_ROOT,
|
||||||
|
ACTION_EXTRACT_SUBTREE,
|
||||||
ACTION_REMOVE,
|
ACTION_REMOVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,6 +74,7 @@ private:
|
||||||
Ref<Texture2D> remove_task_icon;
|
Ref<Texture2D> remove_task_icon;
|
||||||
Ref<Texture2D> rename_task_icon;
|
Ref<Texture2D> rename_task_icon;
|
||||||
Ref<Texture2D> change_type_icon;
|
Ref<Texture2D> change_type_icon;
|
||||||
|
Ref<Texture2D> extract_subtree_icon;
|
||||||
} theme_cache;
|
} theme_cache;
|
||||||
|
|
||||||
Vector<Ref<BehaviorTree>> history;
|
Vector<Ref<BehaviorTree>> history;
|
||||||
|
@ -99,6 +101,7 @@ private:
|
||||||
|
|
||||||
FileDialog *save_dialog;
|
FileDialog *save_dialog;
|
||||||
FileDialog *load_dialog;
|
FileDialog *load_dialog;
|
||||||
|
FileDialog *extract_dialog;
|
||||||
Button *history_back;
|
Button *history_back;
|
||||||
Button *history_forward;
|
Button *history_forward;
|
||||||
|
|
||||||
|
@ -132,6 +135,7 @@ private:
|
||||||
void _create_user_task_dir();
|
void _create_user_task_dir();
|
||||||
void _edit_project_settings();
|
void _edit_project_settings();
|
||||||
void _remove_task_from_favorite(const String &p_task);
|
void _remove_task_from_favorite(const String &p_task);
|
||||||
|
void _extract_subtree(const String &p_path);
|
||||||
|
|
||||||
void _reload_modified();
|
void _reload_modified();
|
||||||
void _resave_modified(String _str = "");
|
void _resave_modified(String _str = "");
|
||||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 35 KiB |
Loading…
Reference in New Issue