Debugger: Add the resource header control with a path to the BehaviorTree for the currently debugged instance.
This commit is contained in:
parent
a3594e173c
commit
fb8585282d
|
@ -16,8 +16,50 @@
|
||||||
|
|
||||||
//// BehaviorTreeData
|
//// BehaviorTreeData
|
||||||
|
|
||||||
BehaviorTreeData::BehaviorTreeData(const Ref<BTTask> &p_instance, const NodePath &p_player_path) {
|
void BehaviorTreeData::serialize(Array &p_arr) {
|
||||||
|
p_arr.push_back(bt_player_path);
|
||||||
|
p_arr.push_back(bt_resource_path);
|
||||||
|
for (const TaskData &td : tasks) {
|
||||||
|
p_arr.push_back(td.id);
|
||||||
|
p_arr.push_back(td.name);
|
||||||
|
p_arr.push_back(td.is_custom_name);
|
||||||
|
p_arr.push_back(td.num_children);
|
||||||
|
p_arr.push_back(td.status);
|
||||||
|
p_arr.push_back(td.elapsed_time);
|
||||||
|
p_arr.push_back(td.type_name);
|
||||||
|
p_arr.push_back(td.script_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BehaviorTreeData::deserialize(const Array &p_arr) {
|
||||||
|
ERR_FAIL_COND(tasks.size() != 0);
|
||||||
|
ERR_FAIL_COND(p_arr.size() < 2);
|
||||||
|
|
||||||
|
ERR_FAIL_COND(p_arr[0].get_type() != Variant::NODE_PATH);
|
||||||
|
bt_player_path = p_arr[0];
|
||||||
|
|
||||||
|
ERR_FAIL_COND(p_arr[1].get_type() != Variant::STRING);
|
||||||
|
bt_resource_path = p_arr[1];
|
||||||
|
|
||||||
|
int idx = 2;
|
||||||
|
while (p_arr.size() > idx + 1) {
|
||||||
|
ERR_FAIL_COND(p_arr.size() < idx + 7);
|
||||||
|
ERR_FAIL_COND(p_arr[idx].get_type() != Variant::INT);
|
||||||
|
ERR_FAIL_COND(p_arr[idx + 1].get_type() != Variant::STRING);
|
||||||
|
ERR_FAIL_COND(p_arr[idx + 2].get_type() != Variant::BOOL);
|
||||||
|
ERR_FAIL_COND(p_arr[idx + 3].get_type() != Variant::INT);
|
||||||
|
ERR_FAIL_COND(p_arr[idx + 4].get_type() != Variant::INT);
|
||||||
|
ERR_FAIL_COND(p_arr[idx + 5].get_type() != Variant::FLOAT);
|
||||||
|
ERR_FAIL_COND(p_arr[idx + 6].get_type() != Variant::STRING);
|
||||||
|
ERR_FAIL_COND(p_arr[idx + 7].get_type() != Variant::STRING);
|
||||||
|
tasks.push_back(TaskData(p_arr[idx], p_arr[idx + 1], p_arr[idx + 2], p_arr[idx + 3], p_arr[idx + 4], p_arr[idx + 5], p_arr[idx + 6], p_arr[idx + 7]));
|
||||||
|
idx += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BehaviorTreeData::BehaviorTreeData(const Ref<BTTask> &p_instance, const NodePath &p_player_path, const String &p_bt_resource) {
|
||||||
bt_player_path = p_player_path;
|
bt_player_path = p_player_path;
|
||||||
|
bt_resource_path = p_bt_resource;
|
||||||
|
|
||||||
// Flatten tree into list depth first
|
// Flatten tree into list depth first
|
||||||
List<Ref<BTTask>> stack;
|
List<Ref<BTTask>> stack;
|
||||||
|
@ -50,40 +92,3 @@ BehaviorTreeData::BehaviorTreeData(const Ref<BTTask> &p_instance, const NodePath
|
||||||
id += 1;
|
id += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BehaviorTreeData::serialize(Array &p_arr) {
|
|
||||||
p_arr.push_back(bt_player_path);
|
|
||||||
for (const TaskData &td : tasks) {
|
|
||||||
p_arr.push_back(td.id);
|
|
||||||
p_arr.push_back(td.name);
|
|
||||||
p_arr.push_back(td.is_custom_name);
|
|
||||||
p_arr.push_back(td.num_children);
|
|
||||||
p_arr.push_back(td.status);
|
|
||||||
p_arr.push_back(td.elapsed_time);
|
|
||||||
p_arr.push_back(td.type_name);
|
|
||||||
p_arr.push_back(td.script_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BehaviorTreeData::deserialize(const Array &p_arr) {
|
|
||||||
ERR_FAIL_COND(tasks.size() != 0);
|
|
||||||
ERR_FAIL_COND(p_arr.size() < 1);
|
|
||||||
|
|
||||||
ERR_FAIL_COND(p_arr[0].get_type() != Variant::NODE_PATH);
|
|
||||||
bt_player_path = p_arr[0];
|
|
||||||
|
|
||||||
int idx = 1;
|
|
||||||
while (p_arr.size() > idx + 1) {
|
|
||||||
ERR_FAIL_COND(p_arr.size() < idx + 7);
|
|
||||||
ERR_FAIL_COND(p_arr[idx].get_type() != Variant::INT);
|
|
||||||
ERR_FAIL_COND(p_arr[idx + 1].get_type() != Variant::STRING);
|
|
||||||
ERR_FAIL_COND(p_arr[idx + 2].get_type() != Variant::BOOL);
|
|
||||||
ERR_FAIL_COND(p_arr[idx + 3].get_type() != Variant::INT);
|
|
||||||
ERR_FAIL_COND(p_arr[idx + 4].get_type() != Variant::INT);
|
|
||||||
ERR_FAIL_COND(p_arr[idx + 5].get_type() != Variant::FLOAT);
|
|
||||||
ERR_FAIL_COND(p_arr[idx + 6].get_type() != Variant::STRING);
|
|
||||||
ERR_FAIL_COND(p_arr[idx + 7].get_type() != Variant::STRING);
|
|
||||||
tasks.push_back(TaskData(p_arr[idx], p_arr[idx + 1], p_arr[idx + 2], p_arr[idx + 3], p_arr[idx + 4], p_arr[idx + 5], p_arr[idx + 6], p_arr[idx + 7]));
|
|
||||||
idx += 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -42,11 +42,12 @@ public:
|
||||||
|
|
||||||
List<TaskData> tasks;
|
List<TaskData> tasks;
|
||||||
NodePath bt_player_path;
|
NodePath bt_player_path;
|
||||||
|
String bt_resource_path;
|
||||||
|
|
||||||
void serialize(Array &p_arr);
|
void serialize(Array &p_arr);
|
||||||
void deserialize(const Array &p_arr);
|
void deserialize(const Array &p_arr);
|
||||||
|
|
||||||
BehaviorTreeData(const Ref<BTTask> &p_instance, const NodePath &p_player_path);
|
BehaviorTreeData(const Ref<BTTask> &p_instance, const NodePath &p_player_path, const String &p_bt_resource);
|
||||||
BehaviorTreeData() {}
|
BehaviorTreeData() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "core/debugger/engine_debugger.h"
|
#include "core/debugger/engine_debugger.h"
|
||||||
#include "core/error/error_macros.h"
|
#include "core/error/error_macros.h"
|
||||||
|
#include "core/io/resource.h"
|
||||||
#include "core/string/node_path.h"
|
#include "core/string/node_path.h"
|
||||||
#include "scene/main/scene_tree.h"
|
#include "scene/main/scene_tree.h"
|
||||||
#include "scene/main/window.h"
|
#include "scene/main/window.h"
|
||||||
|
@ -86,7 +87,7 @@ void LimboDebugger::unregister_bt_instance(Ref<BTTask> p_instance, NodePath p_pl
|
||||||
ERR_FAIL_COND(p_player_path.is_empty());
|
ERR_FAIL_COND(p_player_path.is_empty());
|
||||||
ERR_FAIL_COND(!active_trees.has(p_player_path));
|
ERR_FAIL_COND(!active_trees.has(p_player_path));
|
||||||
|
|
||||||
if (tracked_tree == p_player_path) {
|
if (tracked_player == p_player_path) {
|
||||||
_untrack_tree();
|
_untrack_tree();
|
||||||
}
|
}
|
||||||
active_trees.erase(p_player_path);
|
active_trees.erase(p_player_path);
|
||||||
|
@ -99,14 +100,23 @@ void LimboDebugger::unregister_bt_instance(Ref<BTTask> p_instance, NodePath p_pl
|
||||||
void LimboDebugger::_track_tree(NodePath p_path) {
|
void LimboDebugger::_track_tree(NodePath p_path) {
|
||||||
ERR_FAIL_COND(!active_trees.has(p_path));
|
ERR_FAIL_COND(!active_trees.has(p_path));
|
||||||
|
|
||||||
if (!tracked_tree.is_empty()) {
|
if (!tracked_player.is_empty()) {
|
||||||
_untrack_tree();
|
_untrack_tree();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *node = SceneTree::get_singleton()->get_root()->get_node(p_path);
|
Node *node = SceneTree::get_singleton()->get_root()->get_node(p_path);
|
||||||
ERR_FAIL_COND(node == nullptr);
|
ERR_FAIL_COND(node == nullptr);
|
||||||
|
|
||||||
tracked_tree = p_path;
|
tracked_player = p_path;
|
||||||
|
|
||||||
|
bool r_valid = false;
|
||||||
|
Ref<Resource> bt = node->get(SNAME("behavior_tree"), &r_valid);
|
||||||
|
if (bt.is_valid()) {
|
||||||
|
bt_resource_path = bt->get_path();
|
||||||
|
} else {
|
||||||
|
bt_resource_path = "";
|
||||||
|
}
|
||||||
|
|
||||||
if (node->is_class("BTPlayer")) {
|
if (node->is_class("BTPlayer")) {
|
||||||
node->connect(SNAME("updated"), callable_mp(this, &LimboDebugger::_on_bt_updated).bind(p_path));
|
node->connect(SNAME("updated"), callable_mp(this, &LimboDebugger::_on_bt_updated).bind(p_path));
|
||||||
} else if (node->is_class("BTState")) {
|
} else if (node->is_class("BTState")) {
|
||||||
|
@ -115,12 +125,12 @@ void LimboDebugger::_track_tree(NodePath p_path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimboDebugger::_untrack_tree() {
|
void LimboDebugger::_untrack_tree() {
|
||||||
if (tracked_tree.is_empty()) {
|
if (tracked_player.is_empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodePath was_tracking = tracked_tree;
|
NodePath was_tracking = tracked_player;
|
||||||
tracked_tree = NodePath();
|
tracked_player = NodePath();
|
||||||
|
|
||||||
Node *node = SceneTree::get_singleton()->get_root()->get_node(was_tracking);
|
Node *node = SceneTree::get_singleton()->get_root()->get_node(was_tracking);
|
||||||
ERR_FAIL_COND(node == nullptr);
|
ERR_FAIL_COND(node == nullptr);
|
||||||
|
@ -141,20 +151,20 @@ void LimboDebugger::_send_active_bt_players() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimboDebugger::_on_bt_updated(int _status, NodePath p_path) {
|
void LimboDebugger::_on_bt_updated(int _status, NodePath p_path) {
|
||||||
if (p_path != tracked_tree) {
|
if (p_path != tracked_player) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Array arr;
|
Array arr;
|
||||||
BehaviorTreeData(active_trees.get(tracked_tree), tracked_tree).serialize(arr);
|
BehaviorTreeData(active_trees.get(tracked_player), tracked_player, bt_resource_path).serialize(arr);
|
||||||
EngineDebugger::get_singleton()->send_message("limboai:bt_update", arr);
|
EngineDebugger::get_singleton()->send_message("limboai:bt_update", arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimboDebugger::_on_state_updated(float _delta, NodePath p_path) {
|
void LimboDebugger::_on_state_updated(float _delta, NodePath p_path) {
|
||||||
if (p_path != tracked_tree) {
|
if (p_path != tracked_player) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Array arr;
|
Array arr;
|
||||||
BehaviorTreeData(active_trees.get(tracked_tree), tracked_tree).serialize(arr);
|
BehaviorTreeData(active_trees.get(tracked_player), tracked_player, bt_resource_path).serialize(arr);
|
||||||
EngineDebugger::get_singleton()->send_message("limboai:bt_update", arr);
|
EngineDebugger::get_singleton()->send_message("limboai:bt_update", arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,8 @@ public:
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
private:
|
private:
|
||||||
HashMap<NodePath, Ref<BTTask>> active_trees;
|
HashMap<NodePath, Ref<BTTask>> active_trees;
|
||||||
NodePath tracked_tree;
|
NodePath tracked_player;
|
||||||
|
String bt_resource_path;
|
||||||
bool session_active = false;
|
bool session_active = false;
|
||||||
|
|
||||||
void _track_tree(NodePath p_path);
|
void _track_tree(NodePath p_path);
|
||||||
|
|
|
@ -14,17 +14,21 @@
|
||||||
#include "limbo_debugger_plugin.h"
|
#include "limbo_debugger_plugin.h"
|
||||||
|
|
||||||
#include "limbo_debugger.h"
|
#include "limbo_debugger.h"
|
||||||
|
#include "modules/limboai/bt/behavior_tree.h"
|
||||||
#include "modules/limboai/editor/debugger/behavior_tree_data.h"
|
#include "modules/limboai/editor/debugger/behavior_tree_data.h"
|
||||||
#include "modules/limboai/editor/debugger/behavior_tree_view.h"
|
#include "modules/limboai/editor/debugger/behavior_tree_view.h"
|
||||||
|
|
||||||
#include "core/debugger/engine_debugger.h"
|
#include "core/debugger/engine_debugger.h"
|
||||||
|
#include "core/error/error_macros.h"
|
||||||
#include "core/math/math_defs.h"
|
#include "core/math/math_defs.h"
|
||||||
#include "core/object/callable_method_pointer.h"
|
#include "core/object/callable_method_pointer.h"
|
||||||
#include "core/os/memory.h"
|
#include "core/os/memory.h"
|
||||||
#include "core/string/print_string.h"
|
#include "core/string/print_string.h"
|
||||||
#include "core/string/ustring.h"
|
#include "core/string/ustring.h"
|
||||||
#include "core/variant/array.h"
|
#include "core/variant/array.h"
|
||||||
|
#include "editor/editor_interface.h"
|
||||||
#include "editor/editor_scale.h"
|
#include "editor/editor_scale.h"
|
||||||
|
#include "editor/filesystem_dock.h"
|
||||||
#include "editor/plugins/editor_debugger_plugin.h"
|
#include "editor/plugins/editor_debugger_plugin.h"
|
||||||
#include "scene/gui/box_container.h"
|
#include "scene/gui/box_container.h"
|
||||||
#include "scene/gui/control.h"
|
#include "scene/gui/control.h"
|
||||||
|
@ -52,6 +56,8 @@ void LimboDebuggerTab::stop_session() {
|
||||||
alert_box->hide();
|
alert_box->hide();
|
||||||
info_message->set_text(TTR("Run project to start debugging."));
|
info_message->set_text(TTR("Run project to start debugging."));
|
||||||
info_message->show();
|
info_message->show();
|
||||||
|
resource_header->set_disabled(true);
|
||||||
|
resource_header->set_text(TTR("Inactive"));
|
||||||
session->send_message("limboai:stop_session", Array());
|
session->send_message("limboai:stop_session", Array());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +77,8 @@ String LimboDebuggerTab::get_selected_bt_player() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimboDebuggerTab::update_behavior_tree(const BehaviorTreeData &p_data) {
|
void LimboDebuggerTab::update_behavior_tree(const BehaviorTreeData &p_data) {
|
||||||
|
resource_header->set_text(p_data.bt_resource_path);
|
||||||
|
resource_header->set_disabled(false);
|
||||||
bt_view->update_tree(p_data);
|
bt_view->update_tree(p_data);
|
||||||
info_message->hide();
|
info_message->hide();
|
||||||
}
|
}
|
||||||
|
@ -122,6 +130,8 @@ void LimboDebuggerTab::_bt_selected(int p_idx) {
|
||||||
bt_view->clear();
|
bt_view->clear();
|
||||||
info_message->set_text(TTR("Waiting for behavior tree update."));
|
info_message->set_text(TTR("Waiting for behavior tree update."));
|
||||||
info_message->show();
|
info_message->show();
|
||||||
|
resource_header->set_text(TTR("Waiting for data"));
|
||||||
|
resource_header->set_disabled(true);
|
||||||
NodePath path = bt_player_list->get_item_text(p_idx);
|
NodePath path = bt_player_list->get_item_text(p_idx);
|
||||||
Array msg_data;
|
Array msg_data;
|
||||||
msg_data.push_back(path);
|
msg_data.push_back(path);
|
||||||
|
@ -136,9 +146,21 @@ void LimboDebuggerTab::_window_visibility_changed(bool p_visible) {
|
||||||
make_floating->set_visible(!p_visible);
|
make_floating->set_visible(!p_visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LimboDebuggerTab::_resource_header_pressed() {
|
||||||
|
String bt_path = resource_header->get_text();
|
||||||
|
if (bt_path.is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FileSystemDock::get_singleton()->select_file(bt_path);
|
||||||
|
Ref<BehaviorTree> bt = ResourceLoader::load(bt_path, "BehaviorTree");
|
||||||
|
ERR_FAIL_COND_MSG(!bt.is_valid(), "Failed to load BehaviorTree. Wrong resource path?");
|
||||||
|
EditorInterface::get_singleton()->edit_resource(bt);
|
||||||
|
}
|
||||||
|
|
||||||
void LimboDebuggerTab::_notification(int p_what) {
|
void LimboDebuggerTab::_notification(int p_what) {
|
||||||
if (p_what == NOTIFICATION_THEME_CHANGED) {
|
if (p_what == NOTIFICATION_THEME_CHANGED) {
|
||||||
alert_icon->set_texture(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
|
alert_icon->set_texture(get_editor_theme_icon(SNAME("StatusWarning")));
|
||||||
|
resource_header->set_icon(get_editor_theme_icon(SNAME("BehaviorTree")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +174,16 @@ LimboDebuggerTab::LimboDebuggerTab(Ref<EditorDebuggerSession> p_session, WindowW
|
||||||
toolbar = memnew(HBoxContainer);
|
toolbar = memnew(HBoxContainer);
|
||||||
root_vb->add_child(toolbar);
|
root_vb->add_child(toolbar);
|
||||||
|
|
||||||
|
resource_header = memnew(Button);
|
||||||
|
toolbar->add_child(resource_header);
|
||||||
|
resource_header->set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT);
|
||||||
|
resource_header->set_focus_mode(FOCUS_NONE);
|
||||||
|
resource_header->add_theme_constant_override("hseparation", 8);
|
||||||
|
resource_header->set_text(TTR("Inactive"));
|
||||||
|
resource_header->set_tooltip_text(TTR("Debugged BehaviorTree resource.\nClick to open."));
|
||||||
|
resource_header->set_disabled(true);
|
||||||
|
resource_header->connect("pressed", callable_mp(this, &LimboDebuggerTab::_resource_header_pressed));
|
||||||
|
|
||||||
hsc = memnew(HSplitContainer);
|
hsc = memnew(HSplitContainer);
|
||||||
hsc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
hsc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
hsc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
hsc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
|
|
|
@ -45,7 +45,7 @@ private:
|
||||||
TextureRect *alert_icon = nullptr;
|
TextureRect *alert_icon = nullptr;
|
||||||
Label *alert_message = nullptr;
|
Label *alert_message = nullptr;
|
||||||
LineEdit *filter_players = nullptr;
|
LineEdit *filter_players = nullptr;
|
||||||
|
Button *resource_header = nullptr;
|
||||||
Button *make_floating = nullptr;
|
Button *make_floating = nullptr;
|
||||||
WindowWrapper *window_wrapper = nullptr;
|
WindowWrapper *window_wrapper = nullptr;
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ private:
|
||||||
void _bt_selected(int p_idx);
|
void _bt_selected(int p_idx);
|
||||||
void _filter_changed(String p_text);
|
void _filter_changed(String p_text);
|
||||||
void _window_visibility_changed(bool p_visible);
|
void _window_visibility_changed(bool p_visible);
|
||||||
|
void _resource_header_pressed();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
|
|
Loading…
Reference in New Issue