mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-11-10 06:31:48 +00:00
added file open/save dialog GUI logic
This commit is contained in:
parent
14f9d18075
commit
d1c19fbe2a
2 changed files with 168 additions and 3 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 2022-2023 Gian 'myT' Schellenbaum
|
Copyright (C) 2022-2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
This file is part of Challenge Quake 3 (CNQ3).
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
@ -99,6 +99,161 @@ void ToggleBooleanWithShortcut(bool& value, ImGuiKey key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FileDialog
|
||||||
|
{
|
||||||
|
char folder[MAX_QPATH];
|
||||||
|
char fileName[MAX_QPATH];
|
||||||
|
char filePath[MAX_QPATH];
|
||||||
|
char extension[MAX_QPATH];
|
||||||
|
const char* dialogName;
|
||||||
|
char** filePaths;
|
||||||
|
int fileCount;
|
||||||
|
int selectedFileIndex;
|
||||||
|
bool saveMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
static FileDialog saveFile;
|
||||||
|
static FileDialog openFile;
|
||||||
|
|
||||||
|
static bool PathHasExtension(const char* path, const char* extension)
|
||||||
|
{
|
||||||
|
Q_assert(extension[0] == '.');
|
||||||
|
|
||||||
|
const int pathLength = strlen(path);
|
||||||
|
const int extLength = strlen(extension);
|
||||||
|
if(extLength >= pathLength)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Q_stricmpn(path + pathLength - extLength, extension, extLength) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OpenFileDialog(FileDialog& dialog, const char* folder, const char* extension)
|
||||||
|
{
|
||||||
|
if(ImGui::IsPopupOpen(dialog.dialogName))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.fileName[0] = '\0';
|
||||||
|
Q_strncpyz(dialog.folder, folder, sizeof(dialog.folder));
|
||||||
|
Q_strncpyz(dialog.extension, extension, sizeof(dialog.extension));
|
||||||
|
dialog.filePaths = FS_ListFiles(folder, extension, &dialog.fileCount);
|
||||||
|
dialog.selectedFileIndex = -1;
|
||||||
|
ImGui::OpenPopup(dialog.dialogName);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool DoFileDialog(FileDialog& dialog)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
if(ImGui::BeginPopupModal(dialog.dialogName, NULL, ImGuiWindowFlags_AlwaysAutoResize))
|
||||||
|
{
|
||||||
|
if(BeginTable("Files", 1))
|
||||||
|
{
|
||||||
|
for(int i = 0; i < dialog.fileCount; i++)
|
||||||
|
{
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
if(ImGui::Selectable(dialog.filePaths[i], i == dialog.selectedFileIndex,
|
||||||
|
ImGuiSelectableFlags_DontClosePopups))
|
||||||
|
{
|
||||||
|
dialog.selectedFileIndex = i;
|
||||||
|
Q_strncpyz(dialog.fileName, dialog.filePaths[i], sizeof(dialog.fileName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dialog.saveMode)
|
||||||
|
{
|
||||||
|
if(ImGui::InputText("File path", dialog.fileName, sizeof(dialog.fileName)))
|
||||||
|
{
|
||||||
|
dialog.selectedFileIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::Button("Save") &&
|
||||||
|
dialog.fileName[0] != '\0' &&
|
||||||
|
dialog.fileName[0] != '.')
|
||||||
|
{
|
||||||
|
if(!PathHasExtension(dialog.fileName, dialog.extension))
|
||||||
|
{
|
||||||
|
const int lastCharIndex = strlen(dialog.fileName) - 1;
|
||||||
|
if(dialog.fileName[lastCharIndex] == '.')
|
||||||
|
{
|
||||||
|
dialog.fileName[lastCharIndex] = '\0';
|
||||||
|
}
|
||||||
|
Q_strcat(dialog.fileName, sizeof(dialog.fileName), dialog.extension);
|
||||||
|
}
|
||||||
|
Com_sprintf(dialog.filePath, sizeof(dialog.filePath),
|
||||||
|
"%s/%s", dialog.folder, dialog.fileName);
|
||||||
|
FS_FreeFileList(dialog.filePaths);
|
||||||
|
dialog.filePaths = NULL;
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(ImGui::Button("Open") &&
|
||||||
|
dialog.selectedFileIndex >= 0 &&
|
||||||
|
dialog.selectedFileIndex < dialog.fileCount)
|
||||||
|
{
|
||||||
|
Com_sprintf(dialog.filePath, sizeof(dialog.filePath),
|
||||||
|
"%s/%s", dialog.folder, dialog.filePaths[dialog.selectedFileIndex]);
|
||||||
|
FS_FreeFileList(dialog.filePaths);
|
||||||
|
dialog.filePaths = NULL;
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::Button("Cancel"))
|
||||||
|
{
|
||||||
|
FS_FreeFileList(dialog.filePaths);
|
||||||
|
dialog.filePaths = NULL;
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenSaveFileDialog(const char* folder, const char* extension)
|
||||||
|
{
|
||||||
|
Q_assert(extension[0] == '.');
|
||||||
|
OpenFileDialog(saveFile, folder, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SaveFileDialog()
|
||||||
|
{
|
||||||
|
return DoFileDialog(saveFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GetSaveFileDialogPath()
|
||||||
|
{
|
||||||
|
return saveFile.filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenOpenFileDialog(const char* folder, const char* extension)
|
||||||
|
{
|
||||||
|
Q_assert(extension[0] == '.');
|
||||||
|
OpenFileDialog(openFile, folder, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenFileDialog()
|
||||||
|
{
|
||||||
|
return DoFileDialog(openFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GetOpenFileDialogPath()
|
||||||
|
{
|
||||||
|
return openFile.filePath;
|
||||||
|
}
|
||||||
|
|
||||||
struct MainMenuItem
|
struct MainMenuItem
|
||||||
{
|
{
|
||||||
GUI_MainMenu::Id menu;
|
GUI_MainMenu::Id menu;
|
||||||
|
@ -235,7 +390,7 @@ static void ImGUI_ApplyTheme()
|
||||||
colors[ImGuiCol_NavHighlight] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
|
colors[ImGuiCol_NavHighlight] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
|
||||||
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 0.00f, 0.00f, 0.70f);
|
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 0.00f, 0.00f, 0.70f);
|
||||||
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(1.00f, 0.00f, 0.00f, 0.20f);
|
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(1.00f, 0.00f, 0.00f, 0.20f);
|
||||||
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(1.00f, 0.00f, 0.00f, 0.35f);
|
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.00f, 0.00f, 0.10f, 0.35f);
|
||||||
|
|
||||||
const ImVec4 hover(0.49f, 0.75f, 0.75f, 0.35f);
|
const ImVec4 hover(0.49f, 0.75f, 0.75f, 0.35f);
|
||||||
const ImVec4 active(0.49f, 1.00f, 1.00f, 0.55f);
|
const ImVec4 active(0.49f, 1.00f, 1.00f, 0.55f);
|
||||||
|
@ -454,6 +609,10 @@ void CL_IMGUI_Init()
|
||||||
{
|
{
|
||||||
keyMap[K_F1 + i] = ImGuiKey_F1 + i;
|
keyMap[K_F1 + i] = ImGuiKey_F1 + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saveFile.saveMode = true;
|
||||||
|
saveFile.dialogName = "Save file";
|
||||||
|
openFile.dialogName = "Open file";
|
||||||
}
|
}
|
||||||
|
|
||||||
void CL_IMGUI_Frame()
|
void CL_IMGUI_Frame()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 2022-2023 Gian 'myT' Schellenbaum
|
Copyright (C) 2022-2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
This file is part of Challenge Quake 3 (CNQ3).
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
@ -36,6 +36,12 @@ void TableRow2(const char* item0, int item1);
|
||||||
void TableRow2(const char* item0, float item1, const char* format = "%g");
|
void TableRow2(const char* item0, float item1, const char* format = "%g");
|
||||||
bool IsShortcutPressed(ImGuiKey key);
|
bool IsShortcutPressed(ImGuiKey key);
|
||||||
void ToggleBooleanWithShortcut(bool& value, ImGuiKey key);
|
void ToggleBooleanWithShortcut(bool& value, ImGuiKey key);
|
||||||
|
void OpenSaveFileDialog(const char* folder, const char* extension);
|
||||||
|
bool SaveFileDialog(); // true when the user clicked the save button
|
||||||
|
const char* GetSaveFileDialogPath();
|
||||||
|
void OpenOpenFileDialog(const char* folder, const char* extension);
|
||||||
|
bool OpenFileDialog(); // true when the user clicked the open button
|
||||||
|
const char* GetOpenFileDialogPath();
|
||||||
|
|
||||||
#define MAIN_MENU_LIST(M) \
|
#define MAIN_MENU_LIST(M) \
|
||||||
M(Tools, "Tools") \
|
M(Tools, "Tools") \
|
||||||
|
|
Loading…
Reference in a new issue