diff --git a/editor/limbo_ai_editor_plugin.cpp b/editor/limbo_ai_editor_plugin.cpp index ffa3f54..8fb0939 100644 --- a/editor/limbo_ai_editor_plugin.cpp +++ b/editor/limbo_ai_editor_plugin.cpp @@ -388,6 +388,7 @@ void LimboAIEditor::_add_task(const Ref &p_prototype) { } else { parent->add_child(p_prototype); } + _mark_as_dirty(true); task_tree->update_tree(); } @@ -395,7 +396,10 @@ void LimboAIEditor::_update_header() { String text = task_tree->get_bt()->get_path(); if (text.empty()) { text = TTR("New Behavior Tree"); + } else if (dirty.has(task_tree->get_bt())) { + text += "(*)"; } + header->set_text(text); header->set_icon(editor->get_object_icon(task_tree->get_bt().ptr(), "BehaviorTree")); } @@ -417,6 +421,7 @@ void LimboAIEditor::_save_bt(String p_path) { task_tree->get_bt()->set_path(p_path, true); ResourceSaver::save(p_path, task_tree->get_bt(), ResourceSaver::FLAG_CHANGE_PATH); _update_header(); + _mark_as_dirty(false); } void LimboAIEditor::_load_bt(String p_path) { @@ -447,6 +452,17 @@ void LimboAIEditor::_edit_bt(Ref p_behavior_tree) { _update_header(); } +void LimboAIEditor::_mark_as_dirty(bool p_dirty) { + Ref bt = task_tree->get_bt(); + if (p_dirty && !dirty.has(bt)) { + dirty.insert(bt); + _update_header(); + } else if (p_dirty == false && dirty.has(bt)) { + dirty.erase(bt); + _update_header(); + } +} + void LimboAIEditor::_on_tree_rmb(const Vector2 &p_menu_pos) { menu->set_size(Size2(1, 1)); menu->set_position(p_menu_pos); @@ -474,6 +490,7 @@ void LimboAIEditor::_on_action_selected(int p_id) { } task_tree->update_tree(); editor->edit_node(nullptr); + _mark_as_dirty(true); } } break; case ACTION_MOVE_UP: { @@ -485,6 +502,7 @@ void LimboAIEditor::_on_action_selected(int p_id) { parent->remove_child(sel); parent->add_child_at_index(sel, idx - 1); task_tree->update_tree(); + _mark_as_dirty(true); } } } break; @@ -497,6 +515,7 @@ void LimboAIEditor::_on_action_selected(int p_id) { parent->remove_child(sel); parent->add_child_at_index(sel, idx + 1); task_tree->update_tree(); + _mark_as_dirty(true); } } } break; @@ -509,6 +528,7 @@ void LimboAIEditor::_on_action_selected(int p_id) { } parent->add_child(sel->clone()); task_tree->update_tree(); + _mark_as_dirty(true); } } break; case ACTION_MAKE_ROOT: { @@ -521,6 +541,7 @@ void LimboAIEditor::_on_action_selected(int p_id) { task_tree->get_bt()->set_root_task(sel); sel->add_child(old_root); task_tree->update_tree(); + _mark_as_dirty(true); } } break; } @@ -579,6 +600,18 @@ void LimboAIEditor::_on_history_forward() { _edit_bt(history[idx_history]); } +void LimboAIEditor::apply_changes() { + for (int i = 0; i < history.size(); i++) { + Ref bt = history.get(i); + String path = bt->get_path(); + if (ResourceLoader::exists(path)) { + ResourceSaver::save(path, bt); + } + dirty.clear(); + _update_header(); + } +} + void LimboAIEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_add_task", "p_task"), &LimboAIEditor::_add_task); ClassDB::bind_method(D_METHOD("_on_tree_rmb"), &LimboAIEditor::_on_tree_rmb); @@ -751,6 +784,10 @@ const Ref LimboAIEditorPlugin::get_icon() const { return nullptr; } +void LimboAIEditorPlugin::apply_changes() { + limbo_ai_editor->apply_changes(); +} + void LimboAIEditorPlugin::_notification(int p_notification) { // print_line(vformat("NOTIFICATION: %d", p_notification)); } diff --git a/editor/limbo_ai_editor_plugin.h b/editor/limbo_ai_editor_plugin.h index f03d80d..ad53f13 100644 --- a/editor/limbo_ai_editor_plugin.h +++ b/editor/limbo_ai_editor_plugin.h @@ -104,6 +104,7 @@ private: EditorNode *editor; Vector> history; int idx_history; + Set> dirty; Button *header; TaskTree *task_tree; @@ -120,6 +121,7 @@ private: void _save_bt(String p_path); void _load_bt(String p_path); void _edit_bt(Ref p_behavior_tree); + void _mark_as_dirty(bool p_dirty); void _on_tree_rmb(const Vector2 &p_menu_pos); void _on_action_selected(int p_id); @@ -135,6 +137,8 @@ protected: static void _bind_methods(); public: + void apply_changes(); + LimboAIEditor(EditorNode *p_editor); ~LimboAIEditor(); }; @@ -154,6 +158,7 @@ public: virtual const Ref get_icon() const; bool has_main_screen() const { return true; } virtual void make_visible(bool p_visible); + virtual void apply_changes(); LimboAIEditorPlugin(EditorNode *p_editor); ~LimboAIEditorPlugin();