2023-07-21 09:50:06 +00:00
|
|
|
/**
|
|
|
|
* limbo_debugger.cpp
|
|
|
|
* =============================================================================
|
2024-03-21 20:38:57 +00:00
|
|
|
* Copyright 2021-2024 Serhii Snitsaruk
|
2023-07-21 09:50:06 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
* =============================================================================
|
|
|
|
*/
|
2023-04-13 07:29:45 +00:00
|
|
|
|
|
|
|
#include "limbo_debugger.h"
|
2023-07-20 16:35:36 +00:00
|
|
|
|
2024-01-07 01:40:51 +00:00
|
|
|
#include "../../bt/tasks/bt_task.h"
|
2024-01-10 21:45:42 +00:00
|
|
|
#include "../../util/limbo_compat.h"
|
2023-04-13 07:29:45 +00:00
|
|
|
#include "behavior_tree_data.h"
|
2023-07-20 16:35:36 +00:00
|
|
|
|
2024-01-07 01:40:51 +00:00
|
|
|
#ifdef LIMBOAI_MODULE
|
2023-04-13 07:29:45 +00:00
|
|
|
#include "core/debugger/engine_debugger.h"
|
|
|
|
#include "core/error/error_macros.h"
|
2023-12-12 22:37:28 +00:00
|
|
|
#include "core/io/resource.h"
|
2023-04-13 07:29:45 +00:00
|
|
|
#include "core/string/node_path.h"
|
|
|
|
#include "scene/main/scene_tree.h"
|
|
|
|
#include "scene/main/window.h"
|
2024-01-07 01:40:51 +00:00
|
|
|
#endif // LIMBOAI_MODULE
|
|
|
|
|
|
|
|
#ifdef LIMBOAI_GDEXTENSION
|
|
|
|
#include <godot_cpp/classes/engine_debugger.hpp>
|
|
|
|
#include <godot_cpp/classes/scene_tree.hpp>
|
|
|
|
#include <godot_cpp/classes/window.hpp>
|
|
|
|
#endif // LIMBOAI_GDEXTENSION
|
2023-04-13 07:29:45 +00:00
|
|
|
|
2024-01-13 16:10:42 +00:00
|
|
|
//**** LimboDebugger
|
2023-04-13 07:29:45 +00:00
|
|
|
|
|
|
|
LimboDebugger *LimboDebugger::singleton = nullptr;
|
|
|
|
LimboDebugger *LimboDebugger::get_singleton() {
|
|
|
|
return singleton;
|
|
|
|
}
|
|
|
|
|
|
|
|
LimboDebugger::LimboDebugger() {
|
|
|
|
singleton = this;
|
2024-01-07 01:40:51 +00:00
|
|
|
#if defined(DEBUG_ENABLED) && defined(LIMBOAI_MODULE)
|
2023-04-13 07:29:45 +00:00
|
|
|
EngineDebugger::register_message_capture("limboai", EngineDebugger::Capture(nullptr, LimboDebugger::parse_message));
|
2024-01-13 16:10:42 +00:00
|
|
|
#elif defined(DEBUG_ENABLED) && defined(LIMBOAI_GDEXTENSION)
|
2024-01-09 20:47:22 +00:00
|
|
|
EngineDebugger::get_singleton()->register_message_capture("limboai", callable_mp(this, &LimboDebugger::parse_message_gdext));
|
2024-01-07 01:40:51 +00:00
|
|
|
#endif
|
2023-04-13 07:29:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LimboDebugger::~LimboDebugger() {
|
|
|
|
singleton = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LimboDebugger::initialize() {
|
2024-01-07 01:40:51 +00:00
|
|
|
if (IS_DEBUGGER_ACTIVE()) {
|
2023-04-13 07:29:45 +00:00
|
|
|
memnew(LimboDebugger);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LimboDebugger::deinitialize() {
|
|
|
|
if (singleton) {
|
|
|
|
memdelete(singleton);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-07 01:40:51 +00:00
|
|
|
void LimboDebugger::_bind_methods() {
|
2024-01-10 22:26:24 +00:00
|
|
|
#ifdef DEBUG_ENABLED
|
|
|
|
|
2024-01-07 01:40:51 +00:00
|
|
|
#ifdef LIMBOAI_GDEXTENSION
|
|
|
|
ClassDB::bind_method(D_METHOD("parse_message_gdext"), &LimboDebugger::parse_message_gdext);
|
|
|
|
#endif
|
2024-03-04 20:36:16 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("_on_bt_updated", "status", "path"), &LimboDebugger::_on_bt_updated);
|
|
|
|
ClassDB::bind_method(D_METHOD("_on_state_updated", "delta", "path"), &LimboDebugger::_on_state_updated);
|
2024-01-10 22:26:24 +00:00
|
|
|
#endif // ! DEBUG_ENABLED
|
2024-01-07 01:40:51 +00:00
|
|
|
}
|
|
|
|
|
2023-04-13 07:29:45 +00:00
|
|
|
#ifdef DEBUG_ENABLED
|
|
|
|
Error LimboDebugger::parse_message(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured) {
|
|
|
|
r_captured = true;
|
2023-04-15 07:01:37 +00:00
|
|
|
if (p_msg == "track_bt_player") {
|
2023-04-13 07:29:45 +00:00
|
|
|
singleton->_track_tree(p_args[0]);
|
2023-04-15 07:01:37 +00:00
|
|
|
} else if (p_msg == "untrack_bt_player") {
|
|
|
|
singleton->_untrack_tree();
|
2023-04-13 07:29:45 +00:00
|
|
|
} else if (p_msg == "start_session") {
|
|
|
|
singleton->session_active = true;
|
2023-04-15 07:01:37 +00:00
|
|
|
singleton->_send_active_bt_players();
|
2023-04-13 07:29:45 +00:00
|
|
|
} else if (p_msg == "stop_session") {
|
|
|
|
singleton->session_active = false;
|
|
|
|
} else {
|
|
|
|
r_captured = false;
|
|
|
|
}
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
2024-01-10 21:45:42 +00:00
|
|
|
#ifdef LIMBOAI_GDEXTENSION
|
2024-01-07 01:40:51 +00:00
|
|
|
bool LimboDebugger::parse_message_gdext(const String &p_msg, const Array &p_args) {
|
2024-01-09 20:47:22 +00:00
|
|
|
bool r_captured;
|
|
|
|
LimboDebugger::parse_message(nullptr, p_msg, p_args, r_captured);
|
|
|
|
return r_captured;
|
2024-01-07 01:40:51 +00:00
|
|
|
}
|
2024-01-13 16:10:42 +00:00
|
|
|
#endif // LIMBOAI_GDEXTENSION
|
2024-01-07 01:40:51 +00:00
|
|
|
|
2023-04-15 08:53:57 +00:00
|
|
|
void LimboDebugger::register_bt_instance(Ref<BTTask> p_instance, NodePath p_player_path) {
|
2023-09-09 11:37:09 +00:00
|
|
|
ERR_FAIL_COND(p_instance.is_null());
|
|
|
|
ERR_FAIL_COND(p_player_path.is_empty());
|
|
|
|
if (active_trees.has(p_player_path)) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-13 07:29:45 +00:00
|
|
|
|
2023-04-15 08:53:57 +00:00
|
|
|
active_trees.insert(p_player_path, p_instance);
|
2023-04-13 07:29:45 +00:00
|
|
|
if (session_active) {
|
2023-04-15 07:01:37 +00:00
|
|
|
_send_active_bt_players();
|
2023-04-13 07:29:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-15 08:53:57 +00:00
|
|
|
void LimboDebugger::unregister_bt_instance(Ref<BTTask> p_instance, NodePath p_player_path) {
|
2023-09-09 11:37:09 +00:00
|
|
|
ERR_FAIL_COND(p_instance.is_null());
|
2023-04-15 08:53:57 +00:00
|
|
|
ERR_FAIL_COND(p_player_path.is_empty());
|
|
|
|
ERR_FAIL_COND(!active_trees.has(p_player_path));
|
2023-04-13 07:29:45 +00:00
|
|
|
|
2023-12-12 22:37:28 +00:00
|
|
|
if (tracked_player == p_player_path) {
|
2023-04-13 07:29:45 +00:00
|
|
|
_untrack_tree();
|
|
|
|
}
|
2023-04-15 08:53:57 +00:00
|
|
|
active_trees.erase(p_player_path);
|
2023-04-13 07:29:45 +00:00
|
|
|
|
|
|
|
if (session_active) {
|
2023-04-15 07:01:37 +00:00
|
|
|
_send_active_bt_players();
|
2023-04-13 07:29:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LimboDebugger::_track_tree(NodePath p_path) {
|
|
|
|
ERR_FAIL_COND(!active_trees.has(p_path));
|
|
|
|
|
2023-12-12 22:37:28 +00:00
|
|
|
if (!tracked_player.is_empty()) {
|
2023-04-13 07:29:45 +00:00
|
|
|
_untrack_tree();
|
|
|
|
}
|
|
|
|
|
2024-01-09 12:34:24 +00:00
|
|
|
Node *node = SCENE_TREE()->get_root()->get_node_or_null(p_path);
|
2023-04-13 07:29:45 +00:00
|
|
|
ERR_FAIL_COND(node == nullptr);
|
|
|
|
|
2023-12-12 22:37:28 +00:00
|
|
|
tracked_player = p_path;
|
|
|
|
|
2024-01-09 20:47:22 +00:00
|
|
|
Ref<Resource> bt = node->get(LW_NAME(behavior_tree));
|
2024-01-07 01:40:51 +00:00
|
|
|
|
2023-12-12 22:37:28 +00:00
|
|
|
if (bt.is_valid()) {
|
|
|
|
bt_resource_path = bt->get_path();
|
|
|
|
} else {
|
|
|
|
bt_resource_path = "";
|
|
|
|
}
|
|
|
|
|
2023-04-13 07:29:45 +00:00
|
|
|
if (node->is_class("BTPlayer")) {
|
2024-01-09 12:42:54 +00:00
|
|
|
node->connect(LW_NAME(updated), callable_mp(this, &LimboDebugger::_on_bt_updated).bind(p_path));
|
2023-04-13 07:29:45 +00:00
|
|
|
} else if (node->is_class("BTState")) {
|
2024-01-09 12:42:54 +00:00
|
|
|
node->connect(LW_NAME(updated), callable_mp(this, &LimboDebugger::_on_state_updated).bind(p_path));
|
2023-04-13 07:29:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LimboDebugger::_untrack_tree() {
|
2023-12-12 22:37:28 +00:00
|
|
|
if (tracked_player.is_empty()) {
|
2023-04-13 07:29:45 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-12-12 22:37:28 +00:00
|
|
|
NodePath was_tracking = tracked_player;
|
|
|
|
tracked_player = NodePath();
|
2023-04-13 07:29:45 +00:00
|
|
|
|
2024-01-09 12:34:24 +00:00
|
|
|
Node *node = SCENE_TREE()->get_root()->get_node_or_null(was_tracking);
|
2023-04-13 07:29:45 +00:00
|
|
|
ERR_FAIL_COND(node == nullptr);
|
|
|
|
|
|
|
|
if (node->is_class("BTPlayer")) {
|
2024-01-09 12:42:54 +00:00
|
|
|
node->disconnect(LW_NAME(updated), callable_mp(this, &LimboDebugger::_on_bt_updated));
|
2023-04-13 07:29:45 +00:00
|
|
|
} else if (node->is_class("BTState")) {
|
2024-01-09 12:42:54 +00:00
|
|
|
node->disconnect(LW_NAME(updated), callable_mp(this, &LimboDebugger::_on_state_updated));
|
2023-04-13 07:29:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-15 07:01:37 +00:00
|
|
|
void LimboDebugger::_send_active_bt_players() {
|
2023-04-13 07:29:45 +00:00
|
|
|
Array arr;
|
|
|
|
for (KeyValue<NodePath, Ref<BTTask>> kv : active_trees) {
|
|
|
|
arr.append(kv.key);
|
|
|
|
}
|
2023-04-15 07:01:37 +00:00
|
|
|
EngineDebugger::get_singleton()->send_message("limboai:active_bt_players", arr);
|
2023-04-13 07:29:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void LimboDebugger::_on_bt_updated(int _status, NodePath p_path) {
|
2023-12-12 22:37:28 +00:00
|
|
|
if (p_path != tracked_player) {
|
2023-04-13 07:29:45 +00:00
|
|
|
return;
|
|
|
|
}
|
2024-02-03 15:31:21 +00:00
|
|
|
Array arr = BehaviorTreeData::serialize(active_trees.get(tracked_player), tracked_player, bt_resource_path);
|
2023-04-13 07:29:45 +00:00
|
|
|
EngineDebugger::get_singleton()->send_message("limboai:bt_update", arr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LimboDebugger::_on_state_updated(float _delta, NodePath p_path) {
|
2023-12-12 22:37:28 +00:00
|
|
|
if (p_path != tracked_player) {
|
2023-04-13 07:29:45 +00:00
|
|
|
return;
|
|
|
|
}
|
2024-02-03 15:31:21 +00:00
|
|
|
Array arr = BehaviorTreeData::serialize(active_trees.get(tracked_player), tracked_player, bt_resource_path);
|
2023-04-13 07:29:45 +00:00
|
|
|
EngineDebugger::get_singleton()->send_message("limboai:bt_update", arr);
|
|
|
|
}
|
|
|
|
|
2024-01-11 10:22:02 +00:00
|
|
|
#endif // ! DEBUG_ENABLED
|