Compare commits

..

1 Commits

Author SHA1 Message Date
Legendsmith bae9ff8a30
Merge bbdafa9033 into f90c48eb81 2024-11-02 20:14:45 +01:00
4 changed files with 61 additions and 123 deletions

View File

@ -67,7 +67,6 @@
#include <godot_cpp/classes/ref_counted.hpp> #include <godot_cpp/classes/ref_counted.hpp>
#include <godot_cpp/classes/resource_loader.hpp> #include <godot_cpp/classes/resource_loader.hpp>
#include <godot_cpp/classes/resource_saver.hpp> #include <godot_cpp/classes/resource_saver.hpp>
#include <godot_cpp/classes/scene_tree.hpp>
#include <godot_cpp/classes/script.hpp> #include <godot_cpp/classes/script.hpp>
#include <godot_cpp/classes/script_editor.hpp> #include <godot_cpp/classes/script_editor.hpp>
#include <godot_cpp/classes/script_editor_base.hpp> #include <godot_cpp/classes/script_editor_base.hpp>
@ -75,21 +74,6 @@
#include <godot_cpp/core/error_macros.hpp> #include <godot_cpp/core/error_macros.hpp>
#endif // LIMBOAI_GDEXTENSION #endif // LIMBOAI_GDEXTENSION
namespace {
// If built-in resource - switch to the owner scene (open it if not already).
inline void _switch_to_owner_scene_if_builtin(const Ref<BehaviorTree> &p_behavior_tree) {
if (p_behavior_tree.is_valid() && p_behavior_tree->get_path().contains("::")) {
String current_scene = SCENE_TREE()->get_edited_scene_root()->get_scene_file_path();
String scene_path = p_behavior_tree->get_path().get_slice("::", 0);
if (current_scene != scene_path) {
EditorInterface::get_singleton()->open_scene_from_path(scene_path);
}
}
}
} // unnamed namespace
//**** LimboAIEditor //**** LimboAIEditor
_FORCE_INLINE_ String _get_script_template_path() { _FORCE_INLINE_ String _get_script_template_path() {
@ -114,7 +98,7 @@ void LimboAIEditor::_commit_action_with_update(EditorUndoRedoManager *p_undo_red
p_undo_redo->add_do_method(this, LW_NAME(_update_task_tree), task_tree->get_bt()); p_undo_redo->add_do_method(this, LW_NAME(_update_task_tree), task_tree->get_bt());
p_undo_redo->add_undo_method(this, LW_NAME(_update_task_tree), task_tree->get_bt()); p_undo_redo->add_undo_method(this, LW_NAME(_update_task_tree), task_tree->get_bt());
p_undo_redo->commit_action(); p_undo_redo->commit_action();
_set_as_dirty(task_tree->get_bt(), true); _mark_as_dirty(true);
} }
void LimboAIEditor::_add_task(const Ref<BTTask> &p_task, bool p_as_sibling) { void LimboAIEditor::_add_task(const Ref<BTTask> &p_task, bool p_as_sibling) {
@ -218,58 +202,20 @@ void LimboAIEditor::_new_bt() {
EDIT_RESOURCE(bt); EDIT_RESOURCE(bt);
} }
void LimboAIEditor::_save_bt(const Ref<BehaviorTree> &p_bt, const String &p_path) { void LimboAIEditor::_save_bt(String p_path) {
ERR_FAIL_COND(p_path.is_empty()); ERR_FAIL_COND_MSG(p_path.is_empty(), "Empty p_path");
ERR_FAIL_COND(!p_path.begins_with("res://")); ERR_FAIL_COND_MSG(task_tree->get_bt().is_null(), "Behavior Tree is null.");
ERR_FAIL_COND(p_bt.is_null());
if (p_bt->get_path() != p_path) {
#ifdef LIMBOAI_MODULE #ifdef LIMBOAI_MODULE
task_tree->get_bt()->set_path(p_path, true); task_tree->get_bt()->set_path(p_path, true);
#elif LIMBOAI_GDEXTENSION #elif LIMBOAI_GDEXTENSION
task_tree->get_bt()->take_over_path(p_path); task_tree->get_bt()->take_over_path(p_path);
#endif #endif
} RESOURCE_SAVE(task_tree->get_bt(), p_path, ResourceSaver::FLAG_CHANGE_PATH);
// This is a workaround, because EditorNode::save_resource() function is not accessible in GDExtension.
if (RESOURCE_IS_BUILT_IN(p_bt)) {
// If built-in resource - save the containing resource instead.
String file_path = p_path.get_slice("::", 0);
ERR_FAIL_COND_MSG(!RESOURCE_EXISTS(file_path, "Resource"), "LimboAI: SAVE FAILED - resource file doesn't exist: " + file_path);
if (RESOURCE_IS_SCENE_FILE(file_path)) {
// Packed scene - save the scene instead.
if (EditorInterface::get_singleton()->get_open_scenes().has(file_path)) {
// If scene is open, switch to it first, and then ask to save.
// This is needed because saving the currently edited scene can have complications.
EditorInterface::get_singleton()->open_scene_from_path(file_path);
EditorInterface::get_singleton()->save_scene();
} else {
// If scene is not currently open in the editor, load and resave it.
Ref<Resource> scene = RESOURCE_LOAD(file_path, "PackedScene");
RESOURCE_SAVE(scene, file_path, ResourceSaver::FLAG_NONE);
}
} else {
// Not a packed scene - save the containing resource to file.
Ref<Resource> res = RESOURCE_LOAD(file_path, "Resource");
RESOURCE_SAVE(res, file_path, ResourceSaver::FLAG_NONE);
}
} else {
// If external resource - save to file.
RESOURCE_SAVE(p_bt, p_path, ResourceSaver::FLAG_CHANGE_PATH);
}
_set_as_dirty(p_bt, false);
_update_tabs(); _update_tabs();
_mark_as_dirty(false);
} }
void LimboAIEditor::_save_current_bt(const String &p_path) { void LimboAIEditor::_load_bt(String p_path) {
ERR_FAIL_COND_MSG(p_path.is_empty(), "LimboAI: SAVE FAILED - p_path is empty");
ERR_FAIL_COND_MSG(task_tree->get_bt().is_null(), "LimboAI: SAVE FAILED - bt is null");
_save_bt(task_tree->get_bt(), p_path);
}
void LimboAIEditor::_load_bt(const String &p_path) {
ERR_FAIL_COND_MSG(p_path.is_empty(), "Empty p_path"); ERR_FAIL_COND_MSG(p_path.is_empty(), "Empty p_path");
Ref<BehaviorTree> bt = RESOURCE_LOAD(p_path, "BehaviorTree"); Ref<BehaviorTree> bt = RESOURCE_LOAD(p_path, "BehaviorTree");
ERR_FAIL_COND(!bt.is_valid()); ERR_FAIL_COND(!bt.is_valid());
@ -308,8 +254,6 @@ void LimboAIEditor::_disable_editing() {
void LimboAIEditor::edit_bt(const Ref<BehaviorTree> &p_behavior_tree, bool p_force_refresh) { void LimboAIEditor::edit_bt(const Ref<BehaviorTree> &p_behavior_tree, bool p_force_refresh) {
ERR_FAIL_COND_MSG(p_behavior_tree.is_null(), "p_behavior_tree is null"); ERR_FAIL_COND_MSG(p_behavior_tree.is_null(), "p_behavior_tree is null");
_switch_to_owner_scene_if_builtin(p_behavior_tree);
if (!p_force_refresh && task_tree->get_bt() == p_behavior_tree) { if (!p_force_refresh && task_tree->get_bt() == p_behavior_tree) {
return; return;
} }
@ -325,8 +269,8 @@ void LimboAIEditor::edit_bt(const Ref<BehaviorTree> &p_behavior_tree, bool p_for
task_tree->load_bt(p_behavior_tree); task_tree->load_bt(p_behavior_tree);
if (task_tree->get_bt().is_valid() && !task_tree->get_bt()->is_connected(LW_NAME(changed), callable_mp(this, &LimboAIEditor::_set_as_dirty))) { if (task_tree->get_bt().is_valid() && !task_tree->get_bt()->is_connected(LW_NAME(changed), callable_mp(this, &LimboAIEditor::_mark_as_dirty))) {
task_tree->get_bt()->connect(LW_NAME(changed), callable_mp(this, &LimboAIEditor::_set_as_dirty).bind(task_tree->get_bt(), true)); task_tree->get_bt()->connect(LW_NAME(changed), callable_mp(this, &LimboAIEditor::_mark_as_dirty).bind(true));
} }
int idx = history.find(p_behavior_tree); int idx = history.find(p_behavior_tree);
@ -391,11 +335,12 @@ void LimboAIEditor::get_window_layout(const Ref<ConfigFile> &p_configuration) {
p_configuration->set_value("LimboAI", "bteditor_hsplit", split_offset); p_configuration->set_value("LimboAI", "bteditor_hsplit", split_offset);
} }
void LimboAIEditor::_set_as_dirty(const Ref<BehaviorTree> &p_bt, bool p_dirty) { void LimboAIEditor::_mark_as_dirty(bool p_dirty) {
if (p_dirty && !dirty.has(p_bt)) { Ref<BehaviorTree> bt = task_tree->get_bt();
dirty.insert(p_bt); if (p_dirty && !dirty.has(bt)) {
} else if (p_dirty == false && dirty.has(p_bt)) { dirty.insert(bt);
dirty.erase(p_bt); } else if (p_dirty == false && dirty.has(bt)) {
dirty.erase(bt);
} }
} }
@ -495,14 +440,6 @@ void LimboAIEditor::_process_shortcut_input(const Ref<InputEvent> &p_event) {
} else if (LW_IS_SHORTCUT("limbo_ai/close_tab", p_event)) { } else if (LW_IS_SHORTCUT("limbo_ai/close_tab", p_event)) {
_tab_menu_option_selected(TAB_CLOSE); _tab_menu_option_selected(TAB_CLOSE);
handled = true; handled = true;
} else if (LW_IS_SHORTCUT("limbo_ai/editor_save_scene", p_event)) {
// This intercepts the editor save action, but does not set the event as handled because we don't know the user's intention.
// We just want to save the currently edited BT as well, which may cause a loop with built-in resource if done from "_save_external_data".
// Workaround for: https://github.com/limbonaut/limboai/issues/240#issuecomment-2453087424
if (task_tree->get_bt().is_valid() && RESOURCE_IS_BUILT_IN(task_tree->get_bt())) {
_on_save_pressed();
}
handled = false; // intentionally not set as handled
} }
} }
@ -901,7 +838,6 @@ void LimboAIEditor::_on_tree_task_activated() {
void LimboAIEditor::_on_visibility_changed() { void LimboAIEditor::_on_visibility_changed() {
if (task_tree->is_visible_in_tree()) { if (task_tree->is_visible_in_tree()) {
_switch_to_owner_scene_if_builtin(task_tree->get_bt());
Ref<BTTask> sel = task_tree->get_selected(); Ref<BTTask> sel = task_tree->get_selected();
if (sel.is_valid()) { if (sel.is_valid()) {
EDIT_RESOURCE(sel); EDIT_RESOURCE(sel);
@ -919,6 +855,16 @@ void LimboAIEditor::_on_visibility_changed() {
} }
} }
void LimboAIEditor::_on_header_pressed() {
task_tree->clear_selection();
#ifdef LIMBOAI_MODULE
if (task_tree->get_bt().is_valid()) {
task_tree->get_bt()->editor_set_section_unfold("blackboard_plan", true);
}
#endif // LIMBOAI_MODULE
EDIT_RESOURCE(task_tree->get_bt());
}
void LimboAIEditor::_on_save_pressed() { void LimboAIEditor::_on_save_pressed() {
if (task_tree->get_bt().is_null()) { if (task_tree->get_bt().is_null()) {
return; return;
@ -927,7 +873,7 @@ void LimboAIEditor::_on_save_pressed() {
if (path.is_empty()) { if (path.is_empty()) {
save_dialog->popup_centered_ratio(); save_dialog->popup_centered_ratio();
} else { } else {
_save_current_bt(path); _save_bt(path);
} }
} }
@ -1115,8 +1061,8 @@ void LimboAIEditor::_tab_clicked(int p_tab) {
void LimboAIEditor::_tab_closed(int p_tab) { void LimboAIEditor::_tab_closed(int p_tab) {
ERR_FAIL_INDEX(p_tab, history.size()); ERR_FAIL_INDEX(p_tab, history.size());
Ref<BehaviorTree> history_bt = history[p_tab]; Ref<BehaviorTree> history_bt = history[p_tab];
if (history_bt.is_valid() && history_bt->is_connected(LW_NAME(changed), callable_mp(this, &LimboAIEditor::_set_as_dirty))) { if (history_bt.is_valid() && history_bt->is_connected(LW_NAME(changed), callable_mp(this, &LimboAIEditor::_mark_as_dirty))) {
history_bt->disconnect(LW_NAME(changed), callable_mp(this, &LimboAIEditor::_set_as_dirty)); history_bt->disconnect(LW_NAME(changed), callable_mp(this, &LimboAIEditor::_mark_as_dirty));
} }
if (tab_search_context.has(history_bt)) { if (tab_search_context.has(history_bt)) {
tab_search_context.erase(history_bt); tab_search_context.erase(history_bt);
@ -1296,13 +1242,10 @@ void LimboAIEditor::_reload_modified() {
void LimboAIEditor::_resave_modified(String _str) { void LimboAIEditor::_resave_modified(String _str) {
for (const String &res_path : disk_changed_files) { for (const String &res_path : disk_changed_files) {
Ref<BehaviorTree> bt = RESOURCE_LOAD(res_path, "BehaviorTree"); Ref<BehaviorTree> res = RESOURCE_LOAD(res_path, "BehaviorTree");
if (bt.is_valid()) { if (res.is_valid()) {
ERR_FAIL_COND(!bt->is_class("BehaviorTree")); ERR_FAIL_COND(!res->is_class("BehaviorTree"));
if (RESOURCE_IS_EXTERNAL(bt)) { RESOURCE_SAVE(res, res->get_path(), 0);
// Only resave external - scene files are handled by the editor.
_save_bt(bt, bt->get_path());
}
} }
} }
task_tree->update_tree(); task_tree->update_tree();
@ -1327,13 +1270,14 @@ void LimboAIEditor::_rename_task_confirmed() {
undo_redo->commit_action(); undo_redo->commit_action();
} }
void LimboAIEditor::save_all(bool p_external_only) { void LimboAIEditor::apply_changes() {
for (int i = 0; i < history.size(); i++) { for (int i = 0; i < history.size(); i++) {
Ref<BehaviorTree> bt = history.get(i); Ref<BehaviorTree> bt = history.get(i);
String path = bt->get_path(); String path = bt->get_path();
if (RESOURCE_EXISTS(path, "BehaviorTree") && (!p_external_only || RESOURCE_PATH_IS_EXTERNAL(path))) { if (RESOURCE_EXISTS(path, "BehaviorTree")) {
_save_bt(bt, path); RESOURCE_SAVE(bt, path, 0);
} }
dirty.clear();
} }
} }
@ -1480,14 +1424,14 @@ void LimboAIEditor::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: { case NOTIFICATION_EXIT_TREE: {
task_tree->unload(); task_tree->unload();
for (int i = 0; i < history.size(); i++) { for (int i = 0; i < history.size(); i++) {
if (history[i]->is_connected(LW_NAME(changed), callable_mp(this, &LimboAIEditor::_set_as_dirty))) { if (history[i]->is_connected(LW_NAME(changed), callable_mp(this, &LimboAIEditor::_mark_as_dirty))) {
history[i]->disconnect(LW_NAME(changed), callable_mp(this, &LimboAIEditor::_set_as_dirty)); history[i]->disconnect(LW_NAME(changed), callable_mp(this, &LimboAIEditor::_mark_as_dirty));
} }
} }
} break; } break;
case NOTIFICATION_READY: { case NOTIFICATION_READY: {
// **** Signals // **** Signals
save_dialog->connect("file_selected", callable_mp(this, &LimboAIEditor::_save_current_bt)); save_dialog->connect("file_selected", callable_mp(this, &LimboAIEditor::_save_bt));
load_dialog->connect("file_selected", callable_mp(this, &LimboAIEditor::_load_bt)); load_dialog->connect("file_selected", callable_mp(this, &LimboAIEditor::_load_bt));
extract_dialog->connect("file_selected", callable_mp(this, &LimboAIEditor::_extract_subtree)); extract_dialog->connect("file_selected", callable_mp(this, &LimboAIEditor::_extract_subtree));
new_btn->connect(LW_NAME(pressed), callable_mp(this, &LimboAIEditor::_new_bt)); new_btn->connect(LW_NAME(pressed), callable_mp(this, &LimboAIEditor::_new_bt));
@ -1551,7 +1495,7 @@ void LimboAIEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_remove_task", "task"), &LimboAIEditor::_remove_task); ClassDB::bind_method(D_METHOD("_remove_task", "task"), &LimboAIEditor::_remove_task);
ClassDB::bind_method(D_METHOD("_add_task_with_prototype", "prototype_task"), &LimboAIEditor::_add_task_with_prototype); ClassDB::bind_method(D_METHOD("_add_task_with_prototype", "prototype_task"), &LimboAIEditor::_add_task_with_prototype);
ClassDB::bind_method(D_METHOD("_new_bt"), &LimboAIEditor::_new_bt); ClassDB::bind_method(D_METHOD("_new_bt"), &LimboAIEditor::_new_bt);
ClassDB::bind_method(D_METHOD("_save_bt", "path"), &LimboAIEditor::_save_current_bt); ClassDB::bind_method(D_METHOD("_save_bt", "path"), &LimboAIEditor::_save_bt);
ClassDB::bind_method(D_METHOD("_load_bt", "path"), &LimboAIEditor::_load_bt); ClassDB::bind_method(D_METHOD("_load_bt", "path"), &LimboAIEditor::_load_bt);
ClassDB::bind_method(D_METHOD("_update_task_tree", "bt", "specific_task"), &LimboAIEditor::_update_task_tree, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("_update_task_tree", "bt", "specific_task"), &LimboAIEditor::_update_task_tree, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("edit_bt", "behavior_tree", "force_refresh"), &LimboAIEditor::edit_bt, Variant(false)); ClassDB::bind_method(D_METHOD("edit_bt", "behavior_tree", "force_refresh"), &LimboAIEditor::edit_bt, Variant(false));
@ -1598,14 +1542,11 @@ LimboAIEditor::LimboAIEditor() {
LW_SHORTCUT("limbo_ai/save_behavior_tree", TTR("Save Behavior Tree"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY_MASK(ALT) | LW_KEY(S))); LW_SHORTCUT("limbo_ai/save_behavior_tree", TTR("Save Behavior Tree"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY_MASK(ALT) | LW_KEY(S)));
LW_SHORTCUT("limbo_ai/load_behavior_tree", TTR("Load Behavior Tree"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY_MASK(ALT) | LW_KEY(L))); LW_SHORTCUT("limbo_ai/load_behavior_tree", TTR("Load Behavior Tree"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY_MASK(ALT) | LW_KEY(L)));
LW_SHORTCUT("limbo_ai/open_debugger", TTR("Open Debugger"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY_MASK(ALT) | LW_KEY(D))); LW_SHORTCUT("limbo_ai/open_debugger", TTR("Open Debugger"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY_MASK(ALT) | LW_KEY(D)));
LW_SHORTCUT("limbo_ai/jump_to_owner", TTR("Jump to Owner"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(G))); LW_SHORTCUT("limbo_ai/jump_to_owner", TTR("Jump to Owner"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(J)));
LW_SHORTCUT("limbo_ai/close_tab", TTR("Close Tab"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(W))); LW_SHORTCUT("limbo_ai/close_tab", TTR("Close Tab"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(W)));
LW_SHORTCUT("limbo_ai/find_task", TTR("Find Task"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(F))); LW_SHORTCUT("limbo_ai/find_task", TTR("Find Task"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(F)));
LW_SHORTCUT("limbo_ai/hide_tree_search", TTR("Close Search"), (Key)(LW_KEY(ESCAPE))); LW_SHORTCUT("limbo_ai/hide_tree_search", TTR("Close Search"), (Key)(LW_KEY(ESCAPE)));
// Intercept editor save scene action.
LW_SHORTCUT("limbo_ai/editor_save_scene", TTR("Save Scene"), (Key)(LW_KEY_MASK(CMD_OR_CTRL) | LW_KEY(S)));
set_process_shortcut_input(true); set_process_shortcut_input(true);
save_dialog = memnew(FileDialog); save_dialog = memnew(FileDialog);
@ -1911,6 +1852,14 @@ LimboAIEditor::~LimboAIEditor() {
//**** LimboAIEditorPlugin //**** LimboAIEditorPlugin
#ifdef LIMBOAI_MODULE
void LimboAIEditorPlugin::apply_changes() {
#elif LIMBOAI_GDEXTENSION
void LimboAIEditorPlugin::_apply_changes() {
#endif
limbo_ai_editor->apply_changes();
}
void LimboAIEditorPlugin::_bind_methods() { void LimboAIEditorPlugin::_bind_methods() {
} }
@ -1969,9 +1918,8 @@ void LimboAIEditorPlugin::edit(Object *p_object) {
#elif LIMBOAI_GDEXTENSION #elif LIMBOAI_GDEXTENSION
void LimboAIEditorPlugin::_edit(Object *p_object) { void LimboAIEditorPlugin::_edit(Object *p_object) {
#endif #endif
Ref<BehaviorTree> bt = Object::cast_to<BehaviorTree>(p_object); if (Object::cast_to<BehaviorTree>(p_object)) {
if (bt.is_valid()) { limbo_ai_editor->edit_bt(Object::cast_to<BehaviorTree>(p_object));
limbo_ai_editor->edit_bt(bt);
} }
} }
@ -1986,14 +1934,6 @@ bool LimboAIEditorPlugin::_handles(Object *p_object) const {
return false; return false;
} }
#ifdef LIMBOAI_MODULE
void LimboAIEditorPlugin::save_external_data() {
#elif LIMBOAI_GDEXTENSION
void LimboAIEditorPlugin::_save_external_data() {
#endif
limbo_ai_editor->save_all(true);
}
#ifdef LIMBOAI_GDEXTENSION #ifdef LIMBOAI_GDEXTENSION
Ref<Texture2D> LimboAIEditorPlugin::_get_plugin_icon() const { Ref<Texture2D> LimboAIEditorPlugin::_get_plugin_icon() const {
return LimboUtility::get_singleton()->get_task_icon("LimboAI"); return LimboUtility::get_singleton()->get_task_icon("LimboAI");

View File

@ -205,12 +205,11 @@ private:
void _update_misc_menu(); void _update_misc_menu();
void _update_banners(); void _update_banners();
void _new_bt(); void _new_bt();
void _save_bt(const Ref<BehaviorTree> &p_bt, const String &p_path); void _save_bt(String p_path);
void _save_current_bt(const String &p_path); void _load_bt(String p_path);
void _load_bt(const String &p_path);
void _update_task_tree(const Ref<BehaviorTree> &p_bt, const Ref<BTTask> &p_specific_task = nullptr); void _update_task_tree(const Ref<BehaviorTree> &p_bt, const Ref<BTTask> &p_specific_task = nullptr);
void _disable_editing(); void _disable_editing();
void _set_as_dirty(const Ref<BehaviorTree> &p_bt, bool p_dirty); void _mark_as_dirty(bool p_dirty);
void _create_user_task_dir(); void _create_user_task_dir();
void _remove_task_from_favorite(const String &p_task); void _remove_task_from_favorite(const String &p_task);
void _save_and_restart(); void _save_and_restart();
@ -241,6 +240,7 @@ private:
void _on_tree_task_selected(const Ref<BTTask> &p_task); void _on_tree_task_selected(const Ref<BTTask> &p_task);
void _on_tree_task_activated(); void _on_tree_task_activated();
void _on_visibility_changed(); void _on_visibility_changed();
void _on_header_pressed();
void _on_save_pressed(); void _on_save_pressed();
void _on_history_back(); void _on_history_back();
void _on_history_forward(); void _on_history_forward();
@ -271,7 +271,7 @@ public:
void set_window_layout(const Ref<ConfigFile> &p_configuration); void set_window_layout(const Ref<ConfigFile> &p_configuration);
void get_window_layout(const Ref<ConfigFile> &p_configuration); void get_window_layout(const Ref<ConfigFile> &p_configuration);
void save_all(bool p_external_only = false); void apply_changes();
#ifdef LIMBOAI_GDEXTENSION #ifdef LIMBOAI_GDEXTENSION
virtual void _shortcut_input(const Ref<InputEvent> &p_event) override { _process_shortcut_input(p_event); } virtual void _shortcut_input(const Ref<InputEvent> &p_event) override { _process_shortcut_input(p_event); }
@ -297,23 +297,23 @@ public:
virtual String get_name() const override { return "LimboAI"; } virtual String get_name() const override { return "LimboAI"; }
virtual void make_visible(bool p_visible) override; virtual void make_visible(bool p_visible) override;
virtual void apply_changes() override;
virtual void edit(Object *p_object) override; virtual void edit(Object *p_object) override;
virtual bool handles(Object *p_object) const override; virtual bool handles(Object *p_object) const override;
virtual void set_window_layout(Ref<ConfigFile> p_configuration) override; virtual void set_window_layout(Ref<ConfigFile> p_configuration) override;
virtual void get_window_layout(Ref<ConfigFile> p_configuration) override; virtual void get_window_layout(Ref<ConfigFile> p_configuration) override;
virtual void save_external_data() override;
#elif LIMBOAI_GDEXTENSION #elif LIMBOAI_GDEXTENSION
bool _has_main_screen() const override { return true; } bool _has_main_screen() const override { return true; }
virtual String _get_plugin_name() const override { return "LimboAI"; } virtual String _get_plugin_name() const override { return "LimboAI"; }
virtual void _make_visible(bool p_visible) override; virtual void _make_visible(bool p_visible) override;
virtual void _apply_changes() override;
virtual void _edit(Object *p_object) override; virtual void _edit(Object *p_object) override;
virtual bool _handles(Object *p_object) const override; virtual bool _handles(Object *p_object) const override;
virtual Ref<Texture2D> _get_plugin_icon() const override; virtual Ref<Texture2D> _get_plugin_icon() const override;
virtual void _set_window_layout(const Ref<ConfigFile> &p_configuration) override; virtual void _set_window_layout(const Ref<ConfigFile> &p_configuration) override;
virtual void _get_window_layout(const Ref<ConfigFile> &p_configuration) override; virtual void _get_window_layout(const Ref<ConfigFile> &p_configuration) override;
virtual void _save_external_data() override;
#endif // LIMBOAI_MODULE & LIMBOAI_GDEXTENSION #endif // LIMBOAI_MODULE & LIMBOAI_GDEXTENSION
LimboAIEditorPlugin(); LimboAIEditorPlugin();

View File

@ -95,7 +95,7 @@ protected:
public: public:
void load_bt(const Ref<BehaviorTree> &p_behavior_tree); void load_bt(const Ref<BehaviorTree> &p_behavior_tree);
void unload(); void unload();
_FORCE_INLINE_ Ref<BehaviorTree> get_bt() const { return bt; } Ref<BehaviorTree> get_bt() const { return bt; }
void update_tree() { _update_tree(); } void update_tree() { _update_tree(); }
void update_task(const Ref<BTTask> &p_task); void update_task(const Ref<BTTask> &p_task);
void add_selection(const Ref<BTTask> &p_task); void add_selection(const Ref<BTTask> &p_task);

View File

@ -175,9 +175,7 @@ Variant VARIANT_DEFAULT(Variant::Type p_type);
#define IS_RESOURCE_FILE(m_path) (m_path.begins_with("res://") && m_path.find("::") == -1) #define IS_RESOURCE_FILE(m_path) (m_path.begins_with("res://") && m_path.find("::") == -1)
#define RESOURCE_TYPE_HINT(m_type) vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, m_type) #define RESOURCE_TYPE_HINT(m_type) vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, m_type)
#define RESOURCE_IS_BUILT_IN(m_res) (m_res->get_path().is_empty() || m_res->get_path().contains("::")) #define RESOURCE_IS_BUILT_IN(m_res) (m_res->get_path().is_empty() || m_res->get_path().contains("::"))
#define RESOURCE_IS_EXTERNAL(m_res) (!RESOURCE_IS_BUILT_IN(m_res))
#define RESOURCE_PATH_IS_BUILT_IN(m_path) (m_path.is_empty() || m_path.contains("::")) #define RESOURCE_PATH_IS_BUILT_IN(m_path) (m_path.is_empty() || m_path.contains("::"))
#define RESOURCE_PATH_IS_EXTERNAL(m_path) (!RESOURCE_PATH_IS_BUILT_IN(m_path))
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED