From a9a38bbffb157fd20f26397cbe04676d22667016 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Tue, 9 Jan 2024 21:47:22 +0100 Subject: [PATCH] Port debugger --- bt/tasks/bt_task.cpp | 19 +- editor/debugger/limbo_debugger.cpp | 17 +- editor/debugger/limbo_debugger_plugin.cpp | 120 +++-- editor/debugger/limbo_debugger_plugin.h | 54 ++- editor/limbo_ai_editor_plugin.cpp | 27 +- editor/limbo_ai_editor_plugin.h | 2 +- gdextension/SConstruct | 5 +- gdextension/window_wrapper.cpp | 511 ++++++++++++++++++++++ gdextension/window_wrapper.h | 138 ++++++ register_types.cpp | 11 +- util/limbo_compat.h | 2 + util/limbo_string_names.cpp | 6 + util/limbo_string_names.h | 6 + 13 files changed, 835 insertions(+), 83 deletions(-) create mode 100644 gdextension/window_wrapper.cpp create mode 100644 gdextension/window_wrapper.h diff --git a/bt/tasks/bt_task.cpp b/bt/tasks/bt_task.cpp index 4f54317..fb714f0 100644 --- a/bt/tasks/bt_task.cpp +++ b/bt/tasks/bt_task.cpp @@ -10,12 +10,6 @@ */ #include "bt_task.h" -#include "godot_cpp/classes/global_constants.hpp" -#include "godot_cpp/variant/dictionary.hpp" -#include "godot_cpp/variant/string_name.hpp" -#include "godot_cpp/variant/typed_array.hpp" -#include "godot_cpp/variant/utility_functions.hpp" -#include "godot_cpp/variant/variant.hpp" #ifdef LIMBOAI_MODULE #include "bt_comment.h" @@ -39,6 +33,13 @@ #include "bt/tasks/bt_comment.h" #include "util/limbo_string_names.h" +#include "godot_cpp/classes/global_constants.hpp" +#include "godot_cpp/core/class_db.hpp" +#include "godot_cpp/variant/dictionary.hpp" +#include "godot_cpp/variant/string_name.hpp" +#include "godot_cpp/variant/typed_array.hpp" +#include "godot_cpp/variant/utility_functions.hpp" +#include "godot_cpp/variant/variant.hpp" #include #endif // LIMBOAI_GDEXTENSION @@ -447,6 +448,12 @@ void BTTask::_bind_methods() { ClassDB::bind_method(D_METHOD("_tick", "p_delta"), &BTTask::_tick); ClassDB::bind_method(D_METHOD("_generate_name"), &BTTask::_generate_name); ClassDB::bind_method(D_METHOD("_get_configuration_warnings"), &BTTask::get_configuration_warnings); + // BIND_VIRTUAL_METHOD(BTTask, _setup); + // BIND_VIRTUAL_METHOD(BTTask, _enter); + // BIND_VIRTUAL_METHOD(BTTask, _exit); + // BIND_VIRTUAL_METHOD(BTTask, _tick); + // BIND_VIRTUAL_METHOD(BTTask, _generate_name); + // BIND_VIRTUAL_METHOD(BTTask, get_configuration_warnings); #endif } diff --git a/editor/debugger/limbo_debugger.cpp b/editor/debugger/limbo_debugger.cpp index 6cb5487..45ea87c 100644 --- a/editor/debugger/limbo_debugger.cpp +++ b/editor/debugger/limbo_debugger.cpp @@ -42,7 +42,7 @@ LimboDebugger::LimboDebugger() { EngineDebugger::register_message_capture("limboai", EngineDebugger::Capture(nullptr, LimboDebugger::parse_message)); #endif #if defined(DEBUG_ENABLED) && defined(LIMBOAI_GDEXTENSION) - // EngineDebugger::get_singleton()->register_message_capture("limboai", callable_mp(this, &LimboDebugger::parse_message)); + EngineDebugger::get_singleton()->register_message_capture("limboai", callable_mp(this, &LimboDebugger::parse_message_gdext)); #endif } @@ -89,9 +89,9 @@ Error LimboDebugger::parse_message(void *p_user, const String &p_msg, const Arra } bool LimboDebugger::parse_message_gdext(const String &p_msg, const Array &p_args) { - bool ret; - LimboDebugger::parse_message(nullptr, p_msg, p_args, ret); - return ret; + bool r_captured; + LimboDebugger::parse_message(nullptr, p_msg, p_args, r_captured); + return r_captured; } void LimboDebugger::register_bt_instance(Ref p_instance, NodePath p_player_path) { @@ -134,14 +134,7 @@ void LimboDebugger::_track_tree(NodePath p_path) { tracked_player = p_path; - Ref bt; -#ifdef LIMBOAI_MODULE - bool r_valid = false; - bt = node->get(LW_NAME(behavior_tree), &r_valid); -#endif -#ifdef LIMBOAI_GDEXTENSION - bt = node->get(LW_NAME(behavior_tree)); -#endif + Ref bt = node->get(LW_NAME(behavior_tree)); if (bt.is_valid()) { bt_resource_path = bt->get_path(); diff --git a/editor/debugger/limbo_debugger_plugin.cpp b/editor/debugger/limbo_debugger_plugin.cpp index 9ec68ac..6687ec9 100644 --- a/editor/debugger/limbo_debugger_plugin.cpp +++ b/editor/debugger/limbo_debugger_plugin.cpp @@ -13,11 +13,12 @@ #include "limbo_debugger_plugin.h" +#include "../../bt/behavior_tree.h" +#include "../../editor/debugger/behavior_tree_data.h" +#include "../../editor/debugger/behavior_tree_view.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_view.h" +#ifdef LIMBOAI_MODULE #include "core/debugger/engine_debugger.h" #include "core/error/error_macros.h" #include "core/math/math_defs.h" @@ -38,9 +39,28 @@ #include "scene/gui/split_container.h" #include "scene/gui/tab_container.h" #include "scene/gui/texture_rect.h" +#endif // ! LIMBOAI_MODULE + +#ifdef LIMBOAI_GDEXTENSION +#include +#include +#include +#include + +#endif // ! LIMBOAI_GDEXTENSION //**** LimboDebuggerTab +void LimboDebuggerTab::_reset_controls() { + bt_player_list->clear(); + bt_view->clear(); + alert_box->hide(); + info_message->set_text(TTR("Run project to start debugging.")); + info_message->show(); + resource_header->set_disabled(true); + resource_header->set_text(TTR("Inactive")); +} + void LimboDebuggerTab::start_session() { bt_player_list->clear(); bt_view->clear(); @@ -51,13 +71,7 @@ void LimboDebuggerTab::start_session() { } void LimboDebuggerTab::stop_session() { - bt_player_list->clear(); - bt_view->clear(); - alert_box->hide(); - info_message->set_text(TTR("Run project to start debugging.")); - info_message->show(); - resource_header->set_disabled(true); - resource_header->set_text(TTR("Inactive")); + _reset_controls(); session->send_message("limboai:stop_session", Array()); } @@ -92,7 +106,7 @@ void LimboDebuggerTab::_update_bt_player_list(const List &p_node_paths, // Remember selected item. String selected_player = ""; if (bt_player_list->is_anything_selected()) { - selected_player = bt_player_list->get_item_text(bt_player_list->get_selected_items().get(0)); + selected_player = bt_player_list->get_item_text(bt_player_list->get_selected_items()[0]); } bt_player_list->clear(); @@ -151,23 +165,47 @@ void LimboDebuggerTab::_resource_header_pressed() { if (bt_path.is_empty()) { return; } - FileSystemDock::get_singleton()->select_file(bt_path); - Ref bt = ResourceLoader::load(bt_path, "BehaviorTree"); + FS_DOCK_SELECT_FILE(bt_path); + Ref bt = RESOURCE_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::_bind_methods() { +} + void LimboDebuggerTab::_notification(int p_what) { - if (p_what == NOTIFICATION_THEME_CHANGED) { - alert_icon->set_texture(get_editor_theme_icon(SNAME("StatusWarning"))); - resource_header->set_icon(get_editor_theme_icon(SNAME("BehaviorTree"))); + switch (p_what) { + case NOTIFICATION_READY: { + resource_header->connect(LW_NAME(pressed), callable_mp(this, &LimboDebuggerTab::_resource_header_pressed)); + filter_players->connect(LW_NAME(text_changed), callable_mp(this, &LimboDebuggerTab::_filter_changed)); + bt_player_list->connect(LW_NAME(item_selected), callable_mp(this, &LimboDebuggerTab::_bt_selected)); + } break; + case NOTIFICATION_THEME_CHANGED: { + alert_icon->set_texture(get_theme_icon(LW_NAME(StatusWarning), LW_NAME(EditorIcons))); + BUTTON_SET_ICON(resource_header, get_theme_icon(LW_NAME(BehaviorTree), LW_NAME(EditorIcons))); + } break; } } -LimboDebuggerTab::LimboDebuggerTab(Ref p_session, WindowWrapper *p_wrapper) { +void LimboDebuggerTab::setup(Ref p_session, CompatWindowWrapper *p_wrapper) { session = p_session; window_wrapper = p_wrapper; + if (p_wrapper->is_window_available()) { + make_floating = memnew(CompatScreenSelect); + make_floating->set_flat(true); + make_floating->set_h_size_flags(Control::SIZE_EXPAND | Control::SIZE_SHRINK_END); + make_floating->set_tooltip_text(TTR("Make the LimboAI Debugger floating.")); + make_floating->connect(LW_NAME(request_open_in_screen), callable_mp(window_wrapper, &CompatWindowWrapper::enable_window_on_screen).bind(true)); + toolbar->add_child(make_floating); + p_wrapper->connect(LW_NAME(window_visibility_changed), callable_mp(this, &LimboDebuggerTab::_window_visibility_changed)); + } + + _reset_controls(); +} + +LimboDebuggerTab::LimboDebuggerTab() { root_vb = memnew(VBoxContainer); add_child(root_vb); @@ -182,7 +220,6 @@ LimboDebuggerTab::LimboDebuggerTab(Ref p_session, WindowW 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->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -192,26 +229,14 @@ LimboDebuggerTab::LimboDebuggerTab(Ref p_session, WindowW VBoxContainer *list_box = memnew(VBoxContainer); hsc->add_child(list_box); - if (p_wrapper->is_window_available()) { - make_floating = memnew(ScreenSelect); - make_floating->set_flat(true); - make_floating->set_h_size_flags(Control::SIZE_EXPAND | Control::SIZE_SHRINK_END); - make_floating->set_tooltip_text(TTR("Make the LimboAI Debugger floating.")); - make_floating->connect(SNAME("request_open_in_screen"), callable_mp(window_wrapper, &WindowWrapper::enable_window_on_screen).bind(true)); - toolbar->add_child(make_floating); - p_wrapper->connect(SNAME("window_visibility_changed"), callable_mp(this, &LimboDebuggerTab::_window_visibility_changed)); - } - filter_players = memnew(LineEdit); filter_players->set_placeholder(TTR("Filter Players")); - filter_players->connect(SNAME("text_changed"), callable_mp(this, &LimboDebuggerTab::_filter_changed)); list_box->add_child(filter_players); bt_player_list = memnew(ItemList); bt_player_list->set_custom_minimum_size(Size2(240.0 * EDSCALE, 0.0)); bt_player_list->set_h_size_flags(SIZE_FILL); bt_player_list->set_v_size_flags(SIZE_EXPAND_FILL); - bt_player_list->connect(SNAME("item_selected"), callable_mp(this, &LimboDebuggerTab::_bt_selected)); list_box->add_child(bt_player_list); view_box = memnew(VBoxContainer); @@ -242,8 +267,6 @@ LimboDebuggerTab::LimboDebuggerTab(Ref p_session, WindowW info_message->set_anchors_and_offsets_preset(PRESET_FULL_RECT, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); bt_view->add_child(info_message); - - stop_session(); } //**** LimboDebuggerPlugin @@ -253,7 +276,11 @@ LimboDebuggerPlugin *LimboDebuggerPlugin::singleton = nullptr; void LimboDebuggerPlugin::_window_visibility_changed(bool p_visible) { } +#ifdef LIMBOAI_MODULE void LimboDebuggerPlugin::setup_session(int p_idx) { +#else // LIMBOAI_GDEXTENSION +void LimboDebuggerPlugin::_setup_session(int32_t p_idx) { +#endif Ref session = get_session(p_idx); if (tab != nullptr) { @@ -261,31 +288,36 @@ void LimboDebuggerPlugin::setup_session(int p_idx) { window_wrapper->queue_free(); } - window_wrapper = memnew(WindowWrapper); + window_wrapper = memnew(CompatWindowWrapper); window_wrapper->set_window_title(vformat(TTR("%s - Godot Engine"), TTR("LimboAI Debugger"))); window_wrapper->set_margins_enabled(true); - window_wrapper->set_name("LimboAI"); - tab = memnew(LimboDebuggerTab(session, window_wrapper)); + tab = memnew(LimboDebuggerTab()); + tab->setup(session, window_wrapper); tab->set_name("LimboAI"); window_wrapper->set_wrapped_control(tab); + window_wrapper->set_name("LimboAI"); window_wrapper->set_v_size_flags(Control::SIZE_EXPAND_FILL); - window_wrapper->connect(SNAME("window_visibility_changed"), callable_mp(this, &LimboDebuggerPlugin::_window_visibility_changed)); + window_wrapper->connect(LW_NAME(window_visibility_changed), callable_mp(this, &LimboDebuggerPlugin::_window_visibility_changed)); - session->connect(SNAME("started"), callable_mp(tab, &LimboDebuggerTab::start_session)); - session->connect(SNAME("stopped"), callable_mp(tab, &LimboDebuggerTab::stop_session)); + session->connect(LW_NAME(started), callable_mp(tab, &LimboDebuggerTab::start_session)); + session->connect(LW_NAME(stopped), callable_mp(tab, &LimboDebuggerTab::stop_session)); session->add_session_tab(window_wrapper); } +#ifdef LIMBOAI_MODULE bool LimboDebuggerPlugin::capture(const String &p_message, const Array &p_data, int p_session) { +#else // LIMBOAI_GDEXTENSION +bool LimboDebuggerPlugin::_capture(const String &p_message, const Array &p_data, int32_t p_session) { +#endif bool captured = true; if (p_message == "limboai:active_bt_players") { tab->update_active_bt_players(p_data); } else if (p_message == "limboai:bt_update") { BehaviorTreeData data = BehaviorTreeData(); data.deserialize(p_data); - if (data.bt_player_path == tab->get_selected_bt_player()) { + if (data.bt_player_path == NodePath(tab->get_selected_bt_player())) { tab->update_behavior_tree(data); } } else { @@ -294,11 +326,15 @@ bool LimboDebuggerPlugin::capture(const String &p_message, const Array &p_data, return captured; } +#ifdef LIMBOAI_MODULE bool LimboDebuggerPlugin::has_capture(const String &p_capture) const { +#else // LIMBOAI_GDEXTENSION +bool LimboDebuggerPlugin::_has_capture(const String &p_capture) const { +#endif return p_capture == "limboai"; } -WindowWrapper *LimboDebuggerPlugin::get_session_tab() const { +CompatWindowWrapper *LimboDebuggerPlugin::get_session_tab() const { return window_wrapper; } @@ -308,6 +344,10 @@ int LimboDebuggerPlugin::get_session_tab_index() const { return c->get_tab_idx_from_control(window_wrapper); } +void LimboDebuggerPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("_window_visibility_changed"), &LimboDebuggerPlugin::_window_visibility_changed); +} + LimboDebuggerPlugin::LimboDebuggerPlugin() { tab = nullptr; singleton = this; diff --git a/editor/debugger/limbo_debugger_plugin.h b/editor/debugger/limbo_debugger_plugin.h index b7078fe..4408272 100644 --- a/editor/debugger/limbo_debugger_plugin.h +++ b/editor/debugger/limbo_debugger_plugin.h @@ -9,14 +9,16 @@ * ============================================================================= */ -#ifdef TOOLS_ENABLED - #ifndef LIMBO_DEBUGGER_PLUGIN_H #define LIMBO_DEBUGGER_PLUGIN_H -#include "modules/limboai/editor/debugger/behavior_tree_data.h" -#include "modules/limboai/editor/debugger/behavior_tree_view.h" +#ifdef TOOLS_ENABLED +#include "../../editor/debugger/behavior_tree_data.h" +#include "../../editor/debugger/behavior_tree_view.h" +#include "../../gdextension/window_wrapper.h" + +#ifdef LIMBOAI_MODULE #include "core/object/class_db.h" #include "core/object/object.h" #include "core/typedefs.h" @@ -27,6 +29,23 @@ #include "scene/gui/panel_container.h" #include "scene/gui/split_container.h" #include "scene/gui/texture_rect.h" +#endif // ! LIMBOAI_MODULE + +#ifdef LIMBOAI_GDEXTENSION + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // ! LIMBOAI_GDEXTENSION class LimboDebuggerTab : public PanelContainer { GDCLASS(LimboDebuggerTab, PanelContainer); @@ -47,8 +66,9 @@ private: LineEdit *filter_players = nullptr; Button *resource_header = nullptr; Button *make_floating = nullptr; - WindowWrapper *window_wrapper = nullptr; + CompatWindowWrapper *window_wrapper = nullptr; + void _reset_controls(); void _show_alert(const String &p_message); void _update_bt_player_list(const List &p_node_paths, const String &p_filter); void _bt_selected(int p_idx); @@ -57,6 +77,7 @@ private: void _resource_header_pressed(); protected: + static void _bind_methods(); void _notification(int p_what); public: @@ -67,7 +88,8 @@ public: String get_selected_bt_player(); void update_behavior_tree(const BehaviorTreeData &p_data); - LimboDebuggerTab(Ref p_session, WindowWrapper *p_wrapper); + void setup(Ref p_session, CompatWindowWrapper *p_wrapper); + LimboDebuggerTab(); }; class LimboDebuggerPlugin : public EditorDebuggerPlugin { @@ -77,24 +99,36 @@ private: static LimboDebuggerPlugin *singleton; LimboDebuggerTab *tab = nullptr; - WindowWrapper *window_wrapper = nullptr; + + CompatWindowWrapper *window_wrapper = nullptr; void _window_visibility_changed(bool p_visible); +protected: + static void _bind_methods(); + public: static _FORCE_INLINE_ LimboDebuggerPlugin *get_singleton() { return singleton; } +#ifdef LIMBOAI_MODULE void setup_session(int p_idx) override; bool has_capture(const String &p_capture) const override; bool capture(const String &p_message, const Array &p_data, int p_session) override; +#endif // LIMBOAI_MODULE - WindowWrapper *get_session_tab() const; +#ifdef LIMBOAI_GDEXTENSION + void _setup_session(int32_t p_idx) override; + bool _has_capture(const String &p_capture) const override; + bool _capture(const String &p_message, const Array &p_data, int32_t p_session) override; +#endif // LIMBOAI_GDEXTENSION + + CompatWindowWrapper *get_session_tab() const; int get_session_tab_index() const; LimboDebuggerPlugin(); ~LimboDebuggerPlugin(); }; -#endif // LIMBO_DEBUGGER_PLUGIN +#endif // ! TOOLS_ENABLED -#endif // TOOLS_ENABLED \ No newline at end of file +#endif // ! LIMBO_DEBUGGER_PLUGIN_H diff --git a/editor/limbo_ai_editor_plugin.cpp b/editor/limbo_ai_editor_plugin.cpp index cf89716..0807630 100644 --- a/editor/limbo_ai_editor_plugin.cpp +++ b/editor/limbo_ai_editor_plugin.cpp @@ -18,9 +18,9 @@ #include "../bt/tasks/composites/bt_probability_selector.h" #include "../bt/tasks/composites/bt_selector.h" #include "../bt/tasks/decorators/bt_subtree.h" -#include "../util/limbo_compat.h" -// #include "../editor/debugger/limbo_debugger_plugin.h" // TODO: reenable when debugger is ready. +#include "../editor/debugger/limbo_debugger_plugin.h" #include "../editor/editor_property_bb_param.h" +#include "../util/limbo_compat.h" #include "../util/limbo_utility.h" #include "action_banner.h" @@ -1334,14 +1334,22 @@ void LimboAIEditorPlugin::_apply_changes() { limbo_ai_editor->apply_changes(); } +void LimboAIEditorPlugin::_bind_methods() { +} + void LimboAIEditorPlugin::_notification(int p_notification) { - if (p_notification == NOTIFICATION_ENTER_TREE) { - // Add BehaviorTree to the list of resources that should open in a new inspector. - PackedStringArray open_in_new_inspector = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector"); - if (!open_in_new_inspector.has("BehaviorTree")) { - open_in_new_inspector.push_back("BehaviorTree"); - EDITOR_SETTINGS()->set_setting("interface/inspector/resources_to_open_in_new_inspector", open_in_new_inspector); - } + switch (p_notification) { + case NOTIFICATION_READY: { + add_debugger_plugin(memnew(LimboDebuggerPlugin)); + } break; + case NOTIFICATION_ENTER_TREE: { + // Add BehaviorTree to the list of resources that should open in a new inspector. + PackedStringArray open_in_new_inspector = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector"); + if (!open_in_new_inspector.has("BehaviorTree")) { + open_in_new_inspector.push_back("BehaviorTree"); + EDITOR_SETTINGS()->set_setting("interface/inspector/resources_to_open_in_new_inspector", open_in_new_inspector); + } + } break; } } @@ -1381,7 +1389,6 @@ LimboAIEditorPlugin::LimboAIEditorPlugin() { limbo_ai_editor->hide(); limbo_ai_editor->set_plugin(this); -// add_debugger_plugin(memnew(LimboDebuggerPlugin)); // TODO: disabled for now #ifdef LIMBOAI_MODULE // ! Only used in the module version. add_inspector_plugin(memnew(EditorInspectorPluginBBParam)); diff --git a/editor/limbo_ai_editor_plugin.h b/editor/limbo_ai_editor_plugin.h index 2ce66e1..fd64132 100644 --- a/editor/limbo_ai_editor_plugin.h +++ b/editor/limbo_ai_editor_plugin.h @@ -221,7 +221,7 @@ private: LimboAIEditor *limbo_ai_editor; protected: - static void _bind_methods() {} + static void _bind_methods(); void _notification(int p_notification); public: diff --git a/gdextension/SConstruct b/gdextension/SConstruct index 209966c..21cf457 100644 --- a/gdextension/SConstruct +++ b/gdextension/SConstruct @@ -25,10 +25,9 @@ sources += (Glob("limboai/bt/tasks/composites/*.cpp")) sources += (Glob("limboai/bt/tasks/decorators/*.cpp")) sources += (Glob("limboai/bt/tasks/scene/*.cpp")) sources += (Glob("limboai/bt/tasks/utility/*.cpp")) +sources += (Glob("limboai/gdextension/*.cpp")) +sources += (Glob("limboai/editor/debugger/*.cpp")) sources += (Glob("limboai/editor/*.cpp")) -sources += (Glob("limboai/editor/debugger/behavior_tree_data.cpp")) -sources += (Glob("limboai/editor/debugger/behavior_tree_view.cpp")) -sources += (Glob("limboai/editor/debugger/limbo_debugger.cpp")) sources += (Glob("limboai/hsm/*.cpp")) sources += (Glob("limboai/util/*.cpp")) diff --git a/gdextension/window_wrapper.cpp b/gdextension/window_wrapper.cpp new file mode 100644 index 0000000..88e3e82 --- /dev/null +++ b/gdextension/window_wrapper.cpp @@ -0,0 +1,511 @@ +/**************************************************************************/ +/* window_wrapper.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "window_wrapper.h" + +#ifdef LIMBOAI_GDEXTENSION + +#include "../util/limbo_compat.h" +#include "../util/limbo_string_names.h" +#include "godot_cpp/core/error_macros.hpp" +#include +#include +#include +#include +#include +// #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace godot; +// #include "editor/editor_node.h" +// #include "editor/editor_scale.h" +// #include "editor/progress_dialog.h" + +// WindowWrapper + +void CompatShortcutBin::_notification(int what) { + switch (what) { + case NOTIFICATION_READY: + set_process_shortcut_input(true); + break; + } +} + +void CompatShortcutBin::_bind_methods() {} + +void CompatShortcutBin::_shortcut_input(const Ref &p_event) { + if (!get_window()->is_visible()) { + return; + } + + ERR_FAIL_NULL(get_parent()); + Viewport *vp = get_parent()->get_viewport(); + godot::Window *win = nullptr; + while (vp) { + win = Object::cast_to(vp); + if (win && win->is_visible()) { + break; + } + if (!vp->get_parent()) { + break; + } + + vp = vp->get_parent()->get_viewport(); + } + godot::Window *grandparent_window = win; + + ERR_FAIL_NULL(grandparent_window); + + if (Object::cast_to(p_event.ptr()) || Object::cast_to(p_event.ptr())) { + // HACK: Propagate the window input to the editor main window to handle global shortcuts. + grandparent_window->push_input(p_event); + + if (grandparent_window->is_input_handled()) { + get_viewport()->set_input_as_handled(); + } + } +} + +Rect2 CompatWindowWrapper::_get_default_window_rect() const { + ERR_FAIL_COND_V(!is_inside_tree(), Rect2()); + + // Assume that the control rect is the desidered one for the window. + Transform2D xform = get_screen_transform(); + return Rect2(xform.get_origin(), xform.get_scale() * get_size()); +} + +Node *CompatWindowWrapper::_get_wrapped_control_parent() const { + if (margins) { + return margins; + } + return window; +} + +void CompatWindowWrapper::_set_window_enabled_with_rect(bool p_visible, const Rect2 p_rect) { + ERR_FAIL_NULL(wrapped_control); + + if (!is_window_available()) { + return; + } + + if (window->is_visible() == p_visible) { + if (p_visible) { + window->grab_focus(); + } + return; + } + + Node *parent = _get_wrapped_control_parent(); + + if (wrapped_control->get_parent() != parent) { + // Move the control to the window. + wrapped_control->reparent(parent, false); + + _set_window_rect(p_rect); + wrapped_control->set_anchors_and_offsets_preset(PRESET_FULL_RECT); + + } else if (!p_visible) { + // Remove control from window. + wrapped_control->reparent(this, false); + } + + window->set_visible(p_visible); + if (!p_visible) { + emit_signal("window_close_requested"); + } + emit_signal("window_visibility_changed", p_visible); +} + +void CompatWindowWrapper::_set_window_rect(const Rect2 p_rect) { + // Set the window rect even when the window is maximized to have a good default size + // when the user remove the maximized mode. + window->set_position(p_rect.position); + window->set_size(p_rect.size); + + if (EDITOR_GET("interface/multi_window/maximize_window")) { + window->set_mode(godot::Window::MODE_MAXIMIZED); + } +} + +void CompatWindowWrapper::_shortcut_input(const Ref &p_event) { + if (enable_shortcut.is_valid() && enable_shortcut->matches_event(p_event)) { + set_window_enabled(true); + } +} + +void CompatWindowWrapper::set_wrapped_control(Control *p_control, const Ref &p_enable_shortcut) { + ERR_FAIL_NULL(p_control); + ERR_FAIL_COND(wrapped_control); + + wrapped_control = p_control; + enable_shortcut = p_enable_shortcut; + add_child(p_control); +} + +Control *CompatWindowWrapper::get_wrapped_control() const { + return wrapped_control; +} + +Control *CompatWindowWrapper::release_wrapped_control() { + set_window_enabled(false); + if (wrapped_control) { + Control *old_wrapped = wrapped_control; + wrapped_control->get_parent()->remove_child(wrapped_control); + wrapped_control = nullptr; + + return old_wrapped; + } + return nullptr; +} + +bool CompatWindowWrapper::is_window_available() const { + return window != nullptr; +} + +bool CompatWindowWrapper::get_window_enabled() const { + return is_window_available() ? window->is_visible() : false; +} + +void CompatWindowWrapper::set_window_enabled(bool p_enabled) { + _set_window_enabled_with_rect(p_enabled, _get_default_window_rect()); +} + +Rect2i CompatWindowWrapper::get_window_rect() const { + ERR_FAIL_COND_V(!get_window_enabled(), Rect2i()); + return Rect2i(window->get_position(), window->get_size()); +} + +int CompatWindowWrapper::get_window_screen() const { + ERR_FAIL_COND_V(!get_window_enabled(), -1); + return window->get_current_screen(); +} + +void CompatWindowWrapper::restore_window(const Rect2i &p_rect, int p_screen) { + ERR_FAIL_COND(!is_window_available()); + ERR_FAIL_INDEX(p_screen, DisplayServer::get_singleton()->get_screen_count()); + + _set_window_enabled_with_rect(true, p_rect); + window->set_current_screen(p_screen); +} + +void CompatWindowWrapper::restore_window_from_saved_position(const Rect2 p_window_rect, int p_screen, const Rect2 p_screen_rect) { + ERR_FAIL_COND(!is_window_available()); + + Rect2 window_rect = p_window_rect; + int screen = p_screen; + Rect2 restored_screen_rect = p_screen_rect; + + if (screen < 0 || screen >= DisplayServer::get_singleton()->get_screen_count()) { + // Fallback to the main window screen if the saved screen is not available. + screen = get_window()->get_window_id(); + } + + Rect2i real_screen_rect = DisplayServer::get_singleton()->screen_get_usable_rect(screen); + + if (restored_screen_rect == Rect2i()) { + // Fallback to the target screen rect. + restored_screen_rect = real_screen_rect; + } + + if (window_rect == Rect2i()) { + // Fallback to a standard rect. + window_rect = Rect2i(restored_screen_rect.position + restored_screen_rect.size / 4, restored_screen_rect.size / 2); + } + + // Adjust the window rect size in case the resolution changes. + Vector2 screen_ratio = Vector2(real_screen_rect.size) / Vector2(restored_screen_rect.size); + + // The screen positioning may change, so remove the original screen position. + window_rect.position -= restored_screen_rect.position; + window_rect = Rect2i(window_rect.position * screen_ratio, window_rect.size * screen_ratio); + window_rect.position += real_screen_rect.position; + + // All good, restore the window. + window->set_current_screen(p_screen); + if (window->is_visible()) { + _set_window_rect(window_rect); + } else { + _set_window_enabled_with_rect(true, window_rect); + } +} + +void CompatWindowWrapper::enable_window_on_screen(int p_screen, bool p_auto_scale) { + int current_screen = Object::cast_to(get_viewport())->get_current_screen(); + int screen = p_screen < 0 ? current_screen : p_screen; + + bool auto_scale = p_auto_scale && !EDITOR_GET("interface/multi_window/maximize_window"); + + if (auto_scale && current_screen != screen) { + Rect2 control_rect = _get_default_window_rect(); + + Rect2i source_screen_rect = DisplayServer::get_singleton()->screen_get_usable_rect(current_screen); + Rect2i dest_screen_rect = DisplayServer::get_singleton()->screen_get_usable_rect(screen); + + // Adjust the window rect size in case the resolution changes. + Vector2 screen_ratio = Vector2(source_screen_rect.size) / Vector2(dest_screen_rect.size); + + // The screen positioning may change, so remove the original screen position. + control_rect.position -= source_screen_rect.position; + control_rect = Rect2i(control_rect.position * screen_ratio, control_rect.size * screen_ratio); + control_rect.position += dest_screen_rect.position; + + restore_window(control_rect, p_screen); + } else { + window->set_current_screen(p_screen); + set_window_enabled(true); + } +} + +void CompatWindowWrapper::set_window_title(const String p_title) { + if (!is_window_available()) { + return; + } + window->set_title(p_title); +} + +void CompatWindowWrapper::set_margins_enabled(bool p_enabled) { + if (!is_window_available()) { + return; + } + + if (!p_enabled && margins) { + margins->queue_free(); + margins = nullptr; + } else if (p_enabled && !margins) { + Size2 borders = Size2(4, 4) * EDSCALE; + margins = memnew(MarginContainer); + margins->add_theme_constant_override("margin_right", borders.width); + margins->add_theme_constant_override("margin_top", borders.height); + margins->add_theme_constant_override("margin_left", borders.width); + margins->add_theme_constant_override("margin_bottom", borders.height); + + window->add_child(margins); + margins->set_anchors_and_offsets_preset(PRESET_FULL_RECT); + } +} + +void CompatWindowWrapper::_bind_methods() { + ADD_SIGNAL(MethodInfo("window_visibility_changed", PropertyInfo(Variant::BOOL, "visible"))); + ADD_SIGNAL(MethodInfo("window_close_requested")); +} + +void CompatWindowWrapper::_notification(int p_what) { + if (!is_window_available()) { + return; + } + switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + if (get_window_enabled() && is_visible()) { + // Grab the focus when WindowWrapper.set_visible(true) is called + // and the window is showing. + window->grab_focus(); + } + } break; + case NOTIFICATION_READY: { + set_process_shortcut_input(true); + window->connect("close_requested", callable_mp(this, &CompatWindowWrapper::set_window_enabled).bind(false)); + + } break; + case NOTIFICATION_THEME_CHANGED: { + window_background->add_theme_stylebox_override("panel", get_theme_stylebox("PanelForeground", LW_NAME(EditorStyles))); + } break; + } +} + +CompatWindowWrapper::CompatWindowWrapper() { + if (SCENE_TREE()->get_root()->is_embedding_subwindows() || EDITOR_GET("interface/editor/single_window_mode") || !EDITOR_GET("interface/multi_window/enable")) { + return; + } + + window = memnew(godot::Window); + window->set_wrap_controls(true); + + add_child(window); + window->hide(); + + CompatShortcutBin *capturer = memnew(CompatShortcutBin); + window->add_child(capturer); + + window_background = memnew(Panel); + window_background->set_anchors_and_offsets_preset(PRESET_FULL_RECT); + window->add_child(window_background); + + // ProgressDialog::get_singleton()->add_host_window(window); +} + +// LWScreenSelect + +void CompatScreenSelect::_build_advanced_menu() { + // Clear old screen list. + while (screen_list->get_child_count(false) > 0) { + Node *child = screen_list->get_child(0); + screen_list->remove_child(child); + child->queue_free(); + } + + // Populate screen list. + const real_t height = real_t(get_theme_font_size("font_size")) * 1.5; + + int current_screen = get_window()->get_current_screen(); + for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) { + Button *button = memnew(Button); + + Size2 screen_size = Size2(DisplayServer::get_singleton()->screen_get_size(i)); + Size2 button_size = Size2(height * (screen_size.x / screen_size.y), height); + button->set_custom_minimum_size(button_size); + screen_list->add_child(button); + + button->set_text(itos(i)); + button->set_text_alignment(HORIZONTAL_ALIGNMENT_CENTER); + button->set_tooltip_text(vformat(TTR("Make this panel floating in the screen %d."), i)); + + if (i == current_screen) { + Color accent_color = get_theme_color("accent_color", LW_NAME(Editor)); + button->add_theme_color_override("font_color", accent_color); + } + + button->connect("pressed", callable_mp(this, &CompatScreenSelect::_emit_screen_signal).bind(i)); + button->connect("pressed", callable_mp(static_cast(this), &CompatScreenSelect::set_pressed).bind(false)); + button->connect("pressed", callable_mp(static_cast(popup), &Popup::hide)); + } +} + +void CompatScreenSelect::_emit_screen_signal(int p_screen_idx) { + emit_signal("request_open_in_screen", p_screen_idx); +} + +void CompatScreenSelect::_bind_methods() { + ADD_SIGNAL(MethodInfo("request_open_in_screen", PropertyInfo(Variant::INT, "screen"))); +} + +void CompatScreenSelect::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + connect("gui_input", callable_mp(this, &CompatScreenSelect::_handle_mouse_shortcut)); + popup->connect("popup_hide", callable_mp(static_cast(this), &CompatScreenSelect::set_pressed).bind(false)); + } break; + case NOTIFICATION_THEME_CHANGED: { + set_button_icon(get_theme_icon("MakeFloating", LW_NAME(EditorIcons))); + popup_background->add_theme_stylebox_override("panel", get_theme_stylebox("PanelForeground", LW_NAME(EditorStyles))); + + const real_t popup_height = real_t(get_theme_font_size("font_size")) * 2.0; + popup->set_min_size(Size2(0, popup_height * 3)); + } break; + } +} + +void CompatScreenSelect::_handle_mouse_shortcut(const Ref &p_event) { + const Ref mouse_button = p_event; + if (mouse_button.is_valid()) { + if (mouse_button->is_pressed() && mouse_button->get_button_index() == LW_MBTN(LEFT)) { + _emit_screen_signal(get_window()->get_current_screen()); + accept_event(); + } + } +} + +void CompatScreenSelect::_show_popup() { + // Adapted from /scene/gui/menu_button.cpp::show_popup + if (!get_viewport()) { + return; + } + + Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale(); + + popup->set_size(Size2(size.width, 0)); + Point2 gp = get_screen_position(); + gp.y += size.y; + if (is_layout_rtl()) { + gp.x += size.width - popup->get_size().width; + } + popup->set_position(gp); + popup->popup(); +} + +void CompatScreenSelect::_pressed() { + if (popup->is_visible()) { + popup->hide(); + return; + } + + _build_advanced_menu(); + _show_popup(); +} + +CompatScreenSelect::CompatScreenSelect() { + set_tooltip_text(TTR("Make this panel floating.\nRight click to open the screen selector.")); + set_button_mask(LW_MBTN(RIGHT)); + set_flat(true); + set_toggle_mode(true); + set_focus_mode(FOCUS_NONE); + set_action_mode(ACTION_MODE_BUTTON_PRESS); + + // Create the popup. + const Size2 borders = Size2(4, 4) * EDSCALE; + + popup = memnew(Popup); + add_child(popup); + + popup_background = memnew(Panel); + popup_background->set_anchors_and_offsets_preset(PRESET_FULL_RECT); + popup->add_child(popup_background); + + MarginContainer *popup_root = memnew(MarginContainer); + popup_root->add_theme_constant_override("margin_right", borders.width); + popup_root->add_theme_constant_override("margin_top", borders.height); + popup_root->add_theme_constant_override("margin_left", borders.width); + popup_root->add_theme_constant_override("margin_bottom", borders.height); + popup->add_child(popup_root); + + VBoxContainer *vb = memnew(VBoxContainer); + vb->set_alignment(BoxContainer::ALIGNMENT_CENTER); + popup_root->add_child(vb); + + Label *description = memnew(Label); + description->set_text(TTR("Select Screen")); + description->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); + vb->add_child(description); + + screen_list = memnew(godot::HBoxContainer); + screen_list->set_alignment(BoxContainer::ALIGNMENT_CENTER); + vb->add_child(screen_list); + + popup_root->set_anchors_and_offsets_preset(PRESET_FULL_RECT); +} + +#endif // ! LIMBOAI_GDEXTENSION \ No newline at end of file diff --git a/gdextension/window_wrapper.h b/gdextension/window_wrapper.h new file mode 100644 index 0000000..5aed1d5 --- /dev/null +++ b/gdextension/window_wrapper.h @@ -0,0 +1,138 @@ +/**************************************************************************/ +/* window_wrapper.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +// * This is a port of a WindowWrapper from the Godot Engine to use with godot-cpp. + +#ifdef LIMBOAI_GDEXTENSION + +#ifndef COMPAT_WINDOW_WRAPPER_H +#define COMPAT_WINDOW_WRAPPER_H + +// TODO: Need to compile this as module too!!! + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace godot; + +// Capture all shortcut events not handled by other nodes. +class CompatShortcutBin : public Node { + GDCLASS(CompatShortcutBin, Node); + +protected: + virtual void _notification(int what); + + static void _bind_methods(); + +public: + virtual void _shortcut_input(const Ref &p_event) override; +}; + +class CompatWindowWrapper : public MarginContainer { + GDCLASS(CompatWindowWrapper, MarginContainer); + + Control *wrapped_control = nullptr; + MarginContainer *margins = nullptr; + godot::Window *window = nullptr; + + Panel *window_background = nullptr; + + Ref enable_shortcut; + + Rect2 _get_default_window_rect() const; + Node *_get_wrapped_control_parent() const; + + void _set_window_enabled_with_rect(bool p_visible, const Rect2 p_rect); + void _set_window_rect(const Rect2 p_rect); + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + virtual void _shortcut_input(const Ref &p_event) override; + + void set_wrapped_control(Control *p_control, const Ref &p_enable_shortcut = Ref()); + Control *get_wrapped_control() const; + Control *release_wrapped_control(); + + bool is_window_available() const; + + bool get_window_enabled() const; + void set_window_enabled(bool p_enabled); + + Rect2i get_window_rect() const; + int get_window_screen() const; + + void restore_window(const Rect2i &p_rect, int p_screen = -1); + void restore_window_from_saved_position(const Rect2 p_window_rect, int p_screen, const Rect2 p_screen_rect); + void enable_window_on_screen(int p_screen = -1, bool p_auto_scale = false); + + void set_window_title(const String p_title); + void set_margins_enabled(bool p_enabled); + + CompatWindowWrapper(); +}; + +class CompatScreenSelect : public Button { + GDCLASS(CompatScreenSelect, Button); + + Popup *popup = nullptr; + Panel *popup_background = nullptr; + godot::HBoxContainer *screen_list = nullptr; + + void _build_advanced_menu(); + + void _emit_screen_signal(int p_screen_idx); + void _handle_mouse_shortcut(const Ref &p_event); + void _show_popup(); + +protected: + static void _bind_methods(); + + void _notification(int p_what); + +public: + virtual void _pressed() override; + + CompatScreenSelect(); +}; + +#endif // ! COMPAT_WINDOW_WRAPPER_H + +#endif // ! LIMBOAI_GDEXTENSION diff --git a/register_types.cpp b/register_types.cpp index e9b045c..64bb980 100644 --- a/register_types.cpp +++ b/register_types.cpp @@ -93,6 +93,7 @@ #include "editor/action_banner.h" #include "editor/debugger/behavior_tree_data.h" #include "editor/debugger/limbo_debugger.h" +#include "editor/debugger/limbo_debugger_plugin.h" #include "editor/mode_switch_button.h" #include "hsm/limbo_hsm.h" #include "hsm/limbo_state.h" @@ -227,20 +228,28 @@ void initialize_limboai_module(ModuleInitializationLevel p_level) { #ifdef LIMBOAI_MODULE Engine::get_singleton()->add_singleton(Engine::Singleton("LimboUtility", LimboUtility::get_singleton())); +#else // LIMBOAI_GDEXTENSION + Engine::get_singleton()->register_singleton("LimboUtility", LimboUtility::get_singleton()); #endif + LimboStringNames::create(); } #ifdef TOOLS_ENABLED if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) { #ifdef LIMBOAI_GDEXTENSION - // GDREGISTER_CLASS(BehaviorTreeView); GDREGISTER_CLASS(TaskTree); GDREGISTER_CLASS(TaskButton); GDREGISTER_CLASS(TaskPaletteSection); GDREGISTER_CLASS(TaskPalette); GDREGISTER_CLASS(ActionBanner); GDREGISTER_CLASS(ModeSwitchButton); + GDREGISTER_CLASS(CompatShortcutBin); + GDREGISTER_CLASS(CompatScreenSelect); + GDREGISTER_CLASS(CompatWindowWrapper); + GDREGISTER_CLASS(BehaviorTreeView); + GDREGISTER_CLASS(LimboDebuggerTab); + GDREGISTER_CLASS(LimboDebuggerPlugin); GDREGISTER_CLASS(LimboAIEditor); GDREGISTER_CLASS(LimboAIEditorPlugin); #endif // ! LIMBOAI_GDEXTENSION diff --git a/util/limbo_compat.h b/util/limbo_compat.h index e4b3300..b25491c 100644 --- a/util/limbo_compat.h +++ b/util/limbo_compat.h @@ -30,6 +30,7 @@ #define MAIN_SCREEN_CONTROL(EditorNode::get_singleton()->get_main_screen_control()) #define SCENE_TREE() (SceneTree::get_singleton()) #define IS_DEBUGGER_ACTIVE() (EngineDebugger::is_active()) +#define FS_DOCK_SELECT_FILE(m_path) FileSystemDock::get_singleton()->select_file(m_path) #define PRINT_LINE(...) (print_line(__VA_ARGS__)) #define IS_CLASS(m_obj, m_class) (m_obj->is_class_ptr(m_class::get_class_ptr_static())) @@ -78,6 +79,7 @@ using namespace godot; #define MAIN_SCREEN_CONTROL() (EditorInterface::get_singleton()->get_editor_main_screen()) #define SCENE_TREE() ((SceneTree *)(Engine::get_singleton()->get_main_loop())) #define IS_DEBUGGER_ACTIVE() (EngineDebugger::get_singleton()->is_active()) +#define FS_DOCK_SELECT_FILE(m_path) EditorInterface::get_singleton()->get_file_system_dock()->navigate_to_path(m_path) #define PRINT_LINE(...) (UtilityFunctions::print(__VA_ARGS__)) #define IS_CLASS(m_obj, m_class) (m_obj->get_class_static() == m_class::get_class_static()) diff --git a/util/limbo_string_names.cpp b/util/limbo_string_names.cpp index 3f990ac..d48f948 100644 --- a/util/limbo_string_names.cpp +++ b/util/limbo_string_names.cpp @@ -62,6 +62,7 @@ LimboStringNames::LimboStringNames() { Editor = SN("Editor"); EditorFonts = SN("EditorFonts"); EditorIcons = SN("EditorIcons"); + EditorStyles = SN("EditorStyles"); emit_changed = SN("emit_changed"); entered = SN("entered"); error_value = SN("error_value"); @@ -79,6 +80,7 @@ LimboStringNames::LimboStringNames() { icon_max_width = SN("icon_max_width"); id_pressed = SN("id_pressed"); item_collapsed = SN("item_collapsed"); + item_selected = SN("item_selected"); LimboDeselectAll = SN("LimboDeselectAll"); LimboExtraClock = SN("LimboExtraClock"); LimboPercent = SN("LimboPercent"); @@ -102,6 +104,7 @@ LimboStringNames::LimboStringNames() { Remove = SN("Remove"); remove_child = SN("remove_child"); Rename = SN("Rename"); + request_open_in_screen = SN("request_open_in_screen"); rmb_pressed = SN("rmb_pressed"); Save = SN("Save"); Script = SN("Script"); @@ -110,8 +113,10 @@ LimboStringNames::LimboStringNames() { set_custom_name = SN("set_custom_name"); set_root_task = SN("set_root_task"); setup = SN("setup"); + started = SN("started"); state_changed = SN("state_changed"); StatusWarning = SN("StatusWarning"); + stopped = SN("stopped"); task_activated = SN("task_activated"); task_button_pressed = SN("task_button_pressed"); task_button_rmb = SN("task_button_rmb"); @@ -125,6 +130,7 @@ LimboStringNames::LimboStringNames() { update_tree = SN("update_tree"); updated = SN("updated"); visibility_changed = SN("visibility_changed"); + window_visibility_changed = SN("window_visibility_changed"); EVENT_FINISHED = "finished"; repeat_forever.parse_utf8("Repeat ∞"); diff --git a/util/limbo_string_names.h b/util/limbo_string_names.h index 5e6c921..9ff4a7e 100644 --- a/util/limbo_string_names.h +++ b/util/limbo_string_names.h @@ -77,6 +77,7 @@ public: StringName Editor; StringName EditorFonts; StringName EditorIcons; + StringName EditorStyles; StringName emit_changed; StringName entered; StringName error_value; @@ -94,6 +95,7 @@ public: StringName icon_max_width; StringName id_pressed; StringName item_collapsed; + StringName item_selected; StringName LimboDeselectAll; StringName LimboExtraClock; StringName LimboExtractSubtree; @@ -118,6 +120,7 @@ public: StringName remove_child; StringName Remove; StringName Rename; + StringName request_open_in_screen; StringName rmb_pressed; StringName Save; StringName Script; @@ -126,8 +129,10 @@ public: StringName set_custom_name; StringName set_root_task; StringName setup; + StringName started; StringName state_changed; StringName StatusWarning; + StringName stopped; StringName task_activated; StringName task_button_pressed; StringName task_button_rmb; @@ -142,6 +147,7 @@ public: StringName update_tree; StringName updated; StringName visibility_changed; + StringName window_visibility_changed; String EVENT_FINISHED; String repeat_forever;