Whatever The Fuck Man
This commit is contained in:
1 parent
ce77175162
commit
2efed2a443
162 files changed
+13119
-7417
No files matched your search
@@ -0,0 +1,536 @@
|
||||
#include "window.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <format>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include "../log.hpp"
|
||||
#include "../util/physfs.hpp"
|
||||
#include "../util/preferences.hpp"
|
||||
|
||||
namespace game::developer
|
||||
{
|
||||
bool gIsDocumentUndoMenuRequested{};
|
||||
bool gIsDocumentRedoMenuRequested{};
|
||||
|
||||
namespace window_detail
|
||||
{
|
||||
constexpr auto RECENT_FILES_MAX = 10;
|
||||
constexpr auto CENTER_RATIO = 0.5f;
|
||||
constexpr auto DEVELOPER_WINDOW_SIZE_RATIO = 0.75f;
|
||||
constexpr auto INFO_SCHEMA_TABLE_COLUMNS = 4;
|
||||
constexpr auto DEVELOPER_WINDOW_FLAGS = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings;
|
||||
constexpr auto EDITOR_CHILD_FLAGS = ImGuiWindowFlags_MenuBar;
|
||||
constexpr auto DIALOGUE_SCHEMA_FILENAME = "dialogue.xml";
|
||||
|
||||
using Schema = resource::xml::Schema;
|
||||
using Element = Schema::Element;
|
||||
|
||||
#define GAME_DEVELOPER_SCHEMA_FILES(X) \
|
||||
X(CHARACTER, "character.xml", "Character", Element::CHARACTER) \
|
||||
X(DIALOGUE, "dialogue.xml", "Dialogue", Element::DIALOGUE) \
|
||||
X(ITEMS, "items.xml", "Items", Element::ITEM_SCHEMA) \
|
||||
X(AREAS, "areas.xml", "Areas", Element::AREAS) \
|
||||
X(MENU, "menu.xml", "Menu", Element::MENU) \
|
||||
X(CURSOR, "cursor.xml", "Cursor", Element::CURSOR) \
|
||||
X(PARTICLES, "particles.xml", "Particles", Element::PARTICLES) \
|
||||
X(STRINGS, "strings.xml", "Strings", Element::STRINGS)
|
||||
|
||||
struct SchemaInfo
|
||||
{
|
||||
std::string_view filename{};
|
||||
std::string_view label{};
|
||||
Element::Type type{};
|
||||
};
|
||||
|
||||
constexpr SchemaInfo SCHEMA_INFOS[]{
|
||||
#define GAME_DEVELOPER_SCHEMA_INFO(SYMBOL, FILENAME, LABEL, TYPE) {.filename = FILENAME, .label = LABEL, .type = TYPE},
|
||||
GAME_DEVELOPER_SCHEMA_FILES(GAME_DEVELOPER_SCHEMA_INFO)
|
||||
#undef GAME_DEVELOPER_SCHEMA_INFO
|
||||
};
|
||||
|
||||
std::filesystem::path path_normalized_get(const std::filesystem::path& path)
|
||||
{
|
||||
std::error_code error{};
|
||||
auto normalized = std::filesystem::weakly_canonical(path, error);
|
||||
if (!error) return normalized;
|
||||
return std::filesystem::absolute(path, error).lexically_normal();
|
||||
}
|
||||
|
||||
std::filesystem::path recent_file_path_get() { return util::preferences::path() / "recent.txt"; }
|
||||
|
||||
std::string document_path_label_get(const std::filesystem::path& path)
|
||||
{
|
||||
auto filename = path.filename();
|
||||
if (filename.empty()) return path.string();
|
||||
return filename.string();
|
||||
}
|
||||
|
||||
bool shortcut_is_pressed(ImGuiKeyChord chord)
|
||||
{
|
||||
auto& io = ImGui::GetIO();
|
||||
return !io.WantTextInput && !ImGui::IsAnyItemActive() &&
|
||||
ImGui::Shortcut(chord, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused);
|
||||
}
|
||||
|
||||
#undef GAME_DEVELOPER_SCHEMA_FILES
|
||||
}
|
||||
|
||||
using namespace window_detail;
|
||||
|
||||
void Window::recent_files_load()
|
||||
{
|
||||
if (isRecentFilesLoaded) return;
|
||||
isRecentFilesLoaded = true;
|
||||
recentFiles.clear();
|
||||
|
||||
std::ifstream file(recent_file_path_get());
|
||||
if (!file.is_open()) return;
|
||||
|
||||
std::string line{};
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
if (line.empty()) continue;
|
||||
recentFiles.push_back(path_normalized_get(line));
|
||||
if ((int)recentFiles.size() >= RECENT_FILES_MAX) break;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::recent_files_save()
|
||||
{
|
||||
auto recentPath = recent_file_path_get();
|
||||
if (recentPath.empty()) return;
|
||||
std::error_code error{};
|
||||
if (!recentPath.parent_path().empty()) std::filesystem::create_directories(recentPath.parent_path(), error);
|
||||
|
||||
std::ofstream file(recentPath, std::ios::trunc);
|
||||
if (!file.is_open())
|
||||
{
|
||||
logger.warning(std::format("Failed to write {}", recentPath.string()));
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& path : recentFiles)
|
||||
file << path.string() << '\n';
|
||||
}
|
||||
|
||||
void Window::recent_file_push(const std::filesystem::path& path)
|
||||
{
|
||||
recent_files_load();
|
||||
auto normalized = path_normalized_get(path);
|
||||
if (normalized.empty()) return;
|
||||
|
||||
std::erase_if(recentFiles, [&](const auto& recent) { return recent == normalized; });
|
||||
recentFiles.insert(recentFiles.begin(), normalized);
|
||||
if ((int)recentFiles.size() > RECENT_FILES_MAX) recentFiles.resize(RECENT_FILES_MAX);
|
||||
recent_files_save();
|
||||
}
|
||||
|
||||
Document Window::document_load(const std::filesystem::path& path)
|
||||
{
|
||||
Document document{};
|
||||
document.path = path_normalized_get(path);
|
||||
|
||||
for (auto& info : SCHEMA_INFOS)
|
||||
{
|
||||
Document::SchemaFile schemaFile{};
|
||||
schemaFile.filename = info.filename;
|
||||
schemaFile.label = info.label;
|
||||
schemaFile.type = info.type;
|
||||
schemaFile.path = document.path / schemaFile.filename;
|
||||
schemaFile.isExists = std::filesystem::is_regular_file(schemaFile.path);
|
||||
if (schemaFile.isExists)
|
||||
{
|
||||
schemaFile.isValid = schemaFile.schema.load(schemaFile.path);
|
||||
auto* root = schemaFile.schema.root();
|
||||
if (!root || root->type != schemaFile.type) schemaFile.isValid = false;
|
||||
}
|
||||
document.schemas.emplace_back(std::move(schemaFile));
|
||||
}
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
void Window::folder_open(const std::filesystem::path& path)
|
||||
{
|
||||
auto normalizedPath = path_normalized_get(path);
|
||||
std::error_code error{};
|
||||
if (!std::filesystem::is_directory(normalizedPath, error))
|
||||
{
|
||||
logger.warning(std::format("Ignored {}", normalizedPath.string()));
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = std::ranges::find_if(documents, [&](const auto& document) { return document.path == normalizedPath; });
|
||||
if (it != documents.end())
|
||||
{
|
||||
*it = document_load(normalizedPath);
|
||||
it->history_clear();
|
||||
it->isDirty = false;
|
||||
selectedDocument = (int)std::distance(documents.begin(), it);
|
||||
logger.info(std::format("Opened {}", normalizedPath.string()));
|
||||
toasts.push(std::format("Opened {}", normalizedPath.string()));
|
||||
}
|
||||
else
|
||||
{
|
||||
documents.push_back(document_load(normalizedPath));
|
||||
selectedDocument = (int)documents.size() - 1;
|
||||
logger.info(std::format("Opened {}", normalizedPath.string()));
|
||||
toasts.push(std::format("Opened {}", normalizedPath.string()));
|
||||
}
|
||||
recent_file_push(normalizedPath);
|
||||
}
|
||||
|
||||
void Window::save(int index)
|
||||
{
|
||||
if (index < 0 || index >= (int)documents.size()) return;
|
||||
auto& document = documents[index];
|
||||
auto* dialogue = document.dialogue_schema_get();
|
||||
if (!dialogue || !dialogue->isExists)
|
||||
{
|
||||
toasts.push("No dialogue.xml to save");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(std::format("Wrote to {}", dialogue->path.string()));
|
||||
dialogue->schema.serialize(dialogue->path);
|
||||
documents[index].isDirty = false;
|
||||
toasts.push(std::format("Wrote to {}", dialogue->path.string()));
|
||||
recent_file_push(documents[index].path);
|
||||
}
|
||||
|
||||
void Window::export_to(int index, const std::filesystem::path& path)
|
||||
{
|
||||
if (index < 0 || index >= (int)documents.size()) return;
|
||||
if (documents[index].isDirty) save(index);
|
||||
auto destination = path_normalized_get(path);
|
||||
if (util::physfs::archive_write(documents[index].path, destination))
|
||||
toasts.push(std::format("Exported {}", destination.string()));
|
||||
else
|
||||
toasts.push(std::format("Failed to export {}", destination.string()));
|
||||
}
|
||||
|
||||
void Window::close(int index)
|
||||
{
|
||||
if (index < 0 || index >= (int)documents.size()) return;
|
||||
auto label = document_path_label_get(documents[index].path);
|
||||
documents.erase(documents.begin() + index);
|
||||
selectedDocument = documents.empty() ? 0 : std::clamp(index, 0, (int)documents.size() - 1);
|
||||
toasts.push(std::format("Closed {}", label));
|
||||
}
|
||||
|
||||
void Window::undo(int index)
|
||||
{
|
||||
if (index < 0 || index >= (int)documents.size()) return;
|
||||
auto& document = documents[index];
|
||||
if (!document.can_undo()) return;
|
||||
|
||||
auto message = document.undo_apply();
|
||||
if (!message.empty()) toasts.push(std::format("Undo: {}", message));
|
||||
}
|
||||
|
||||
void Window::redo(int index)
|
||||
{
|
||||
if (index < 0 || index >= (int)documents.size()) return;
|
||||
auto& document = documents[index];
|
||||
if (!document.can_redo()) return;
|
||||
|
||||
auto message = document.redo_apply();
|
||||
if (!message.empty()) toasts.push(std::format("Redo: {}", message));
|
||||
}
|
||||
|
||||
void Window::dropped_file_open(const char* path)
|
||||
{
|
||||
if (!path) return;
|
||||
folder_open(path);
|
||||
}
|
||||
|
||||
void Window::editor_shortcuts_update()
|
||||
{
|
||||
if (shortcut_is_pressed(ImGuiMod_Ctrl | ImGuiKey_O)) dialog.folder_open(util::Dialog::SCHEMA_FOLDER_OPEN);
|
||||
if (shortcut_is_pressed(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Z))
|
||||
redo(selectedDocument);
|
||||
else if (shortcut_is_pressed(ImGuiMod_Ctrl | ImGuiKey_Z))
|
||||
undo(selectedDocument);
|
||||
if (shortcut_is_pressed(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_S))
|
||||
dialog.file_save(util::Dialog::DOCUMENT_EXPORT);
|
||||
else if (shortcut_is_pressed(ImGuiMod_Ctrl | ImGuiKey_S))
|
||||
save(selectedDocument);
|
||||
if (shortcut_is_pressed(ImGuiMod_Ctrl | ImGuiKey_W)) close(selectedDocument);
|
||||
}
|
||||
|
||||
void Window::dialog_selection_update()
|
||||
{
|
||||
if (dialog.is_selected(util::Dialog::SCHEMA_FOLDER_OPEN))
|
||||
{
|
||||
folder_open(dialog.path);
|
||||
dialog.reset();
|
||||
}
|
||||
else if (dialog.is_selected(util::Dialog::DOCUMENT_EXPORT))
|
||||
{
|
||||
export_to(selectedDocument, dialog.path);
|
||||
dialog.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::editor_menu_update()
|
||||
{
|
||||
if (!ImGui::BeginMenuBar()) return;
|
||||
|
||||
if (ImGui::BeginMenu("File"))
|
||||
{
|
||||
if (ImGui::MenuItem("Open Folder", "Ctrl+O")) dialog.folder_open(util::Dialog::SCHEMA_FOLDER_OPEN);
|
||||
if (ImGui::BeginMenu("Open Recent", !recentFiles.empty()))
|
||||
{
|
||||
for (int recentIndex = 0; recentIndex < (int)recentFiles.size(); ++recentIndex)
|
||||
{
|
||||
ImGui::PushID(recentIndex);
|
||||
auto label = recentFiles[recentIndex].string();
|
||||
if (ImGui::MenuItem(label.c_str())) folder_open(recentFiles[recentIndex]);
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::MenuItem("Save", "Ctrl+S", false, selectedDocument >= 0 && selectedDocument < (int)documents.size()))
|
||||
save(selectedDocument);
|
||||
if (ImGui::MenuItem("Export", "Ctrl+Shift+S", false,
|
||||
selectedDocument >= 0 && selectedDocument < (int)documents.size()))
|
||||
dialog.file_save(util::Dialog::DOCUMENT_EXPORT);
|
||||
if (ImGui::MenuItem("Close", "Ctrl+W", false, selectedDocument >= 0 && selectedDocument < (int)documents.size()))
|
||||
close(selectedDocument);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Edit"))
|
||||
{
|
||||
auto isCanUndo =
|
||||
selectedDocument >= 0 && selectedDocument < (int)documents.size() && documents[selectedDocument].can_undo();
|
||||
auto isCanRedo =
|
||||
selectedDocument >= 0 && selectedDocument < (int)documents.size() && documents[selectedDocument].can_redo();
|
||||
if (ImGui::MenuItem("Undo", "Ctrl+Z", false, isCanUndo)) undo(selectedDocument);
|
||||
if (ImGui::MenuItem("Redo", "Ctrl+Shift+Z", false, isCanRedo)) redo(selectedDocument);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
void Window::editor_documents_update(Resources& resources)
|
||||
{
|
||||
if (documents.empty() || !ImGui::BeginTabBar("schemas", ImGuiTabBarFlags_Reorderable)) return;
|
||||
|
||||
auto closeRequest = -1;
|
||||
for (int i = 0; i < (int)documents.size(); ++i)
|
||||
{
|
||||
ImGui::PushID(i);
|
||||
auto label = document_path_label_get(documents[i].path) + (documents[i].isDirty ? " *" : "");
|
||||
label += std::format("###{}", documents[i].path.string());
|
||||
|
||||
auto isOpen = true;
|
||||
auto isTabOpen = ImGui::BeginTabItem(label.c_str(), &isOpen);
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal))
|
||||
ImGui::SetTooltip("%s", documents[i].path.string().c_str());
|
||||
|
||||
if (isTabOpen)
|
||||
{
|
||||
selectedDocument = i;
|
||||
if (ImGui::BeginTabBar("##Document Tabs"))
|
||||
{
|
||||
if (ImGui::BeginTabItem("Info"))
|
||||
{
|
||||
document_info_update(documents[i]);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Dialogue"))
|
||||
{
|
||||
document_dialogue_update(resources, documents[i]);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (!isOpen) closeRequest = i;
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
if (closeRequest >= 0) close(closeRequest);
|
||||
}
|
||||
|
||||
void Window::document_info_update(const Document& document)
|
||||
{
|
||||
if (!ImGui::BeginTable("##Schema Info", INFO_SCHEMA_TABLE_COLUMNS, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg))
|
||||
return;
|
||||
|
||||
ImGui::TableSetupColumn("Schema");
|
||||
ImGui::TableSetupColumn("File");
|
||||
ImGui::TableSetupColumn("Exists");
|
||||
ImGui::TableSetupColumn("Valid");
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (auto& schema : document.schemas)
|
||||
{
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(schema.label.c_str());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(schema.filename.c_str());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(schema.isExists ? "Yes" : "No");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(schema.isValid ? "Yes" : "No");
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
void Window::document_dialogue_update(Resources& resources, Document& document)
|
||||
{
|
||||
auto* dialogue = document.dialogue_schema_get();
|
||||
if (!dialogue || !dialogue->isExists)
|
||||
{
|
||||
ImGui::TextUnformatted("No dialogue.xml found.");
|
||||
return;
|
||||
}
|
||||
if (!dialogue->isValid)
|
||||
{
|
||||
ImGui::TextUnformatted("dialogue.xml is not valid.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::IsAnyItemActive()) document.edit_snapshot_begin();
|
||||
std::vector<Editor::LoadedSchema> loadedSchemas{};
|
||||
for (auto& schemaFile : document.schemas)
|
||||
{
|
||||
if (!schemaFile.isValid) continue;
|
||||
loadedSchemas.push_back({.path = &schemaFile.path, .schema = &schemaFile.schema});
|
||||
}
|
||||
|
||||
auto before = dialogue->schema;
|
||||
if (document.editor.update(resources, dialogue->schema, dialogue->path, dialog, loadedSchemas))
|
||||
{
|
||||
before = document.edit_snapshot_take_or(std::move(before));
|
||||
if (before.element_serialize(0) != dialogue->schema.element_serialize(0))
|
||||
{
|
||||
auto message = Document::change_message_get(before, dialogue->schema);
|
||||
document.snapshot_push(std::move(before), message);
|
||||
}
|
||||
else
|
||||
document.isDirty = true;
|
||||
}
|
||||
else if (!ImGui::IsAnyItemActive())
|
||||
document.edit_snapshot_clear();
|
||||
}
|
||||
|
||||
void Window::editor_update(Resources& resources)
|
||||
{
|
||||
if (ImGui::BeginChild("##Editor", ImVec2(), ImGuiChildFlags_None, EDITOR_CHILD_FLAGS))
|
||||
{
|
||||
editor_menu_update();
|
||||
|
||||
if (ImGui::BeginPopupContextWindow("developer-context",
|
||||
ImGuiPopupFlags_MouseButtonRight | ImGuiPopupFlags_NoOpenOverItems))
|
||||
{
|
||||
auto isCanUndo =
|
||||
selectedDocument >= 0 && selectedDocument < (int)documents.size() && documents[selectedDocument].can_undo();
|
||||
auto isCanRedo =
|
||||
selectedDocument >= 0 && selectedDocument < (int)documents.size() && documents[selectedDocument].can_redo();
|
||||
if (ImGui::MenuItem("Undo", "Ctrl+Z", false, isCanUndo)) isContextUndoRequested = true;
|
||||
if (ImGui::MenuItem("Redo", "Ctrl+Shift+Z", false, isCanRedo)) isContextRedoRequested = true;
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
editor_documents_update(resources);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
void Window::update(Resources& resources, SDL_Window* window, state::Play* play)
|
||||
{
|
||||
dialog.window_set(window);
|
||||
|
||||
if (!resources.isDeveloper && shortcut_is_pressed(ImGuiKey_GraveAccent))
|
||||
{
|
||||
resources.isDeveloper = true;
|
||||
if (selectedTab == Tab::CONSOLE) console.focus_request();
|
||||
}
|
||||
|
||||
if (!resources.isDeveloper)
|
||||
{
|
||||
isDeveloperOpen = false;
|
||||
return;
|
||||
}
|
||||
|
||||
recent_files_load();
|
||||
|
||||
auto* viewport = ImGui::GetMainViewport();
|
||||
auto windowSize =
|
||||
ImVec2(viewport->WorkSize.x * DEVELOPER_WINDOW_SIZE_RATIO, viewport->WorkSize.y * DEVELOPER_WINDOW_SIZE_RATIO);
|
||||
auto windowPosition = ImVec2(viewport->WorkPos.x + (viewport->WorkSize.x * CENTER_RATIO),
|
||||
viewport->WorkPos.y + (viewport->WorkSize.y * CENTER_RATIO));
|
||||
ImGui::SetNextWindowPos(windowPosition, ImGuiCond_Appearing, ImVec2(CENTER_RATIO, CENTER_RATIO));
|
||||
ImGui::SetNextWindowSize(windowSize, ImGuiCond_Appearing);
|
||||
|
||||
if (!isDeveloperOpen)
|
||||
{
|
||||
ImGui::SetNextWindowFocus();
|
||||
if (selectedTab == Tab::CONSOLE) console.focus_request();
|
||||
}
|
||||
isDeveloperOpen = true;
|
||||
|
||||
isContextUndoRequested = false;
|
||||
isContextRedoRequested = false;
|
||||
action = {};
|
||||
console.action = {};
|
||||
gIsDocumentUndoMenuRequested = false;
|
||||
gIsDocumentRedoMenuRequested = false;
|
||||
|
||||
if (selectedTab == Tab::EDITOR) editor_shortcuts_update();
|
||||
dialog_selection_update();
|
||||
|
||||
auto gameStyle = ImGui::GetStyle();
|
||||
ImGui::GetStyle() = ImGuiStyle{};
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui::PushFont(resources.font.get(), resource::Font::SMALL);
|
||||
|
||||
if (ImGui::Begin("Developer", &resources.isDeveloper, DEVELOPER_WINDOW_FLAGS))
|
||||
{
|
||||
auto isFocused = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows);
|
||||
if (isFocused && (shortcut_is_pressed(ImGuiKey_GraveAccent) || shortcut_is_pressed(ImGuiKey_Escape)))
|
||||
resources.isDeveloper = false;
|
||||
|
||||
if (ImGui::BeginTabBar("##Developer Tabs"))
|
||||
{
|
||||
auto isWasConsole = selectedTab == Tab::CONSOLE;
|
||||
if (ImGui::BeginTabItem("Console"))
|
||||
{
|
||||
selectedTab = Tab::CONSOLE;
|
||||
if (!isWasConsole) console.focus_request();
|
||||
console.update(resources, play);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Editor"))
|
||||
{
|
||||
selectedTab = Tab::EDITOR;
|
||||
editor_update(resources);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
if (gIsDocumentUndoMenuRequested) isContextUndoRequested = true;
|
||||
if (gIsDocumentRedoMenuRequested) isContextRedoRequested = true;
|
||||
action = console.action;
|
||||
if (isContextUndoRequested) undo(selectedDocument);
|
||||
if (isContextRedoRequested) redo(selectedDocument);
|
||||
|
||||
toasts.update();
|
||||
|
||||
ImGui::PopFont();
|
||||
ImGui::GetStyle() = gameStyle;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user