17#include "../DataManager.h"
19#include "../third_party/imgui/imgui.h"
20#include "../third_party/nlohmann/json.hpp"
21#include "../system/system_utils.h"
43 , m_showSaveAsDialog(
false)
50 for (
size_t i = 0;
i <
m_tabs.size(); ++
i)
64 std::ostringstream
oss;
75 size_t pos = filePath.find_last_of(
"/\\");
76 if (
pos == std::string::npos)
78 return filePath.substr(
pos + 1);
87 std::ifstream
ifs(filePath.c_str());
101 if (!
root.is_object())
105 if (
root.contains(
"graphType") &&
root[
"graphType"].is_string())
107 std::string
gt =
root[
"graphType"].get<std::string>();
108 if (
gt ==
"VisualScript" ||
gt ==
"BehaviorTree" ||
gt ==
"AnimGraph")
111 if (
root.contains(
"blueprintType") &&
root[
"blueprintType"].is_string())
113 std::string
bt =
root[
"blueprintType"].get<std::string>();
114 if (
bt ==
"BehaviorTree")
115 return "BehaviorTree";
116 if (
bt ==
"EntityPrefab")
117 return "EntityPrefab";
121 int schemaVersion = 0;
122 if (
root.contains(
"schema_version") &&
root[
"schema_version"].is_number())
125 if (schemaVersion == 4)
127 if (
root.contains(
"nodes") &&
root.contains(
"execConnections"))
128 return "VisualScript";
131 if (
root.contains(
"rootNodeId") &&
root.contains(
"nodes"))
132 return "BehaviorTree";
134 if (
root.contains(
"states") &&
root.contains(
"transitions"))
138 if (
root.contains(
"blueprintType"))
139 return "BehaviorTree";
150 std::ostringstream
nameSS;
157 tab.graphType = graphType;
159 tab.isActive =
false;
161 if (graphType ==
"VisualScript")
166 else if (graphType ==
"EntityPrefab")
180 else if (graphType ==
"BehaviorTree")
209 if (filePath.empty())
213 for (
size_t i = 0;
i <
m_tabs.size(); ++
i)
215 if (
m_tabs[
i].filePath == filePath)
229 tab.filePath = filePath;
230 tab.graphType = graphType;
232 tab.isActive =
false;
234 if (graphType ==
"VisualScript")
237 if (!
r->Load(filePath))
245 else if (graphType ==
"BehaviorTree")
260 if (!
r->Load(filePath))
268 else if (graphType ==
"EntityPrefab")
282 if (!
r->Load(filePath))
294 if (!
r->Load(filePath))
300 tab.graphType =
"VisualScript";
323 for (
size_t i = 0;
i <
m_tabs.size(); ++
i)
336 newTab->renderer->RestoreCanvasState();
347 for (
size_t i = 0;
i <
m_tabs.size(); ++
i)
357 for (
size_t i = 0;
i <
m_tabs.size(); ++
i)
377 m_tabs.erase(
m_tabs.begin() +
static_cast<std::vector<EditorTab>::difference_type
>(
index));
397 for (
size_t i = 0;
i <
m_tabs.size(); ++
i)
424 for (
int i =
static_cast<int>(
m_tabs.size()) - 1;
i >= 0; --
i)
456 if (!
tab || !
tab->renderer)
459 if (
tab->filePath.empty())
471 bool ok =
tab->renderer->Save(
tab->filePath);
474 tab->isDirty =
false;
488 if (!
tab || !
tab->renderer)
501 bool ok =
tab->renderer->Save(path);
504 tab->filePath = path;
505 tab->isDirty =
false;
517 for (
size_t i = 0;
i <
m_tabs.size(); ++
i)
536 ImGui::OpenPopup(
"TabManager_UnsavedClose");
539 if (ImGui::BeginPopupModal(
"TabManager_UnsavedClose",
nullptr,
545 ImGui::Text(
"The graph \"%s\" has unsaved changes.",
546 tab->displayName.c_str());
547 ImGui::Text(
"Do you want to save before closing?");
550 if (ImGui::Button(
"Save",
ImVec2(100, 0)))
555 for (
size_t i = 0;
i <
m_tabs.size(); ++
i)
564 ImGui::CloseCurrentPopup();
567 if (ImGui::Button(
"Don't Save",
ImVec2(100, 0)))
569 for (
size_t i = 0;
i <
m_tabs.size(); ++
i)
578 ImGui::CloseCurrentPopup();
581 if (ImGui::Button(
"Cancel",
ImVec2(100, 0)))
584 ImGui::CloseCurrentPopup();
590 ImGui::CloseCurrentPopup();
599 ImGui::TextDisabled(
"No graph open. Double-click a file to open it.");
606 if (ImGui::BeginTabBar(
"GraphTabBar",
tabBarFlags))
608 for (
size_t i = 0;
i <
m_tabs.size(); ++
i)
630 std::string label =
tab.displayName;
649 if (ImGui::BeginTabItem(label.c_str(), &
open,
flags))
686 if (!
tab || !
tab->renderer)
688 ImGui::TextDisabled(
"No graph open.");
691 tab->renderer->Render();
IGraphRenderer adapter for BehaviorTree graphs (wraps BTNodeGraphManager).
ComponentTypeID GetComponentTypeID_Static()
static SDL_Renderer * renderer
Central manager for the multi-graph tab system.
IGraphRenderer adapter that wraps VisualScriptEditorPanel.
Adapts the BTNodeGraphManager + NodeGraphPanel to IGraphRenderer.
Renderer adapter for Entity Prefab graphs.
NodeGraphPanel - ImGui/ImNodes panel for node graph editing Provides visual editor for behavior trees...
void Initialize(EntityPrefabGraphDocument *document)
Singleton that owns and manages all open graph editor tabs.
int m_nextTabNum
Counter for "Untitled-N" names.
bool SaveActiveTabAs(const std::string &path)
Saves the active tab to a specific path.
bool HasDirtyTabs() const
Returns true when at least one tab has unsaved changes.
int ShowUnsavedDialog(const EditorTab &tab)
Shows a 3-button "Save / Don't Save / Cancel" modal dialog.
static TabManager & Get()
Returns the global singleton instance.
EditorTab * GetActiveTab()
EditorTab * GetTab(const std::string &tabID)
std::string m_saveAsTabID
std::string GetActiveTabID() const
std::string CreateNewTab(const std::string &graphType)
Creates a new empty tab of the given graph type.
std::string NextTabID()
Generates the next unique tabID.
bool CloseAllTabs()
Attempts to close all tabs.
bool SaveActiveTab()
Saves the active tab.
bool CloseTab(const std::string &tabID)
Closes the given tab.
static std::string DisplayNameFromPath(const std::string &filePath)
Derives a display name from a file path (filename without dir).
int m_nextTabIDNum
Counter for unique tab IDs.
static std::string DetectGraphType(const std::string &filePath)
Detects the graph type by inspecting the JSON contents.
void RenderTabBar()
Renders the horizontal tab bar (call before RenderActiveCanvas).
std::vector< EditorTab > m_tabs
std::string m_pendingSelectTabID
void RenderActiveCanvas()
Renders the graph canvas of the active tab.
void DestroyTab(size_t index)
Deletes a renderer and removes its tab entry.
std::string m_pendingCloseTabID
void SetActiveTab(const std::string &tabID)
std::string OpenFileInTab(const std::string &filePath)
Opens a file in a new tab.
std::string m_activeTabID
Adapts the existing VisualScriptEditorPanel to the IGraphRenderer interface.
< Provides AssetID and INVALID_ASSET_ID
Represents a single open graph in the editor.
bool isDirty
True when there are unsaved changes.
std::string tabID
Unique identifier (stringified int counter)