Prototype loading user tasks

This commit is contained in:
Serhii Snitsaruk 2022-09-03 00:10:22 +02:00
parent 552185dc07
commit c9d92610a0
2 changed files with 62 additions and 12 deletions

View File

@ -4,17 +4,18 @@
#include "limbo_ai_editor_plugin.h" #include "limbo_ai_editor_plugin.h"
#include "../bt/composites/bt_parallel.h"
#include "../bt/composites/bt_selector.h"
#include "../bt/composites/bt_sequence.h"
#include "core/class_db.h" #include "core/class_db.h"
#include "core/error_list.h"
#include "core/error_macros.h"
#include "core/io/resource_loader.h" #include "core/io/resource_loader.h"
#include "core/io/resource_saver.h" #include "core/io/resource_saver.h"
#include "core/list.h" #include "core/list.h"
#include "core/math/math_defs.h" #include "core/math/math_defs.h"
#include "core/object.h" #include "core/object.h"
#include "core/os/dir_access.h"
#include "core/os/memory.h" #include "core/os/memory.h"
#include "core/print_string.h" #include "core/print_string.h"
#include "core/script_language.h"
#include "core/string_name.h" #include "core/string_name.h"
#include "core/typedefs.h" #include "core/typedefs.h"
#include "core/ustring.h" #include "core/ustring.h"
@ -22,7 +23,12 @@
#include "core/vector.h" #include "core/vector.h"
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/editor_plugin.h" #include "editor/editor_plugin.h"
#include "modules/limboai/bt/actions/bt_action.h"
#include "modules/limboai/bt/behavior_tree.h" #include "modules/limboai/bt/behavior_tree.h"
#include "modules/limboai/bt/bt_task.h"
#include "modules/limboai/bt/composites/bt_parallel.h"
#include "modules/limboai/bt/composites/bt_selector.h"
#include "modules/limboai/bt/composites/bt_sequence.h"
#include "scene/gui/box_container.h" #include "scene/gui/box_container.h"
#include "scene/gui/button.h" #include "scene/gui/button.h"
#include "scene/gui/file_dialog.h" #include "scene/gui/file_dialog.h"
@ -259,8 +265,10 @@ void TaskPanel::_init() {
categories["Condition"] = List<String>(); categories["Condition"] = List<String>();
_populate_core_tasks_from_class("BTCondition", &categories["Condition"]); _populate_core_tasks_from_class("BTCondition", &categories["Condition"]);
List<String> keys; categories["User"] = List<String>();
_populate_scripted_tasks_from_dir("res://ai/tasks/", &categories["User"]);
List<String> keys;
categories.get_key_list(&keys); categories.get_key_list(&keys);
keys.sort(); keys.sort();
for (List<String>::Element *E = keys.front(); E; E = E->next()) { for (List<String>::Element *E = keys.front(); E; E = E->next()) {
@ -268,8 +276,19 @@ void TaskPanel::_init() {
List<String> task_list = categories.get(cat); List<String> task_list = categories.get(cat);
TaskSection *sec = memnew(TaskSection(cat, editor)); TaskSection *sec = memnew(TaskSection(cat, editor));
for (List<String>::Element *E = task_list.front(); E; E = E->next()) { for (List<String>::Element *E = task_list.front(); E; E = E->next()) {
String tname = E->get(); String meta = E->get();
sec->add_task_button(tname, get_icon(tname, "EditorIcons"), tname); String tname;
Ref<Texture> icon;
if (meta.begins_with("res:")) {
// Scripted class
tname = meta.get_file().get_basename();
icon = editor->get_object_icon(ResourceLoader::load(meta).ptr());
} else {
// Core class
tname = meta;
icon = get_icon(tname, "EditorIcons");
}
sec->add_task_button(tname, icon, meta);
} }
sec->set_filter(""); sec->set_filter("");
sec->connect("task_button_pressed", this, "_on_task_button_pressed"); sec->connect("task_button_pressed", this, "_on_task_button_pressed");
@ -286,6 +305,26 @@ void TaskPanel::_populate_core_tasks_from_class(const StringName &p_base_class,
} }
} }
void TaskPanel::_populate_scripted_tasks_from_dir(String p_path, List<String> *p_task_classes) {
DirAccess *dir = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (dir->change_dir(p_path) == OK) {
dir->list_dir_begin();
String fn = dir->get_next();
while (!fn.empty()) {
if (fn.ends_with(".gd")) {
String full_path = p_path.plus_file(fn);
p_task_classes->push_back(full_path);
}
fn = dir->get_next();
}
dir->list_dir_end();
} else {
ERR_FAIL_MSG(vformat("Failed to list \"%s\" directory.", p_path));
}
memdelete(dir);
}
void TaskPanel::_bind_methods() { void TaskPanel::_bind_methods() {
ClassDB::bind_method(D_METHOD("_init"), &TaskPanel::_init); ClassDB::bind_method(D_METHOD("_init"), &TaskPanel::_init);
ClassDB::bind_method(D_METHOD("_on_task_button_pressed"), &TaskPanel::_on_task_button_pressed); ClassDB::bind_method(D_METHOD("_on_task_button_pressed"), &TaskPanel::_on_task_button_pressed);
@ -330,9 +369,9 @@ void LimboAIEditor::_add_task(const Ref<BTTask> &p_prototype) {
parent = task_tree->get_bt()->get_root_task(); parent = task_tree->get_bt()->get_root_task();
} }
if (parent.is_null()) { if (parent.is_null()) {
task_tree->get_bt()->set_root_task(p_prototype->clone()); task_tree->get_bt()->set_root_task(p_prototype);
} else { } else {
parent->add_child(p_prototype->clone()); parent->add_child(p_prototype);
} }
task_tree->update_tree(); task_tree->update_tree();
} }
@ -476,8 +515,18 @@ void LimboAIEditor::_on_tree_task_selected(const Ref<BTTask> &p_task) const {
editor->edit_resource(p_task); editor->edit_resource(p_task);
} }
void LimboAIEditor::_on_panel_task_selected(const StringName &p_task) { void LimboAIEditor::_on_panel_task_selected(String p_task) {
_add_task(Ref<BTTask>(ClassDB::instance(p_task))); if (p_task.begins_with("res:")) {
Ref<Script> script = ResourceLoader::load(p_task, "Script");
Variant inst = ClassDB::instance(script->get_instance_base_type());
ERR_FAIL_COND_MSG(!((Object *)inst)->is_class("BTTask"), vformat("Task script doesn't inherit BTTask: %s", p_task));
if (inst && script.is_valid()) {
((Object *)inst)->set_script(script.get_ref_ptr());
_add_task(Variant(inst));
}
} else {
_add_task(Ref<BTTask>(ClassDB::instance(p_task)));
}
} }
void LimboAIEditor::_on_visibility_changed() const { void LimboAIEditor::_on_visibility_changed() const {

View File

@ -4,10 +4,10 @@
#ifndef LIMBO_AI_EDITOR_PLUGIN_H #ifndef LIMBO_AI_EDITOR_PLUGIN_H
#define LIMBO_AI_EDITOR_PLUGIN_H #define LIMBO_AI_EDITOR_PLUGIN_H
#include "../bt/behavior_tree.h"
#include "core/object.h" #include "core/object.h"
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/editor_plugin.h" #include "editor/editor_plugin.h"
#include "modules/limboai/bt/behavior_tree.h"
#include "scene/gui/box_container.h" #include "scene/gui/box_container.h"
#include "scene/gui/file_dialog.h" #include "scene/gui/file_dialog.h"
#include "scene/gui/flow_container.h" #include "scene/gui/flow_container.h"
@ -77,6 +77,7 @@ private:
void _init(); void _init();
void _populate_core_tasks_from_class(const StringName &p_base_class, List<String> *p_task_classes); void _populate_core_tasks_from_class(const StringName &p_base_class, List<String> *p_task_classes);
void _populate_scripted_tasks_from_dir(String p_path, List<String> *p_task_classes);
void _on_task_button_pressed(const StringName &p_task); void _on_task_button_pressed(const StringName &p_task);
void _on_filter_text_changed(String p_text); void _on_filter_text_changed(String p_text);
@ -126,7 +127,7 @@ private:
void _on_visibility_changed() const; void _on_visibility_changed() const;
void _on_header_pressed() const; void _on_header_pressed() const;
void _on_save_pressed(); void _on_save_pressed();
void _on_panel_task_selected(const StringName &p_task); void _on_panel_task_selected(String p_task);
void _on_history_back(); void _on_history_back();
void _on_history_forward(); void _on_history_forward();