Open and draw a story teller project format

This commit is contained in:
Anthony Rabine 2023-12-10 22:37:12 +01:00
parent 3c01a29c66
commit 8b13a63e6b
35 changed files with 14091 additions and 2209 deletions

4
.gitignore vendored
View file

@ -59,3 +59,7 @@ story-editor-v2/src/CMakeSettings.json
story-editor-v2/imgui.ini
story-editor-v2/src/.vscode/
build-story-editor-v2-Desktop-Debug/
build-story-editor-Desktop-Debug/

View file

@ -22,64 +22,79 @@ if(POLICY CMP0072)
endif()
find_package(OpenGL REQUIRED)
set(IMGUI_VERSION 1.89.9)
set(IMGUI_VERSION 1.90)
include(FetchContent)
#=========================================================================================================================
# IMGUI and plugins
#=========================================================================================================================
FetchContent_Declare(imgui
URL https://github.com/ocornut/imgui/archive/refs/tags/v${IMGUI_VERSION}-docking.zip
)
FetchContent_GetProperties(imgui)
if (NOT imgui_POPULATED) # Have we downloaded raylib yet?
if (NOT imgui_POPULATED)
set(FETCHCONTENT_QUIET NO)
FetchContent_Populate(imgui)
endif()
# ImGuiFileDialog
include_directories(${imgui_SOURCE_DIR})
add_compile_definitions(CUSTOM_IMGUIFILEDIALOG_CONFIG="${CMAKE_SOURCE_DIR}/src/CustomImGuiFileDialogConfig.h")
add_compile_definitions(IMGUI_INCLUDE="imgui.h")
add_subdirectory(libs/ImGuiFileDialog)
#=========================================================================================================================
# SDL3
# SDL
#=========================================================================================================================
include(FetchContent)
Set(FETCHCONTENT_QUIET FALSE)
FetchContent_Declare(
SDL3
sdl2
GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
GIT_TAG origin/main
GIT_TAG origin/SDL2
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
set(BUILD_SHARED_LIBS TRUE)
set(SDL_STATIC TRUE)
FetchContent_MakeAvailable(SDL3)
FetchContent_MakeAvailable(sdl2)
#add_subdirectory(libs/SDL)
#include_directories(libs/SDL/include)
#=========================================================================================================================
# SDL3-Image
#=========================================================================================================================
FetchContent_Declare(
SDL2_image
GIT_REPOSITORY https://github.com/libsdl-org/SDL_image.git
GIT_TAG origin/main
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
#FetchContent_Declare(
# SDL2_image
# GIT_REPOSITORY https://github.com/libsdl-org/SDL_image.git
# GIT_TAG origin/main
# GIT_SHALLOW TRUE
# GIT_PROGRESS TRUE
#)
# START ADDITION
set(SDL2IMAGE_INSTALL OFF)
set(BUILD_SHARED_LIBS FALSE)
# END ADDITION
## START ADDITION
#set(SDL2IMAGE_INSTALL OFF)
#set(BUILD_SHARED_LIBS FALSE)
## END ADDITION
FetchContent_MakeAvailable(SDL2_image)
#FetchContent_MakeAvailable(SDL2_image)
set(SRCS
src/main.cpp
src/window_base.h
src/window_base.cpp
src/console_window.cpp
src/console_window.h
@ -95,6 +110,9 @@ set(SRCS
src/media_node.h
src/media_node.cpp
src/platform_folders.cpp
src/platform_folders.h
src/base_node.h
src/base_node.cpp
@ -115,8 +133,8 @@ set(SRCS
libs/imgui-node-editor/crude_json.cpp
libs/ImGuiFileDialog/ImGuiFileDialog.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_sdl3.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_sdlrenderer3.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_sdl2.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_sdlrenderer2.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp
${imgui_SOURCE_DIR}/imgui.cpp
${imgui_SOURCE_DIR}/imgui_widgets.cpp
@ -144,11 +162,13 @@ endif()
add_executable(${STORY_EDITOR_PROJECT}
${SRCS}
src/uuid.h
src/window_base.h src/window_base.cpp
)
target_include_directories(${STORY_EDITOR_PROJECT} PUBLIC
${imgui_SOURCE_DIR}
${sdl3_SOURCE_DIR}/include
${sdl2_SOURCE_DIR}/include
libs/ImGuiColorTextEdit/
${imgui_SOURCE_DIR}/backends
libs/ImGuiFileDialog
@ -159,21 +179,23 @@ target_include_directories(${STORY_EDITOR_PROJECT} PUBLIC
)
add_definitions(-DIMGUI_USE_WCHAR32)
add_link_options(-static-libgcc -static-libstdc++)
target_compile_definitions(${STORY_EDITOR_PROJECT} PUBLIC cimg_display=0)
target_link_directories(${STORY_EDITOR_PROJECT} PUBLIC ${sdl3_BINARY_DIR})
message(${sdl3_BINARY_DIR})
target_compile_definitions(${STORY_EDITOR_PROJECT} PUBLIC "$<$<CONFIG:DEBUG>:DEBUG>")
target_link_directories(${STORY_EDITOR_PROJECT} PUBLIC ${sdl2_BINARY_DIR})
message(${sdl2_BINARY_DIR})
if (UNIX)
target_link_libraries(${STORY_EDITOR_PROJECT}
pthread
udev
glfw
OpenGL::GL
dl
SDL3
SDL2
)
elseif(WIN32)
target_link_libraries(${STORY_EDITOR_PROJECT}

View file

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.5)
project(ImGuiFileDialog)
add_library(ImGuiFileDialog STATIC
ImGuiFileDialog.cpp
ImGuiFileDialog.h
ImGuiFileDialogConfig.h
)
target_include_directories(ImGuiFileDialog PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
if(UNIX)
target_compile_options(ImGuiFileDialog PUBLIC "-Wno-unknown-pragmas")
endif()

File diff suppressed because it is too large Load diff

View file

@ -43,21 +43,21 @@ SOFTWARE.
/*
// generated with "Text to ASCII Art Generator (TAAG)"
// https://patorjk.com/software/taag/#p=display&h=1&v=0&f=Big&t=ImGuiFileDialog%0Av0.6.5
_____ _____ _ ______ _ _ _____ _ _
|_ _| / ____| (_) ____(_) | | __ \(_) | |
| | _ __ ___ | | __ _ _ _| |__ _| | ___| | | |_ __ _| | ___ __ _
| | | '_ ` _ \| | |_ | | | | | __| | | |/ _ \ | | | |/ _` | |/ _ \ / _` |
_| |_| | | | | | |__| | |_| | | | | | | __/ |__| | | (_| | | (_) | (_| |
|_____|_| |_| |_|\_____|\__,_|_|_| |_|_|\___|_____/|_|\__,_|_|\___/ \__, |
_________________________________________________________________________/ |
|__________________________________________________________________________/
___ __ __
/ _ \ / / / /
__ __| | | | / /_ / /_
\ \ / /| | | | | '_ \ | '_ \
\ V / | |_| |_| (_) |_| (_) |
\_/ \___/(_)\___/(_)\___/
_____ _____ _ ______ _ _ _____ _ _
|_ _| / ____| (_)| ____|(_)| | | __ \ (_) | |
| | _ __ ___ | | __ _ _ _ | |__ _ | | ___ | | | | _ __ _ | | ___ __ _
| | | '_ ` _ \ | | |_ || | | || || __| | || | / _ \| | | || | / _` || | / _ \ / _` |
_| |_ | | | | | || |__| || |_| || || | | || || __/| |__| || || (_| || || (_) || (_| |
|_____||_| |_| |_| \_____| \__,_||_||_| |_||_| \___||_____/ |_| \__,_||_| \___/ \__, |
__/ |
|___/
___ __ ______
/ _ \ / / |____ |
__ __| | | | / /_ / /
\ \ / /| | | | | '_ \ / /
\ V / | |_| |_| (_) |_ / /
\_/ \___/(_)\___/(_)/_/
github repo : https://github.com/aiekick/ImGuiFileDialog
this section is the content of the ReadMe.md file
@ -73,7 +73,7 @@ solutions.
## ImGui Supported Version
ImGuiFileDialog follow the master and docking branch of ImGui . currently ImGui 1.89.7 WIP
ImGuiFileDialog follow the master and docking branch of ImGui . currently ImGui 1.90.1 WIP
## Structure
@ -760,7 +760,7 @@ ImGuiFileDialog::Instance()->ManageGPUThumbnails();
The dialog can be embedded in another user frame than the standard or modal dialog
You have to create a variable of type ImGuiFileDialog. (if you are suing the singleton, you will not have the
You have to create a variable of type ImGuiFileDialog. (if you are using the singleton, you will not have the
possibility to open other dialog)
ex :
@ -769,7 +769,7 @@ ex :
ImGuiFileDialog fileDialog;
// open dialog; in this case, Bookmark, directory creation are disabled with, and also the file input field is readonly.
// btw you can od what you want
// btw you can do what you want
fileDialog.OpenDialog("embedded", "Select File", ".*", "", -1, nullptr,
ImGuiFileDialogFlags_NoDialog |
ImGuiFileDialogFlags_DisableBookmarkMode |
@ -790,8 +790,8 @@ the result :
you have a separator between two directories in the path composer
when you click on it you can explore a list of parrallels directories of this point
this feature is disabled by default
you can enable it with the compiler flag : flags
this feature is enabled by default
you can disable it with the flag : ImGuiFileDialogFlags_DisableQuickPathSelection
you can also customize the spacing between path button's with and without this mode
you can do that by define the compiler flag : #define CUSTOM_PATH_SPACING 2
@ -915,7 +915,7 @@ but you can modify them.
There is 3 Modes :
```cpp
IGFD_ResultMode_AddIfNoFileExt [DEFAULT for
IGFD_ResultMode_AddIfNoFileExt [DEFAULT]
This mode add the filter ext only if there is no file ext. (compatible multi layer)
ex :
filter {.cpp,.h} with file :
@ -981,6 +981,27 @@ to note :
a collection {.a, .b.z} is a two dots filter, so a file toto.g.z will be replaced by toto.a
a collection {.z; .b} is a one dot filter, so a file toto.g.z will be replaced by toto.g.a
################################################################
## Custom FileSystem
################################################################
you can use your custom file system interface.
by default IGFD come with the File System Interfaces for Dirent or std::filesystem
but you have now a FileSystem interface called IFileSystem who can be overrided with your needs
by ex for android, emscripten, or boost
2 steps :
1) create a include file who must contain :
- your override of IGFD::IFileSystem
- a define of your class name in FILE_SYSTEM_OVERRIDE (ex : #define FILE_SYSTEM_OVERRIDE FileSystemBoost)
2) define your file system include file path in the preprocessor var "CUSTOM_FILESYSTEM_INCLUDE"
ex : #define CUSTOM_FILESYSTEM_INCLUDE "src/FileSystemBoost.hpp"
you can check the DemoApp who is using an override for the Boost::filesystem
################################################################
## How to Integrate ImGuiFileDialog in your project
################################################################
@ -1100,8 +1121,8 @@ The Custom Icon Font (in CustomFont.cpp and CustomFont.h) was made with ImGuiFon
#pragma region IGFD VERSION
// compatible with 1.89.7 WIP
#define IMGUIFILEDIALOG_VERSION "v0.6.6"
// compatible with 1.90.1 WIP
#define IMGUIFILEDIALOG_VERSION "v0.6.7"
#pragma endregion
@ -1127,8 +1148,7 @@ enum IGFD_FileStyleFlags_ // by evaluation / priority order
IGFD_FileStyleByTypeLink = (1 << 2), // define style for all link
IGFD_FileStyleByExtention = (1 << 3), // define style by extention, for files or links
IGFD_FileStyleByFullName = (1 << 4), // define style for particular file/dir/link full name (filename + extention)
IGFD_FileStyleByContainedInFullName =
(1 << 5), // define style for file/dir/link when criteria is contained in full name
IGFD_FileStyleByContainedInFullName = (1 << 5), // define style for file/dir/link when criteria is contained in full name
};
#pragma endregion
@ -1145,10 +1165,8 @@ enum ImGuiFileDialogFlags_ {
ImGuiFileDialogFlags_HideColumnSize = (1 << 4), // hide column file size
ImGuiFileDialogFlags_HideColumnDate = (1 << 5), // hide column file date
ImGuiFileDialogFlags_NoDialog = (1 << 6), // let the dialog embedded in your own imgui begin / end scope
ImGuiFileDialogFlags_ReadOnlyFileNameField =
(1 << 7), // don't let user type in filename field for file open style dialogs
ImGuiFileDialogFlags_CaseInsensitiveExtention =
(1 << 8), // the file extentions treatments will not take into account the case
ImGuiFileDialogFlags_ReadOnlyFileNameField = (1 << 7), // don't let user type in filename field for file open style dialogs
ImGuiFileDialogFlags_CaseInsensitiveExtention = (1 << 8), // the file extentions treatments will not take into account the case
ImGuiFileDialogFlags_Modal = (1 << 9), // modal
ImGuiFileDialogFlags_DisableThumbnailMode = (1 << 10), // disable the thumbnail mode
ImGuiFileDialogFlags_DisableBookmarkMode = (1 << 11), // disable the bookmark mode
@ -1341,14 +1359,30 @@ public:
m_Array.clear();
}
bool empty() const { return m_Array.empty(); }
size_t size() const { return m_Array.size(); }
T& operator[](const size_t& vIdx) { return m_Array[vIdx]; }
T& at(const size_t& vIdx) { return m_Array.at(vIdx); }
typename std::vector<T>::iterator begin() { return m_Array.begin(); }
typename std::vector<T>::const_iterator begin() const { return m_Array.begin(); }
typename std::vector<T>::iterator end() { return m_Array.end(); }
typename std::vector<T>::const_iterator end() const { return m_Array.end(); }
bool empty() const {
return m_Array.empty();
}
size_t size() const {
return m_Array.size();
}
T& operator[](const size_t& vIdx) {
return m_Array[vIdx];
}
T& at(const size_t& vIdx) {
return m_Array.at(vIdx);
}
typename std::vector<T>::iterator begin() {
return m_Array.begin();
}
typename std::vector<T>::const_iterator begin() const {
return m_Array.begin();
}
typename std::vector<T>::iterator end() {
return m_Array.end();
}
typename std::vector<T>::const_iterator end() const {
return m_Array.end();
}
bool try_add(T vKey) {
if (!exist(vKey)) {
@ -1368,7 +1402,9 @@ public:
return false;
}
bool exist(const std::string& vKey) const { return (m_Dico.find(vKey) != m_Dico.end()); }
bool exist(const std::string& vKey) const {
return (m_Dico.find(vKey) != m_Dico.end());
}
};
#pragma endregion
@ -1377,7 +1413,7 @@ public:
class IGFD_API Utils {
public:
struct IGFD_API PathStruct {
struct PathStruct {
std::string path;
std::string name;
std::string ext;
@ -1385,31 +1421,18 @@ public:
};
public:
static bool ImSplitter(bool split_vertically,
float thickness,
float* size1,
float* size2,
float min_size1,
float min_size2,
float splitter_long_axis_size = -1.0f);
static bool ReplaceString(
std::string& str, const std::string& oldStr, const std::string& newStr, const size_t& vMaxRecursion = 10U);
static bool IsDirectoryCanBeOpened(const std::string& name); // by ex protected dirs (not user rights)
static bool IsDirectoryExist(const std::string& name);
static bool CreateDirectoryIfNotExist(const std::string& name);
static PathStruct ParsePathFileName(const std::string& vPathFileName);
static bool ImSplitter(
bool split_vertically, float thickness, float* size1, float* size2, float min_size1, float min_size2, float splitter_long_axis_size = -1.0f);
static bool ReplaceString(std::string& str, const std::string& oldStr, const std::string& newStr, const size_t& vMaxRecursion = 10U);
static void AppendToBuffer(char* vBuffer, size_t vBufferLen, const std::string& vStr);
static void ResetBuffer(char* vBuffer);
static void SetBuffer(char* vBuffer, size_t vBufferLen, const std::string& vStr);
static std::string UTF8Encode(const std::wstring& wstr);
static std::wstring UTF8Decode(const std::string& str);
static std::vector<std::string> SplitStringToVector(
const std::string& vText, const char& vDelimiter, const bool& vPushEmpty);
static std::vector<std::string> GetDrivesList();
static std::vector<std::string> SplitStringToVector(const std::string& vText, const char& vDelimiter, const bool& vPushEmpty);
static std::string LowerCaseString(const std::string& vString); // turn all text in lower case for search facilitie
static size_t GetCharCountInString(const std::string& vString, const char& vChar);
static size_t GetLastCharPosWithMinCharCount(
const std::string& vString, const char& vChar, const size_t& vMinCharCount);
static size_t GetLastCharPosWithMinCharCount(const std::string& vString, const char& vChar, const size_t& vMinCharCount);
};
#pragma endregion
@ -1440,9 +1463,9 @@ public:
class IGFD_API FileDialogInternal;
class IGFD_API SearchManager {
public:
std::string puSearchTag;
char puSearchBuffer[MAX_FILE_DIALOG_NAME_BUFFER] = "";
bool puSearchInputIsActive = false;
std::string searchTag;
char searchBuffer[MAX_FILE_DIALOG_NAME_BUFFER] = "";
bool searchInputIsActive = false;
public:
void Clear(); // clear datas
@ -1476,8 +1499,7 @@ public:
void setCollectionTitle(const std::string& vTitle); // set the collection title
void addFilter(const std::string& vFilter, const bool& vIsRegex); // add a filter
void addCollectionFilter(const std::string& vFilter, const bool& vIsRegex); // add a filter in collection
std::string transformAsteriskBasedFilterToRegex(
const std::string& vFilter); // will transform a filter who contain * to a regex
std::string transformAsteriskBasedFilterToRegex(const std::string& vFilter); // will transform a filter who contain * to a regex
};
#pragma endregion
@ -1491,23 +1513,22 @@ public:
#else
private:
#endif
std::vector<FilterInfos> prParsedFilters;
std::unordered_map<IGFD_FileStyleFlags, std::unordered_map<std::string, std::shared_ptr<FileStyle>>>
prFilesStyle; // file infos for file extention only
std::vector<FileStyle::FileStyleFunctor> prFilesStyleFunctors; // file style via lambda function
FilterInfos prSelectedFilter;
std::vector<FilterInfos> m_ParsedFilters;
std::unordered_map<IGFD_FileStyleFlags, std::unordered_map<std::string, std::shared_ptr<FileStyle>>> m_FilesStyle; // file infos for file
// extention only
std::vector<FileStyle::FileStyleFunctor> m_FilesStyleFunctors; // file style via lambda function
FilterInfos m_SelectedFilter;
public:
std::string puDLGFilters;
std::string puDLGdefaultExt;
std::string dLGFilters;
std::string dLGdefaultExt;
public:
const FilterInfos& GetSelectedFilter() const;
void ParseFilters(const char* vFilters); // Parse filter syntax, detect and parse filter collection
void SetSelectedFilterWithExt(const std::string& vFilter); // Select filter
bool prFillFileStyle(std::shared_ptr<FileInfos> vFileInfos) const; // fill with the good style
void SetFileStyle(
const IGFD_FileStyleFlags& vFlags, const char* vCriteria, const FileStyle& vInfos); // Set FileStyle
bool m_FillFileStyle(std::shared_ptr<FileInfos> vFileInfos) const; // fill with the good style
void SetFileStyle(const IGFD_FileStyleFlags& vFlags, const char* vCriteria, const FileStyle& vInfos); // Set FileStyle
void SetFileStyle(const IGFD_FileStyleFlags& vFlags,
const char* vCriteria,
const ImVec4& vColor,
@ -1519,12 +1540,11 @@ public:
ImVec4* vOutColor,
std::string* vOutIcon,
ImFont** vOutFont); // Get Color and Icon for Filter
void ClearFilesStyle(); // clear prFileStyle
bool IsCoveredByFilters(const FileInfos& vFileInfos, bool vIsCaseInsensitive)
const; // check if current file extention (vExt) is covered by current filter, or by regex (vNameExt)
void ClearFilesStyle(); // clear m_FileStyle
bool IsCoveredByFilters(const FileInfos& vFileInfos,
bool vIsCaseInsensitive) const; // check if current file extention (vExt) is covered by current filter, or by regex (vNameExt)
float GetFilterComboBoxWidth() const; // will return the current combo box widget width
bool DrawFilterComboBox(
FileDialogInternal& vFileDialogInternal); // draw the filter combobox // get the current selected filter
bool DrawFilterComboBox(FileDialogInternal& vFileDialogInternal); // draw the filter combobox // get the current selected filter
std::string ReplaceExtentionWithCurrentFilterIfNeeded(const std::string& vFileName,
IGFD_ResultMode vFlag) const; // replace the extention of the current file by the selected filter
void SetDefaultFilterIfNotDefined(); // define the first filter if no filter is selected
@ -1593,13 +1613,37 @@ public:
public:
bool SearchForTag(const std::string& vTag) const; // will search a tag in fileNameExt and fileNameExt_optimized
bool SearchForExt(const std::string& vExt, const bool& vIsCaseInsensitive, const size_t& vMaxLevel = EXT_MAX_LEVEL)
const; // will check the fileExtLevels levels for vExt, until vMaxLevel
bool SearchForExts(
const std::string& vComaSepExts, const bool& vIsCaseInsensitive, const size_t& vMaxLevel = EXT_MAX_LEVEL)
const; // will check the fileExtLevels levels for vExts (ext are coma separated), until vMaxLevel
bool FinalizeFileTypeParsing(
const size_t& vMaxDotToExtract); // finalize the parsing the file (only a file or link to file. no dir)
bool SearchForExt(const std::string& vExt,
const bool& vIsCaseInsensitive,
const size_t& vMaxLevel = EXT_MAX_LEVEL) const; // will check the fileExtLevels levels for vExt, until vMaxLevel
bool SearchForExts(const std::string& vComaSepExts,
const bool& vIsCaseInsensitive,
const size_t& vMaxLevel = EXT_MAX_LEVEL) const; // will check the fileExtLevels levels for vExts (ext are coma separated), until vMaxLevel
bool FinalizeFileTypeParsing(const size_t& vMaxDotToExtract); // finalize the parsing the file (only a file or link to file. no dir)
};
#pragma endregion
#pragma region FILE SYSTEM INTERFACE
class IFileSystem {
public:
// say if a directory can be openened or for any reason locked
virtual bool IsDirectoryCanBeOpened(const std::string& vName) = 0;
// say if a directory exist
virtual bool IsDirectoryExist(const std::string& vName) = 0;
// say if a file exist
virtual bool IsFileExist(const std::string& vName) = 0;
// say if a directory was created, return false if vName is invalid or alreayd exist
virtual bool CreateDirectoryIfNotExist(const std::string& vName) = 0;
// extract the component of a file apth name, like path, name, ext
virtual IGFD::Utils::PathStruct ParsePathFileName(const std::string& vPathFileName) = 0;
// will return a list of files inside a path
virtual std::vector<IGFD::FileInfos> ScanDirectory(const std::string& vPath) = 0;
// say if the path is well a directory
virtual bool IsDirectory(const std::string& vFilePathName) = 0;
// return a drive list on windows, bu can be used on android or linux for give to the suer a list of root dir
virtual std::vector<std::string> GetDrivesList() = 0;
};
#pragma endregion
@ -1609,7 +1653,7 @@ public:
class IGFD_API FileManager {
public: // types
enum class SortingFieldEnum { // sorting for filetering of the file lsit
FIELD_NONE = 0, // no sorting preference, result indetermined haha..
FIELD_NONE = 0, // no sorting reference, result indetermined haha..
FIELD_FILENAME, // sorted by filename
FIELD_TYPE, // sorted by filetype
FIELD_SIZE, // sorted by filesize (formated file size)
@ -1622,85 +1666,75 @@ public:
#else
private:
#endif
std::string prCurrentPath; // current path (to be decomposed in prCurrentPathDecomposition
std::vector<std::string> prCurrentPathDecomposition; // part words
std::vector<std::shared_ptr<FileInfos>> prFileList; // base container
std::vector<std::shared_ptr<FileInfos>> prFilteredFileList; // filtered container (search, sorting, etc..)
std::vector<std::shared_ptr<FileInfos>> prPathList; // base container for path selection
std::vector<std::shared_ptr<FileInfos>> prFilteredPathList; // filtered container for path selection (search,
// sorting, etc..)
std::vector<std::string>::iterator prPopupComposedPath; // iterator on prCurrentPathDecomposition for Current Path
// popup
std::string prLastSelectedFileName; // for shift multi selection
std::set<std::string> prSelectedFileNames; // the user selection of FilePathNames
bool prCreateDirectoryMode = false; // for create directory widget
std::string m_CurrentPath; // current path (to be decomposed in m_CurrentPathDecomposition
std::vector<std::string> m_CurrentPathDecomposition; // part words
std::vector<std::shared_ptr<FileInfos>> m_FileList; // base container
std::vector<std::shared_ptr<FileInfos>> m_FilteredFileList; // filtered container (search, sorting, etc..)
std::vector<std::shared_ptr<FileInfos>> m_PathList; // base container for path selection
std::vector<std::shared_ptr<FileInfos>> m_FilteredPathList; // filtered container for path selection (search, sorting, etc..)
std::vector<std::string>::iterator m_PopupComposedPath; // iterator on m_CurrentPathDecomposition for Current Path popup
std::string m_LastSelectedFileName; // for shift multi selection
std::set<std::string> m_SelectedFileNames; // the user selection of FilePathNames
bool m_CreateDirectoryMode = false; // for create directory widget
std::unique_ptr<IFileSystem> m_FileSystemPtr = nullptr;
public:
bool puInputPathActivated = false; // show input for path edition
bool puDrivesClicked = false; // event when a drive button is clicked
bool inputPathActivated = false; // show input for path edition
bool drivesClicked = false; // event when a drive button is clicked
bool puPathClicked = false; // event when a path button was clicked
char puInputPathBuffer[MAX_PATH_BUFFER_SIZE] =
""; // input path buffer for imgui widget input text (displayed in palce of composer)
char puVariadicBuffer[MAX_FILE_DIALOG_NAME_BUFFER] = ""; // called by prSelectableItem
char puFileNameBuffer[MAX_FILE_DIALOG_NAME_BUFFER] = ""; // file name buffer in footer for imgui widget input text
char puDirectoryNameBuffer[MAX_FILE_DIALOG_NAME_BUFFER] =
""; // directory name buffer in footer for imgui widget input text (when is directory mode)
std::string puHeaderFileName; // detail view name of column file
std::string puHeaderFileType; // detail view name of column type
std::string puHeaderFileSize; // detail view name of column size
std::string puHeaderFileDate; // detail view name of column date + time
char inputPathBuffer[MAX_PATH_BUFFER_SIZE] = ""; // input path buffer for imgui widget input text (displayed in palce of composer)
char variadicBuffer[MAX_FILE_DIALOG_NAME_BUFFER] = ""; // called by m_SelectableItem
char fileNameBuffer[MAX_FILE_DIALOG_NAME_BUFFER] = ""; // file name buffer in footer for imgui widget input text
char directoryNameBuffer[MAX_FILE_DIALOG_NAME_BUFFER] = ""; // directory name buffer (when in directory mode)
std::string headerFileName; // detail view name of column file
std::string headerFileType; // detail view name of column type
std::string headerFileSize; // detail view name of column size
std::string headerFileDate; // detail view name of column date + time
#ifdef USE_THUMBNAILS
std::string puHeaderFileThumbnails; // detail view name of column thumbnails
bool puSortingDirection[5] = { // true => Ascending, false => Descending
defaultSortOrderFilename, defaultSortOrderType, defaultSortOrderSize, defaultSortOrderDate,
defaultSortOrderThumbnails};
std::string headerFileThumbnails; // detail view name of column thumbnails
bool sortingDirection[5] = { // true => Ascending, false => Descending
defaultSortOrderFilename, defaultSortOrderType, defaultSortOrderSize, defaultSortOrderDate, defaultSortOrderThumbnails};
#else
bool puSortingDirection[4] = { // true => Ascending, false => Descending
bool sortingDirection[4] = { // true => Ascending, false => Descending
defaultSortOrderFilename, defaultSortOrderType, defaultSortOrderSize, defaultSortOrderDate};
#endif
SortingFieldEnum puSortingField = SortingFieldEnum::FIELD_FILENAME; // detail view sorting column
bool puShowDrives = false; // drives are shown (only on os windows)
SortingFieldEnum sortingField = SortingFieldEnum::FIELD_FILENAME; // detail view sorting column
bool showDrives = false; // drives are shown (only on os windows)
std::string puDLGpath; // base path set by user when OpenDialog was called
std::string puDLGDefaultFileName; // base default file path name set by user when OpenDialog was called
size_t puDLGcountSelectionMax =
1U; // 0 for infinite // base max selection count set by user when OpenDialog was called
bool puDLGDirectoryMode = false; // is directory mode (defiend like : puDLGDirectoryMode = (filters.empty()))
std::string dLGpath; // base path set by user when OpenDialog was called
std::string dLGDefaultFileName; // base default file path name set by user when OpenDialog was called
size_t dLGcountSelectionMax = 1U; // 0 for infinite // base max selection count set by user when OpenDialog was called
bool dLGDirectoryMode = false; // is directory mode (defiend like : dLGDirectoryMode = (filters.empty()))
std::string puFsRoot;
std::string fsRoot;
#ifdef NEED_TO_BE_PUBLIC_FOR_TESTS
public:
#else
private:
#endif
static std::string prRoundNumber(double vvalue, int n); // custom rounding number
static std::string prFormatFileSize(size_t vByteSize); // format file size field
static void prCompleteFileInfos(
const std::shared_ptr<FileInfos>& FileInfos); // set time and date infos of a file (detail view mode)
void prRemoveFileNameInSelection(const std::string& vFileName); // selection : remove a file name
void prAddFileNameInSelection(
const std::string& vFileName, bool vSetLastSelectionFileName); // selection : add a file name
void AddFile(const FileDialogInternal& vFileDialogInternal,
static std::string m_RoundNumber(double vvalue, int n); // custom rounding number
static std::string m_FormatFileSize(size_t vByteSize); // format file size field
static void m_CompleteFileInfos(const std::shared_ptr<FileInfos>& FileInfos); // set time and date infos of a file (detail view mode)
void m_RemoveFileNameInSelection(const std::string& vFileName); // selection : remove a file name
void m_m_AddFileNameInSelection(const std::string& vFileName, bool vSetLastSelectionFileName); // selection : add a file name
void m_AddFile(const FileDialogInternal& vFileDialogInternal,
const std::string& vPath,
const std::string& vFileName,
const FileType& vFileType); // add file called by scandir
void AddPath(const FileDialogInternal& vFileDialogInternal,
void m_AddPath(const FileDialogInternal& vFileDialogInternal,
const std::string& vPath,
const std::string& vFileName,
const FileType& vFileType); // add file called by scandir
void ScanDirForPathSelection(const FileDialogInternal& vFileDialogInternal,
void m_ScanDirForPathSelection(const FileDialogInternal& vFileDialogInternal,
const std::string& vPath); // scan the directory for retrieve the path list
void OpenPathPopup(const FileDialogInternal& vFileDialogInternal,
void m_OpenPathPopup(const FileDialogInternal& vFileDialogInternal,
std::vector<std::string>::iterator vPathIter); // open the popup list of paths
void SetCurrentPath(std::vector<std::string>::iterator vPathIter); // set the current path, update the path bar
void ApplyFilteringOnFileList(const FileDialogInternal& vFileDialogInternal,
void m_SetCurrentPath(std::vector<std::string>::iterator vPathIter); // set the current path, update the path bar
void m_ApplyFilteringOnFileList(const FileDialogInternal& vFileDialogInternal,
std::vector<std::shared_ptr<FileInfos>>& vFileInfosList,
std::vector<std::shared_ptr<FileInfos>>& vFileInfosFilteredList);
void SortFields(const FileDialogInternal& vFileDialogInternal,
void m_SortFields(const FileDialogInternal& vFileDialogInternal,
std::vector<std::shared_ptr<FileInfos>>& vFileInfosList,
std::vector<std::shared_ptr<FileInfos>>& vFileInfosFilteredList); // will sort a column
@ -1731,12 +1765,10 @@ public:
// scandir for populate the file listview
bool GetDrives(); // list drives on windows platform
bool CreateDir(const std::string& vPath); // create a directory on the file system
std::string ComposeNewPath(
std::vector<std::string>::iterator vIter); // compose a path from the compose path widget
std::string ComposeNewPath(std::vector<std::string>::iterator vIter); // compose a path from the compose path widget
bool SetPathOnParentDirectoryIfAny(); // compose paht on parent directory
std::string GetCurrentPath(); // get the current path
void SetCurrentPath(const std::string& vCurrentPath); // set the current path
static bool IsFileExist(const std::string& vFile);
void SetDefaultFileName(const std::string& vFileName);
bool SelectDirectory(const std::shared_ptr<FileInfos>& vInfos); // enter directory
void SelectFileName(const FileDialogInternal& vFileDialogInternal,
@ -1745,16 +1777,17 @@ public:
void ScanDir(const FileDialogInternal& vFileDialogInternal,
const std::string& vPath); // scan the directory for retrieve the file list
public:
std::string GetResultingPath();
std::string GetResultingFileName(FileDialogInternal& vFileDialogInternal, IGFD_ResultMode vFlag);
std::string GetResultingFilePathName(FileDialogInternal& vFileDialogInternal, IGFD_ResultMode vFlag);
std::map<std::string, std::string> GetResultingSelection(
FileDialogInternal& vFileDialogInternal, IGFD_ResultMode vFlag);
std::map<std::string, std::string> GetResultingSelection(FileDialogInternal& vFileDialogInternal, IGFD_ResultMode vFlag);
public:
void DrawDirectoryCreation(const FileDialogInternal& vFileDialogInternal); // draw directory creation widget
void DrawPathComposer(const FileDialogInternal& vFileDialogInternal); // draw path composer widget
void DrawPathComposer(const FileDialogInternal& vFileDialogInternal);
IFileSystem* GetFileSystemInstance() {
return m_FileSystemPtr.get();
}
};
#pragma endregion
@ -1765,32 +1798,32 @@ typedef void* UserDatas;
typedef std::function<void(const char*, UserDatas, bool*)> PaneFun; // side pane function binding
class IGFD_API FileDialogInternal {
public:
FileManager puFileManager; // the file manager
FilterManager puFilterManager; // the filter manager
SearchManager puSearchManager; // the search manager
FileManager fileManager; // the file manager
FilterManager filterManager; // the filter manager
SearchManager searchManager; // the search manager
public:
std::string puName; // the internal dialog name (title + ##word)
bool puShowDialog = false; // the dialog is shown
ImVec2 puDialogCenterPos = ImVec2(0, 0); // center pos for display the confirm overwrite dialog
int puLastImGuiFrameCount = 0; // to be sure than only one dialog displayed per frame
float puFooterHeight = 0.0f; // footer height
bool puCanWeContinue = true; // events
bool puOkResultToConfirm = false; // to confim if ok for OverWrite
bool puIsOk = false; // is dialog ok button click
bool puFileInputIsActive = false; // when input text for file or directory is active
bool puFileListViewIsActive = false; // when list view is active
std::string puDLGkey; // the dialog key
std::string puDLGtitle; // the dialog title
ImGuiFileDialogFlags puDLGflags = ImGuiFileDialogFlags_None; // default dialog flag
UserDatas puDLGuserDatas = nullptr; // the user datas passed to a dialog
PaneFun puDLGoptionsPane = nullptr; // the user side pane
float puDLGoptionsPaneWidth = 0.0f; // the user side pane width
bool puNeedToExitDialog = false; // we need to exit the dialog
std::string name; // the internal dialog name (title + ##word)
bool showDialog = false; // the dialog is shown
ImVec2 dialogCenterPos = ImVec2(0, 0); // center pos for display the confirm overwrite dialog
int lastImGuiFrameCount = 0; // to be sure than only one dialog displayed per frame
float footerHeight = 0.0f; // footer height
bool canWeContinue = true; // events
bool okResultToConfirm = false; // to confim if ok for OverWrite
bool isOk = false; // is dialog ok button click
bool fileInputIsActive = false; // when input text for file or directory is active
bool fileListViewIsActive = false; // when list view is active
std::string dLGkey; // the dialog key
std::string dLGtitle; // the dialog title
ImGuiFileDialogFlags dLGflags = ImGuiFileDialogFlags_None; // default dialog flag
UserDatas dLGuserDatas = nullptr; // the user datas passed to a dialog
PaneFun dLGoptionsPane = nullptr; // the user side pane
float dLGoptionsPaneWidth = 0.0f; // the user side pane width
bool needToExitDialog = false; // we need to exit the dialog
bool puUseCustomLocale = false; // custom user locale
int puLocaleCategory = LC_ALL; // locale category to use
std::string puLocaleBegin; // the locale who will be applied at start of the display dialog
std::string puLocaleEnd; // the locale who will be applaied at end of the display dialog
int localeCategory = LC_ALL; // locale category to use
std::string localeBegin; // the locale who will be applied at start of the display dialog
std::string localeEnd; // the locale who will be applaied at end of the display dialog
public:
void NewFrame(); // new frame, so maybe neded to do somethings, like reset events
@ -1815,46 +1848,45 @@ protected:
ThumbnailFeature();
~ThumbnailFeature();
void NewThumbnailFrame(FileDialogInternal& vFileDialogInternal);
void EndThumbnailFrame(FileDialogInternal& vFileDialogInternal);
void QuitThumbnailFrame(FileDialogInternal& vFileDialogInternal);
void m_NewThumbnailFrame(FileDialogInternal& vFileDialogInternal);
void m_EndThumbnailFrame(FileDialogInternal& vFileDialogInternal);
void m_QuitThumbnailFrame(FileDialogInternal& vFileDialogInternal);
#ifdef USE_THUMBNAILS
protected:
enum class DisplayModeEnum { FILE_LIST = 0, THUMBNAILS_LIST, THUMBNAILS_GRID };
private:
uint32_t prCountFiles = 0U;
bool prIsWorking = false;
std::shared_ptr<std::thread> prThumbnailGenerationThread = nullptr;
std::list<std::shared_ptr<FileInfos>> prThumbnailFileDatasToGet; // base container
std::mutex prThumbnailFileDatasToGetMutex;
std::list<std::shared_ptr<FileInfos>> prThumbnailToCreate; // base container
std::mutex prThumbnailToCreateMutex;
std::list<IGFD_Thumbnail_Info> prThumbnailToDestroy; // base container
std::mutex prThumbnailToDestroyMutex;
uint32_t m_CountFiles = 0U;
bool m_IsWorking = false;
std::shared_ptr<std::thread> m_ThumbnailGenerationThread = nullptr;
std::list<std::shared_ptr<FileInfos>> m_ThumbnailFileDatasToGet; // base container
std::mutex m_ThumbnailFileDatasToGetMutex;
std::list<std::shared_ptr<FileInfos>> m_ThumbnailToCreate; // base container
std::mutex m_ThumbnailToCreateMutex;
std::list<IGFD_Thumbnail_Info> m_ThumbnailToDestroy; // base container
std::mutex m_ThumbnailToDestroyMutex;
CreateThumbnailFun prCreateThumbnailFun = nullptr;
DestroyThumbnailFun prDestroyThumbnailFun = nullptr;
CreateThumbnailFun m_CreateThumbnailFun = nullptr;
DestroyThumbnailFun m_DestroyThumbnailFun = nullptr;
protected:
DisplayModeEnum prDisplayMode = DisplayModeEnum::FILE_LIST;
DisplayModeEnum m_DisplayMode = DisplayModeEnum::FILE_LIST;
private:
void prVariadicProgressBar(float fraction, const ImVec2& size_arg, const char* fmt, ...);
void m_VariadicProgressBar(float fraction, const ImVec2& size_arg, const char* fmt, ...);
protected:
// will be call in cpu zone (imgui computations, will call a texture file retrieval thread)
void prStartThumbnailFileDatasExtraction(); // start the thread who will get byte buffer from image files
bool prStopThumbnailFileDatasExtraction(); // stop the thread who will get byte buffer from image files
void prThreadThumbnailFileDatasExtractionFunc(); // the thread who will get byte buffer from image files
void prDrawThumbnailGenerationProgress(); // a little progressbar who will display the texture gen status
void prAddThumbnailToLoad(const std::shared_ptr<FileInfos>& vFileInfos); // add texture to load in the thread
void prAddThumbnailToCreate(const std::shared_ptr<FileInfos>& vFileInfos);
void prAddThumbnailToDestroy(const IGFD_Thumbnail_Info& vIGFD_Thumbnail_Info);
void prDrawDisplayModeToolBar(); // draw display mode toolbar (file list, thumbnails list, small thumbnails grid,
// big thumbnails grid)
void prClearThumbnails(FileDialogInternal& vFileDialogInternal);
void m_StartThumbnailFileDatasExtraction(); // start the thread who will get byte buffer from image files
bool m_StopThumbnailFileDatasExtraction(); // stop the thread who will get byte buffer from image files
void m_ThreadThumbnailFileDatasExtractionFunc(); // the thread who will get byte buffer from image files
void m_DrawThumbnailGenerationProgress(); // a little progressbar who will display the texture gen status
void m_AddThumbnailToLoad(const std::shared_ptr<FileInfos>& vFileInfos); // add texture to load in the thread
void m_AddThumbnailToCreate(const std::shared_ptr<FileInfos>& vFileInfos);
void m_AddThumbnailToDestroy(const IGFD_Thumbnail_Info& vIGFD_Thumbnail_Info);
void m_DrawDisplayModeToolBar(); // draw display mode toolbar (file list, thumbnails list, small thumbnails grid, big thumbnails grid)
void m_ClearThumbnails(FileDialogInternal& vFileDialogInternal);
public:
void SetCreateThumbnailCallback(const CreateThumbnailFun& vCreateThumbnailFun);
@ -1885,24 +1917,23 @@ private:
};
private:
ImGuiListClipper prBookmarkClipper;
std::vector<BookmarkStruct> prBookmarks;
char prBookmarkEditBuffer[MAX_FILE_DIALOG_NAME_BUFFER] = "";
ImGuiListClipper m_BookmarkClipper;
std::vector<BookmarkStruct> m_Bookmarks;
char m_BookmarkEditBuffer[MAX_FILE_DIALOG_NAME_BUFFER] = "";
protected:
float prBookmarkWidth = 200.0f;
bool prBookmarkPaneShown = false;
float m_BookmarkWidth = 200.0f;
bool m_BookmarkPaneShown = false;
protected:
void prDrawBookmarkButton(); // draw bookmark button
bool prDrawBookmarkPane(FileDialogInternal& vFileDialogInternal, const ImVec2& vSize); // draw bookmark Pane
void m_DrawBookmarkButton(); // draw bookmark button
bool m_DrawBookmarkPane(FileDialogInternal& vFileDialogInternal, const ImVec2& vSize); // draw bookmark Pane
public:
std::string SerializeBookmarks( // serialize bookmarks : return bookmark buffer to save in a file
const bool& vDontSerializeCodeBasedBookmarks = true); // for avoid serialization of bookmarks added by code
void DeserializeBookmarks( // deserialize bookmarks : load bookmark buffer to load in the dialog (saved from
// previous use with SerializeBookmarks())
const std::string& vBookmarks); // bookmark buffer to load
const std::string& vBookmarks); // previous use with SerializeBookmarks()) bookmark buffer to load
void AddBookmark( // add a bookmark by code
const std::string& vBookMarkName, // bookmark name
const std::string& vBookMarkPath); // bookmark path
@ -1923,30 +1954,28 @@ protected:
#ifdef USE_EXPLORATION_BY_KEYS
private:
bool prLocateFileByInputChar_lastFound = false;
ImWchar prLocateFileByInputChar_lastChar = 0;
float prFlashAlpha = 0.0f; // flash when select by char
float prFlashAlphaAttenInSecs = 1.0f; // fps display dependant
int prLocateFileByInputChar_InputQueueCharactersSize = 0;
size_t prFlashedItem = 0; // flash when select by char
size_t prLocateFileByInputChar_lastFileIdx = 0;
bool m_LocateFileByInputChar_lastFound = false;
ImWchar m_LocateFileByInputChar_lastChar = 0;
float m_FlashAlpha = 0.0f; // flash when select by char
float m_FlashAlphaAttenInSecs = 1.0f; // fps display dependant
int m_LocateFileByInputChar_InputQueueCharactersSize = 0;
size_t m_FlashedItem = 0; // flash when select by char
size_t m_LocateFileByInputChar_lastFileIdx = 0;
protected:
void prLocateByInputKey(
FileDialogInternal& vFileDialogInternal); // select a file line in listview according to char key
bool prLocateItem_Loop(FileDialogInternal& vFileDialogInternal,
void m_LocateByInputKey(FileDialogInternal& vFileDialogInternal); // select a file line in listview according to char key
bool m_LocateItem_Loop(FileDialogInternal& vFileDialogInternal,
ImWchar vC); // restrat for start of list view if not found a corresponding file
void prExploreWithkeys(FileDialogInternal& vFileDialogInternal,
void m_ExploreWithkeys(FileDialogInternal& vFileDialogInternal,
ImGuiID vListViewID); // select file/directory line in listview accroding to up/down enter/backspace keys
void prStartFlashItem(size_t vIdx); // define than an item must be flashed
bool prBeginFlashItem(size_t vIdx); // start the flashing of a line in lsit view
static void prEndFlashItem(); // end the fleshing accrdoin to var prFlashAlphaAttenInSecs
static bool prFlashableSelectable(const char* label,
void m_StartFlashItem(size_t vIdx); // define than an item must be flashed
bool m_BeginFlashItem(size_t vIdx); // start the flashing of a line in lsit view
static void m_EndFlashItem(); // end the fleshing accrdoin to var m_FlashAlphaAttenInSecs
static bool m_FlashableSelectable(const char* label,
bool selected = false,
ImGuiSelectableFlags flags = 0,
bool vFlashing = false,
const ImVec2& size = ImVec2(
0, 0)); // custom flashing selectable widgets, for flash the selected line in a short time
const ImVec2& size = ImVec2(0, 0)); // custom flashing selectable widgets, for flash the selected line in a short time
public:
void SetFlashingAttenuationInSeconds( // set the flashing time of the line in file list when use exploration keys
@ -1962,9 +1991,9 @@ public:
class IGFD_API FileDialog : public BookMarkFeature, public KeyExplorerFeature, public ThumbnailFeature {
protected:
FileDialogInternal prFileDialogInternal;
ImGuiListClipper prFileListClipper;
ImGuiListClipper prPathListClipper;
FileDialogInternal m_FileDialogInternal;
ImGuiListClipper m_FileListClipper;
ImGuiListClipper m_PathListClipper;
float prOkCancelButtonWidth = 0.0f;
public:
@ -1989,7 +2018,8 @@ public:
virtual // todo : need to refactor all theses function to maybe just one
// standard dialog
void OpenDialog( // open simple dialog (path and fileName can be specified)
void
OpenDialog( // open simple dialog (path and fileName can be specified)
const std::string& vKey, // key dialog
const std::string& vTitle, // title
const char* vFilters, // filters
@ -2053,11 +2083,8 @@ public:
IGFD_ResultMode vFlag = IGFD_ResultMode_KeepInputFile); // Open File behavior : will return selection via a
// map<FileName, FilePathName>
std::string GetFilePathName(
IGFD_ResultMode vFlag =
IGFD_ResultMode_AddIfNoFileExt); // Save File behavior : will return the current file path name
std::string GetCurrentFileName(
IGFD_ResultMode vFlag =
IGFD_ResultMode_AddIfNoFileExt); // Save File behavior : will return the content file name
IGFD_ResultMode vFlag = IGFD_ResultMode_AddIfNoFileExt); // Save File behavior : will return the current file path name
std::string GetCurrentFileName(IGFD_ResultMode vFlag = IGFD_ResultMode_AddIfNoFileExt); // Save File behavior : will return the content file name
std::string GetCurrentPath(); // will return current file path
std::string GetCurrentFilter(); // will return current filter
UserDatas GetUserDatas() const; // will return user datas send with Open Dialog
@ -2089,48 +2116,48 @@ public:
const std::string& vLocaleEnd); // locale to use at the end of the dialog display
protected:
void NewFrame(); // new frame just at begining of display
void EndFrame(); // end frame just at end of display
void QuitFrame(); // quit frame when qui quit the dialog
void m_NewFrame(); // new frame just at begining of display
void m_EndFrame(); // end frame just at end of display
void m_QuitFrame(); // quit frame when qui quit the dialog
// others
bool prConfirm_Or_OpenOverWriteFileDialog_IfNeeded(
bool m_Confirm_Or_OpenOverWriteFileDialog_IfNeeded(
bool vLastAction, ImGuiWindowFlags vFlags); // treatment of the result, start the confirm to overwrite dialog
// if needed (if defined with flag)
// dialog parts
virtual void prDrawHeader(); // draw header part of the dialog (bookmark btn, dir creation, path composer, search
virtual void m_DrawHeader(); // draw header part of the dialog (bookmark btn, dir creation, path composer, search
// bar)
virtual void prDrawContent(); // draw content part of the dialog (bookmark pane, file list, side pane)
virtual bool prDrawFooter(); // draw footer part of the dialog (file field, fitler combobox, ok/cancel btn's)
virtual void m_DrawContent(); // draw content part of the dialog (bookmark pane, file list, side pane)
virtual bool m_DrawFooter(); // draw footer part of the dialog (file field, fitler combobox, ok/cancel btn's)
// widgets components
virtual void DisplayPathPopup(ImVec2 vSize); // draw path popup when click on a \ or /
virtual bool prDrawValidationButtons(); // draw validations btns, ok, cancel buttons
virtual bool prDrawOkButton(); // draw ok button
virtual bool prDrawCancelButton(); // draw cancel button
virtual void prDrawSidePane(float vHeight); // draw side pane
virtual void prSelectableItem(int vidx,
virtual void m_DisplayPathPopup(ImVec2 vSize); // draw path popup when click on a \ or /
virtual bool m_DrawValidationButtons(); // draw validations btns, ok, cancel buttons
virtual bool m_DrawOkButton(); // draw ok button
virtual bool m_DrawCancelButton(); // draw cancel button
virtual void m_DrawSidePane(float vHeight); // draw side pane
virtual void m_SelectableItem(int vidx,
std::shared_ptr<FileInfos> vInfos,
bool vSelected,
const char* vFmt,
...); // draw a custom selectable behavior item
virtual void prDrawFileListView(ImVec2 vSize); // draw file list view (default mode)
virtual void m_DrawFileListView(ImVec2 vSize); // draw file list view (default mode)
#ifdef USE_THUMBNAILS
virtual void prDrawThumbnailsListView(ImVec2 vSize); // draw file list view with small thumbnails on the same line
virtual void prDrawThumbnailsGridView(ImVec2 vSize); // draw a grid of small thumbnails
virtual void m_DrawThumbnailsListView(ImVec2 vSize); // draw file list view with small thumbnails on the same line
virtual void m_DrawThumbnailsGridView(ImVec2 vSize); // draw a grid of small thumbnails
#endif
// to be called only by these function and theirs overrides
// - prDrawFileListView
// - prDrawThumbnailsListView
// - prDrawThumbnailsGridView
void prBeginFileColorIconStyle(std::shared_ptr<FileInfos> vFileInfos,
// - m_DrawFileListView
// - m_DrawThumbnailsListView
// - m_DrawThumbnailsGridView
void m_BeginFileColorIconStyle(std::shared_ptr<FileInfos> vFileInfos,
bool& vOutShowColor,
std::string& vOutStr,
ImFont** vOutFont); // begin style apply of filter with color an icon if any
void prEndFileColorIconStyle(const bool& vShowColor, ImFont* vFont); // end style apply of filter
void m_EndFileColorIconStyle(const bool& vShowColor, ImFont* vFont); // end style apply of filter
};
#pragma endregion
@ -2177,8 +2204,7 @@ struct IGFD_Selection_Pair {
};
IGFD_C_API IGFD_Selection_Pair IGFD_Selection_Pair_Get(); // return an initialized IGFD_Selection_Pair
IGFD_C_API void IGFD_Selection_Pair_DestroyContent(
IGFD_Selection_Pair* vSelection_Pair); // destroy the content of a IGFD_Selection_Pair
IGFD_C_API void IGFD_Selection_Pair_DestroyContent(IGFD_Selection_Pair* vSelection_Pair); // destroy the content of a IGFD_Selection_Pair
struct IGFD_Selection {
IGFD_Selection_Pair* table; // 0
@ -2272,8 +2298,7 @@ IGFD_C_API bool IGFD_IsKeyOpened( // say if the dialog key is opened
IGFD_C_API bool IGFD_IsOpened( // say if the dialog is opened somewhere
ImGuiFileDialog* vContextPtr); // ImGuiFileDialog context
IGFD_C_API IGFD_Selection
IGFD_GetSelection( // Open File behavior : will return selection via a map<FileName, FilePathName>
IGFD_C_API IGFD_Selection IGFD_GetSelection( // Open File behavior : will return selection via a map<FileName, FilePathName>
ImGuiFileDialog* vContextPtr, // user datas (can be retrieved in pane)
IGFD_ResultMode vMode); // Result Mode

View file

@ -2,8 +2,12 @@
// uncomment and modify defines under for customize ImGuiFileDialog
//this options need c++17
//#define USE_STD_FILESYSTEM
// uncomment if you need to use your FileSystem Interface
// if commented, you have two defualt interface, std::filesystem or dirent
// #define USE_CUSTOM_FILESYSTEM
// this options need c++17
// #define USE_STD_FILESYSTEM
//#define MAX_FILE_DIALOG_NAME_BUFFER 1024
//#define MAX_PATH_BUFFER_SIZE 1024

View file

@ -1,7 +1,7 @@
[![Win](https://github.com/aiekick/ImGuiFileDialog/actions/workflows/Win.yml/badge.svg?branch=DemoApp)](https://github.com/aiekick/ImGuiFileDialog/actions/workflows/Win.yml)
[![Linux](https://github.com/aiekick/ImGuiFileDialog/actions/workflows/Linux.yml/badge.svg?branch=DemoApp)](https://github.com/aiekick/ImGuiFileDialog/actions/workflows/Linux.yml)
[![Osx](https://github.com/aiekick/ImGuiFileDialog/actions/workflows/Osx.yml/badge.svg?branch=DemoApp)](https://github.com/aiekick/ImGuiFileDialog/actions/workflows/Osx.yml)
[![Wrapped Dear ImGui Version](https://img.shields.io/badge/Dear%20ImGui%20Version-1.89.9-blue.svg)](https://github.com/ocornut/imgui)
[![Wrapped Dear ImGui Version](https://img.shields.io/badge/Dear%20ImGui%20Version-1.90.1-blue.svg)](https://github.com/ocornut/imgui)
# ImGuiFileDialog
@ -14,7 +14,7 @@ solutions.
## ImGui Supported Version
ImGuiFileDialog follow the master and docking branch of ImGui . currently ImGui 1.89.9
ImGuiFileDialog follow the master and docking branch of ImGui. Currently ImGui 1.90.1
## Structure
@ -67,7 +67,7 @@ Android Requirements : Api 21 mini
- 0 => Infinite
- 1 => One file (default)
- n => n files
- Compatible with MacOs, Linux, Windows
- Compatible with MacOs, Linux, Windows, Emscripten
- Windows version can list drives
- Supports modal or standard dialog types
- Select files or directories
@ -86,6 +86,9 @@ Android Requirements : Api 21 mini
- multi layer extentions like : .a.b.c .json.cpp .vcxproj.filters etc..
- advanced behavior regarding asterisk based filter. like : .* .*.* .vcx.* .*.filters .vcs*.filt.* etc.. (internally regex is used)
- result modes GetFilePathName, GetFileName and GetSelection (overwrite file ext, keep file, add ext if no user ext exist)
- you can use your own FileSystem Api
- by default Api Dirent and std::filesystem are defined
- you can override GetDrieveList for specify by ex on android other fs, like local and SDCards
### WARNINGS :
- the nav system keyboard behavior is not working as expected, so maybe full of bug for ImGuiFileDialog
@ -938,9 +941,28 @@ to note :
</blockquote></details>
<details open><summary><h2>Api's C/C++ :</h2></summary><blockquote>
<details open><summary><h2>Custom FileSystem</h2></summary><blockquote>
### the C Api
you can use your custom file system interface.
by default IGFD come with the File System Interfaces for Dirent or std::filesystem
but you have now a FileSystem interface called IFileSystem who can be overrided with your needs
by ex for android, emscripten, or boost
2 steps :
1) create a include file who must contain :
- your override of IGFD::IFileSystem
- a define of your class name in FILE_SYSTEM_OVERRIDE (ex : #define FILE_SYSTEM_OVERRIDE FileSystemBoost)
2) define your file system include file path in the preprocessor var "CUSTOM_FILESYSTEM_INCLUDE"
ex : #define CUSTOM_FILESYSTEM_INCLUDE "src/FileSystemBoost.hpp"
you can check the DemoApp who is using an override for the Boost::filesystem
</blockquote></details>
<details open><summary><h2>C Api :</h2></summary><blockquote>
this api was sucessfully tested with CImGui

View file

@ -0,0 +1,37 @@
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,165 @@
<!--- THIS FILE IS AUTOMATICALLY GENERATED, DO NOT CHANGE IT BY HAND --->
stb
===
single-file public domain (or MIT licensed) libraries for C/C++
Noteworthy:
* image loader: [stb_image.h](stb_image.h)
* image writer: [stb_image_write.h](stb_image_write.h)
* image resizer: [stb_image_resize.h](stb_image_resize.h)
* font text rasterizer: [stb_truetype.h](stb_truetype.h)
* typesafe containers: [stb_ds.h](stb_ds.h)
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize
by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts.
<a name="stb_libs"></a>
library | lastest version | category | LoC | description
--------------------- | ---- | -------- | --- | --------------------------------
**[stb_vorbis.c](stb_vorbis.c)** | 1.20 | audio | 5563 | decode ogg vorbis files from file/memory to float/16-bit signed output
**[stb_image.h](stb_image.h)** | 2.26 | graphics | 7762 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
**[stb_truetype.h](stb_truetype.h)** | 1.24 | graphics | 5011 | parse, decode, and rasterize characters from truetype fonts
**[stb_image_write.h](stb_image_write.h)** | 1.15 | graphics | 1690 | image writing to disk: PNG, TGA, BMP
**[stb_image_resize.h](stb_image_resize.h)** | 0.96 | graphics | 2631 | resize images larger/smaller with good quality
**[stb_rect_pack.h](stb_rect_pack.h)** | 1.00 | graphics | 628 | simple 2D rectangle packer with decent quality
**[stb_ds.h](stb_ds.h)** | 0.65 | utility | 1880 | typesafe dynamic array and hash tables for C, will compile in C++
**[stb_sprintf.h](stb_sprintf.h)** | 1.09 | utility | 1879 | fast sprintf, snprintf for C/C++
**[stretchy_buffer.h](stretchy_buffer.h)** | 1.04 | utility | 263 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++
**[stb_textedit.h](stb_textedit.h)** | 1.13 | user&nbsp;interface | 1404 | guts of a text editor for games etc implementing them from scratch
**[stb_voxel_render.h](stb_voxel_render.h)** | 0.89 | 3D&nbsp;graphics | 3807 | Minecraft-esque voxel rendering "engine" with many more features
**[stb_dxt.h](stb_dxt.h)** | 1.10 | 3D&nbsp;graphics | 753 | Fabian "ryg" Giesen's real-time DXT compressor
**[stb_perlin.h](stb_perlin.h)** | 0.5 | 3D&nbsp;graphics | 428 | revised Perlin noise (3D input, 1D output)
**[stb_easy_font.h](stb_easy_font.h)** | 1.1 | 3D&nbsp;graphics | 305 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
**[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.41 | game&nbsp;dev | 4161 | embeddable tilemap editor
**[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.7 | game&nbsp;dev | 1221 | herringbone Wang tile map generator
**[stb_c_lexer.h](stb_c_lexer.h)** | 0.11 | parsing | 966 | simplify writing parsers for C-like languages
**[stb_divide.h](stb_divide.h)** | 0.93 | math | 430 | more useful 32-bit modulus e.g. "euclidean divide"
**[stb_connected_comp...](stb_connected_components.h)** | 0.96 | misc | 1049 | incrementally compute reachability on grids
**[stb.h](stb.h)** | 2.37 | misc | 14454 | helper functions for C, mostly redundant in C++; basically author's personal stuff
**[stb_leakcheck.h](stb_leakcheck.h)** | 0.6 | misc | 194 | quick-and-dirty malloc/free leak-checking
**[stb_include.h](stb_include.h)** | 0.02 | misc | 295 | implement recursive #include support, particularly for GLSL
Total libraries: 22
Total lines of C code: 56774
FAQ
---
#### What's the license?
These libraries are in the public domain. You can do anything you
want with them. You have no legal obligation
to do anything else, although I appreciate attribution.
They are also licensed under the MIT open source license, if you have lawyers
who are unhappy with public domain. Every source file includes an explicit
dual-license for you to choose from.
#### <a name="other_libs"></a> Are there other single-file public-domain/open source libraries with minimal dependencies out there?
[Yes.](https://github.com/nothings/single_file_libs)
#### If I wrap an stb library in a new library, does the new library have to be public domain/MIT?
No, because it's public domain you can freely relicense it to whatever license your new
library wants to be.
#### What's the deal with SSE support in GCC-based compilers?
stb_image will either use SSE2 (if you compile with -msse2) or
will not use any SIMD at all, rather than trying to detect the
processor at runtime and handle it correctly. As I understand it,
the approved path in GCC for runtime-detection require
you to use multiple source files, one for each CPU configuration.
Because stb_image is a header-file library that compiles in only
one source file, there's no approved way to build both an
SSE-enabled and a non-SSE-enabled variation.
While we've tried to work around it, we've had multiple issues over
the years due to specific versions of gcc breaking what we're doing,
so we've given up on it. See https://github.com/nothings/stb/issues/280
and https://github.com/nothings/stb/issues/410 for examples.
#### Some of these libraries seem redundant to existing open source libraries. Are they better somehow?
Generally they're only better in that they're easier to integrate,
easier to use, and easier to release (single file; good API; no
attribution requirement). They may be less featureful, slower,
and/or use more memory. If you're already using an equivalent
library, there's probably no good reason to switch.
#### Can I link directly to the table of stb libraries?
You can use [this URL](https://github.com/nothings/stb#stb_libs) to link directly to that list.
#### Why do you list "lines of code"? It's a terrible metric.
Just to give you some idea of the internal complexity of the library,
to help you manage your expectations, or to let you know what you're
getting into. While not all the libraries are written in the same
style, they're certainly similar styles, and so comparisons between
the libraries are probably still meaningful.
Note though that the lines do include both the implementation, the
part that corresponds to a header file, and the documentation.
#### Why single-file headers?
Windows doesn't have standard directories where libraries
live. That makes deploying libraries in Windows a lot more
painful than open source developers on Unix-derivates generally
realize. (It also makes library dependencies a lot worse in Windows.)
There's also a common problem in Windows where a library was built
against a different version of the runtime library, which causes
link conflicts and confusion. Shipping the libs as headers means
you normally just compile them straight into your project without
making libraries, thus sidestepping that problem.
Making them a single file makes it very easy to just
drop them into a project that needs them. (Of course you can
still put them in a proper shared library tree if you want.)
Why not two files, one a header and one an implementation?
The difference between 10 files and 9 files is not a big deal,
but the difference between 2 files and 1 file is a big deal.
You don't need to zip or tar the files up, you don't have to
remember to attach *two* files, etc.
#### Why "stb"? Is this something to do with Set-Top Boxes?
No, they are just the initials for my name, Sean T. Barrett.
This was not chosen out of egomania, but as a moderately sane
way of namespacing the filenames and source function names.
#### Will you add more image types to stb_image.h?
No. As stb_image use has grown, it has become more important
for us to focus on security of the codebase. Adding new image
formats increases the amount of code we need to secure, so it
is no longer worth adding new formats.
#### Do you have any advice on how to create my own single-file library?
Yes. https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
#### Why public domain?
I prefer it over GPL, LGPL, BSD, zlib, etc. for many reasons.
Some of them are listed here:
https://github.com/nothings/stb/blob/master/docs/why_public_domain.md
#### Why C?
Primarily, because I use C, not C++. But it does also make it easier
for other people to use them from other languages.
#### Why not C99? stdint.h, declare-anywhere, etc.
I still use MSVC 6 (1998) as my IDE because it has better human factors
for me than later versions of MSVC.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,135 @@
#pragma once
// uncomment and modify defines under for customize ImGuiFileDialog
// uncomment if you need to use your FileSystem Interface
// if commented, you have two defualt interface, std::filesystem or dirent
// #define USE_CUSTOM_FILESYSTEM
// this options need c++17
// #define USE_STD_FILESYSTEM
//#define MAX_FILE_DIALOG_NAME_BUFFER 1024
//#define MAX_PATH_BUFFER_SIZE 1024
// the slash's buttons in path cna be used for quick select parallles directories
//#define USE_QUICK_PATH_SELECT
// the spacing between button path's can be customized.
// if disabled the spacing is defined by the imgui theme
// define the space between path buttons
//#define CUSTOM_PATH_SPACING 2
//#define USE_THUMBNAILS
//the thumbnail generation use the stb_image and stb_resize lib who need to define the implementation
//btw if you already use them in your app, you can have compiler error due to "implemntation found in double"
//so uncomment these line for prevent the creation of implementation of these libs again
//#define DONT_DEFINE_AGAIN__STB_IMAGE_IMPLEMENTATION
//#define DONT_DEFINE_AGAIN__STB_IMAGE_RESIZE_IMPLEMENTATION
//#define IMGUI_RADIO_BUTTON RadioButton
//#define DisplayMode_ThumbailsList_ImageHeight 32.0f
//#define tableHeaderFileThumbnailsString "Thumbnails"
//#define DisplayMode_FilesList_ButtonString "FL"
//#define DisplayMode_FilesList_ButtonHelp "File List"
//#define DisplayMode_ThumbailsList_ButtonString "TL"
//#define DisplayMode_ThumbailsList_ButtonHelp "Thumbnails List"
// todo
//#define DisplayMode_ThumbailsGrid_ButtonString "TG"
//#define DisplayMode_ThumbailsGrid_ButtonHelp "Thumbnails Grid"
//#define USE_EXPLORATION_BY_KEYS
// this mapping by default is for GLFW but you can use another
//#include <GLFW/glfw3.h>
// Up key for explore to the top
//#define IGFD_KEY_UP ImGuiKey_UpArrow
// Down key for explore to the bottom
//#define IGFD_KEY_DOWN ImGuiKey_DownArrow
// Enter key for open directory
//#define IGFD_KEY_ENTER ImGuiKey_Enter
// BackSpace for comming back to the last directory
//#define IGFD_KEY_BACKSPACE ImGuiKey_Backspace
// by ex you can quit the dialog by pressing the key excape
//#define USE_DIALOG_EXIT_WITH_KEY
//#define IGFD_EXIT_KEY ImGuiKey_Escape
// widget
// begin combo widget
//#define IMGUI_BEGIN_COMBO ImGui::BeginCombo
// when auto resized, FILTER_COMBO_MIN_WIDTH will be considered has minimum width
// FILTER_COMBO_AUTO_SIZE is enabled by default now to 1
// uncomment if you want disable
//#define FILTER_COMBO_AUTO_SIZE 0
// filter combobox width
//#define FILTER_COMBO_MIN_WIDTH 120.0f
// button widget use for compose path
//#define IMGUI_PATH_BUTTON ImGui::Button
// standard button
//#define IMGUI_BUTTON ImGui::Button
// locales string
//#define createDirButtonString "+"
//#define resetButtonString "R"
//#define drivesButtonString "Drives"
//#define editPathButtonString "E"
//#define searchString "Search"
//#define dirEntryString "[DIR] "
//#define linkEntryString "[LINK] "
//#define fileEntryString "[FILE] "
//#define fileNameString "File Name : "
//#define dirNameString "Directory Path :"
//#define buttonResetSearchString "Reset search"
//#define buttonDriveString "Drives"
//#define buttonEditPathString "Edit path\nYou can also right click on path buttons"
//#define buttonResetPathString "Reset to current directory"
//#define buttonCreateDirString "Create Directory"
//#define OverWriteDialogTitleString "The file Already Exist !"
//#define OverWriteDialogMessageString "Would you like to OverWrite it ?"
//#define OverWriteDialogConfirmButtonString "Confirm"
//#define OverWriteDialogCancelButtonString "Cancel"
//Validation buttons
//#define okButtonString " OK"
//#define okButtonWidth 0.0f
//#define cancelButtonString " Cancel"
//#define cancelButtonWidth 0.0f
//alignement [0:1], 0.0 is left, 0.5 middle, 1.0 right, and other ratios
//#define okCancelButtonAlignement 0.0f
//#define invertOkAndCancelButtons 0
// DateTimeFormat
// see strftime functionin <ctime> for customize
// "%Y/%m/%d %H:%M" give 2021:01:22 11:47
// "%Y/%m/%d %i:%M%p" give 2021:01:22 11:45PM
//#define DateTimeFormat "%Y/%m/%d %i:%M%p"
// theses icons will appear in table headers
//#define USE_CUSTOM_SORTING_ICON
//#define tableHeaderAscendingIcon "A|"
//#define tableHeaderDescendingIcon "D|"
//#define tableHeaderFileNameString " File name"
//#define tableHeaderFileTypeString " Type"
//#define tableHeaderFileSizeString " Size"
//#define tableHeaderFileDateTimeString " Date"
//#define fileSizeBytes "o"
//#define fileSizeKiloBytes "Ko"
//#define fileSizeMegaBytes "Mo"
//#define fileSizeGigaBytes "Go"
// default table sort field (must be FIELD_FILENAME, FIELD_TYPE, FIELD_SIZE, FIELD_DATE or FIELD_THUMBNAILS)
//#define defaultSortField FIELD_FILENAME
// default table sort order for each field (true => Descending, false => Ascending)
//#define defaultSortOrderFilename true
//#define defaultSortOrderType true
//#define defaultSortOrderSize true
//#define defaultSortOrderDate true
//#define defaultSortOrderThumbnails true
//#define USE_BOOKMARK
//#define bookmarkPaneWith 150.0f
//#define IMGUI_TOGGLE_BUTTON ToggleButton
//#define bookmarksButtonString "Bookmark"
//#define bookmarksButtonHelpString "Bookmark"
//#define addBookmarkButtonString "+"
//#define removeBookmarkButtonString "-"

View file

@ -1,19 +1,17 @@
#include "base_node.h"
#include "uuid.h"
#include "IconsMaterialDesignIcons.h"
int BaseNode::s_nextId = 1;
BaseNode::BaseNode(const std::string &title)
BaseNode::BaseNode(const std::string &title, StoryProject &proj)
: m_project(proj)
{
m_id = UUID().String();
// m_id = UUID().String();
m_id = -1;
m_node = std::make_unique<Node>(GetNextId(), title.c_str());
// m_node->Inputs.emplace_back(GetNextId(), "", PinType::Flow);
// m_node->Inputs.emplace_back(GetNextId(), "Condition", PinType::Bool);
// m_node->Outputs.emplace_back(GetNextId(), "True", PinType::Flow);
// m_node->Outputs.emplace_back(GetNextId(), "False", PinType::Flow);
}
void BaseNode::AddInput()
@ -21,9 +19,27 @@ void BaseNode::AddInput()
m_node->Inputs.emplace_back(GetNextId(), "", PinType::Flow);
}
void BaseNode::AddOutput()
void BaseNode::AddOutputs(int num)
{
for (int i = 0; i < num; i++)
{
m_node->Outputs.emplace_back(GetNextId(), "", PinType::Flow);
}
}
void BaseNode::SetOutputs(uint32_t num)
{
if (num > Outputs())
{
AddOutputs(num - Outputs());
}
else if (num < Outputs())
{
for (unsigned int i = 0; i < (Outputs() - num); i++)
{
DeleteOutput();
}
}
}
void BaseNode::DeleteOutput()
@ -33,28 +49,20 @@ void BaseNode::DeleteOutput()
void BaseNode::SetPosition(int x, int y)
{
ed::SetNodePosition(m_node->ID, ImVec2(0, 0));
m_pos.x = x;
m_pos.y = y;
m_firstFrame = true;
}
void BaseNode::FrameStart()
{
ed::BeginNode(m_node->ID);
// ImGui::Text("Node A");
// for (auto& input : m_node->Inputs)
// {
// ed::BeginPin(input.ID, ed::PinKind::Input);
// ImGui::Text("-> In");
// ed::EndPin();
// }
// for (auto& output : m_node->Outputs)
// {
// ed::BeginPin(output.ID, ed::PinKind::Output);
// ImGui::Text("Out ->");
// ed::EndPin();
// }
if (m_firstFrame)
{
ed::SetNodePosition(m_node->ID, ImVec2(m_pos.x, m_pos.y));
}
m_firstFrame = false;
}
void BaseNode::FrameEnd()

View file

@ -6,6 +6,7 @@
#include <random>
#include <string>
#include "json.hpp"
#include "story_project.h"
#include <imgui_node_editor.h>
@ -100,7 +101,7 @@ public:
int y;
};
BaseNode(const std::string &title);
BaseNode(const std::string &title, StoryProject &proj);
virtual void Draw() = 0;
@ -114,12 +115,16 @@ public:
uint32_t Outputs() const { return m_node->Outputs.size(); }
void SetId(const std::string &id) { m_id = id; }
std::string GetId() const { return m_id; }
void SetId(const int id) { m_id = id; }
int GetId() const { return m_id; }
void seTitle(const std::string &title) { m_title = title; }
std::string getTitle() const { return m_title; }
virtual void FromJson(nlohmann::json &) {
// default implementation does nothing
}
virtual nlohmann::json ToJson() const {
nlohmann::json j;
@ -132,17 +137,51 @@ public:
return s_nextId++;
}
static void InitId() {
s_nextId = 1;
}
ed::PinId GetInputPinAt(int index)
{
ed::PinId id = -1;
if (index < static_cast<int>(m_node->Inputs.size()))
{
id = m_node->Inputs[index].ID;
}
return id;
}
ed::PinId GetOutputPinAt(int index)
{
ed::PinId id = -1;
if (index < static_cast<int>(m_node->Outputs.size()))
{
id = m_node->Outputs[index].ID;
}
return id;
}
void AddInput();
void AddOutput();
void AddOutputs(int num = 1);
void SetOutputs(uint32_t num);
void DeleteOutput();
private:
StoryProject &m_project;
std::unique_ptr<Node> m_node;
std::string m_title{"Base node"};
std::string m_type;
std::string m_id;
int m_id;
NodePosition m_pos;
bool m_firstFrame{true};
static int s_nextId;

View file

@ -3,6 +3,7 @@
#include <fstream>
CodeEditor::CodeEditor()
: WindowBase("Code editor")
{
}
@ -33,15 +34,15 @@ void CodeEditor::Initialize()
}
}
void CodeEditor::Draw(const char* title, bool* p_open)
void CodeEditor::Draw()
{
if (!IsVisible())
{
return;
}
WindowBase::BeginDraw();
auto cpos = mEditor.GetCursorPosition();
ImGui::Begin(title, p_open, ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_MenuBar);
ImGui::SetWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
if (ImGui::BeginMenuBar())
{
@ -104,5 +105,5 @@ void CodeEditor::Draw(const char* title, bool* p_open)
mEditor.GetLanguageDefinition().mName.c_str(), mFileToEdit.c_str());
mEditor.Render("TextEditor");
ImGui::End();
WindowBase::EndDraw();
}

View file

@ -8,7 +8,7 @@ class CodeEditor : public WindowBase
public:
CodeEditor();
void Draw(const char *title, bool *p_open);
virtual void Draw() override;
void Initialize();
private:

View file

@ -2,6 +2,7 @@
#include "gui.h"
EmulatorWindow::EmulatorWindow()
: WindowBase("Emulator")
{
}
@ -13,19 +14,17 @@ void EmulatorWindow::Initialize() {
}
void EmulatorWindow::Draw(const char *title, bool *p_open)
void EmulatorWindow::Draw()
{
if (!IsVisible())
{
return;
}
// if (!IsVisible())
// {
// return;
// }
ImGui::SetNextWindowSize(ImVec2(626, 744), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(title, p_open))
{
ImGui::End();
return;
}
WindowBase::BeginDraw();
ImGui::SetWindowSize(ImVec2(626, 744), ImGuiCond_FirstUseEver);
// ImGui::Image((void*)(intptr_t)my_image_texture, ImVec2(313, 367));
@ -33,5 +32,5 @@ void EmulatorWindow::Draw(const char *title, bool *p_open)
ImVec2 p = ImGui::GetCursorScreenPos();
ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), ImGui::GetColorU32(ImVec4(1.0, 1.0, 1.0, 1.0)));
ImGui::End();
WindowBase::EndDraw();
}

View file

@ -8,7 +8,7 @@ public:
EmulatorWindow();
void Initialize();
void Draw(const char* title, bool* p_open);
virtual void Draw() override;
private:

View file

@ -10,14 +10,14 @@ your use of the corresponding standard functions.
#include <stdio.h>
#include "imgui_impl_sdl3.h"
#include "imgui_impl_sdlrenderer3.h"
#include "imgui_impl_sdl2.h"
#include "imgui_impl_sdlrenderer2.h"
#include <stdio.h>
#include <SDL3/SDL.h>
#include <SDL2/SDL.h>
#if defined(IMGUI_IMPL_OPENGL_ES2)
#include <SDL3/SDL_opengles2.h>
#include <SDL2/SDL_opengles2.h>
#else
#include <SDL3/SDL_opengl.h>
#include <SDL2/SDL_opengl.h>
#endif
#include "IconsMaterialDesignIcons.h"
@ -46,7 +46,13 @@ bool LoadTextureFromFile(const char* filename, Gui::Image &img)
return false;
}
SDL_Surface* surface = SDL_CreateSurfaceFrom((void*)data, img.w, img.h, 4 * img.w, SDL_PIXELFORMAT_RGBA8888);
// SDL3
// SDL_Surface* surface = SDL_CreateSurfaceFrom((void*)data, img.w, img.h, 4 * img.w, SDL_PIXELFORMAT_RGBA8888);
// SDL2
SDL_Surface* surface = SDL_CreateRGBSurfaceFrom((void*)data, img.w, img.h, channels * 8, channels * img.w,
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
if (surface == nullptr) {
fprintf(stderr, "Failed to create SDL surface: %s\n", SDL_GetError());
@ -59,7 +65,8 @@ bool LoadTextureFromFile(const char* filename, Gui::Image &img)
fprintf(stderr, "Failed to create SDL texture: %s\n", SDL_GetError());
}
SDL_DestroySurface(surface);
// SDL_DestroySurface(surface); // SDL3
SDL_FreeSurface(surface); // SDL2
stbi_image_free(data);
return true;
@ -76,7 +83,7 @@ Gui::Gui()
bool Gui::Initialize()
{
// Setup SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD) != 0)
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
{
printf("Error: SDL_Init(): %s\n", SDL_GetError());
return -1;
@ -87,13 +94,19 @@ bool Gui::Initialize()
// Create window with SDL_Renderer graphics context
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN);
window = SDL_CreateWindow("Dear ImGui SDL3+SDL_Renderer example", 1280, 720, window_flags);
// SDL3
//window = SDL_CreateWindow("Dear ImGui SDL3+SDL_Renderer example", 1280, 720, window_flags);
// SDL2
window = SDL_CreateWindow("Story Editor", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
}
renderer = SDL_CreateRenderer(window, NULL, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
if (renderer == nullptr)
{
SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError());
@ -139,8 +152,15 @@ bool Gui::Initialize()
//ImGui::StyleColorsLight();
// Setup Platform/Renderer backends
ImGui_ImplSDL3_InitForSDLRenderer(window, renderer);
ImGui_ImplSDLRenderer3_Init(renderer);
// SDL3
// ImGui_ImplSDL3_InitForSDLRenderer(window, renderer);
// ImGui_ImplSDLRenderer3_Init(renderer);
// SDL2
ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
ImGui_ImplSDLRenderer2_Init(renderer);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
@ -169,11 +189,22 @@ bool Gui::PollEvent()
SDL_Event event;
while (SDL_PollEvent(&event))
{
// SDL3
/*
ImGui_ImplSDL3_ProcessEvent(&event);
if (event.type == SDL_EVENT_QUIT)
done = true;
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window))
done = true;
*/
// SLD2
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT)
done = true;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
done = true;
}
return done;
@ -182,8 +213,15 @@ bool Gui::PollEvent()
void Gui::StartFrame()
{
// Start the Dear ImGui frame
ImGui_ImplSDLRenderer3_NewFrame();
ImGui_ImplSDL3_NewFrame();
// SDL3
// ImGui_ImplSDLRenderer3_NewFrame();
// ImGui_ImplSDL3_NewFrame();
// SDL2
ImGui_ImplSDLRenderer2_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
}
@ -192,19 +230,32 @@ void Gui::EndFrame()
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Rendering
// Rendering
ImGui::Render();
//SDL_RenderSetScale(renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
SDL_SetRenderDrawColor(renderer, (Uint8)(clear_color.x * 255), (Uint8)(clear_color.y * 255), (Uint8)(clear_color.z * 255), (Uint8)(clear_color.w * 255));
SDL_RenderClear(renderer);
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData());
ImGui::Render();
//ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData()); // SDL3
ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData()); // SDL2
SDL_RenderPresent(renderer);
}
void Gui::Destroy()
{
// Cleanup
ImGui_ImplSDLRenderer3_Shutdown();
ImGui_ImplSDL3_Shutdown();
// SDL3
// ImGui_ImplSDLRenderer3_Shutdown();
// ImGui_ImplSDL3_Shutdown();
// SDL2
ImGui_ImplSDLRenderer2_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
SDL_DestroyRenderer(renderer);

View file

@ -18,11 +18,14 @@ public:
int w;
int h;
std::string name;
bool valid() const {
return (w && h);
}
Image();
};
struct Size {

View file

@ -2,6 +2,9 @@
#include <filesystem>
#include <random>
#include "platform_folders.h"
#include "uuid.h"
#ifdef USE_WINDOWS_OS
#include <winsock2.h>
#include <iphlpapi.h>
@ -17,6 +20,7 @@
MainWindow::MainWindow()
: m_resourcesWindow(m_project)
, m_nodeEditorWindow(m_project)
{
m_project.Clear();
}
@ -26,7 +30,34 @@ MainWindow::~MainWindow()
}
void MainWindow::SetupMainMenuBar()
void MainWindow::DrawStatusBar()
{
float statusWindowHeight = ImGui::GetFrameHeight() * 1.4f;
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + viewport->Size.y - statusWindowHeight));
ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, statusWindowHeight));
ImGui::SetNextWindowViewport(viewport->ID);
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoDocking;
ImGui::Begin("StatusBar", nullptr, windowFlags);
if (true)
{
float dy = ImGui::GetFontSize() * 0.15f;
ImGui::SameLine(ImGui::GetIO().DisplaySize.x - 14.f * ImGui::GetFontSize());
ImGui::SameLine();
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - dy);
ImGui::Text("FPS: %.1f", 1000.0f / ImGui::GetIO().Framerate);
}
ImGui::End();
}
void MainWindow::DrawMainMenuBar()
{
bool showAboutPopup = false;
bool showParameters = false;
@ -89,7 +120,13 @@ void MainWindow::SetupMainMenuBar()
if (showOpenProject)
{
ImGuiFileDialog::Instance()->OpenDialog("OpenProjectDlgKey", "Choose File", "project.json", ".", 1, nullptr, ImGuiFileDialogFlags_Modal);
std::string home = pf::getUserHome() + "/";
#ifdef DEBUG
home = "/home/anthony/ostproj/ba869e4b-03d6-4249-9202-85b4cec767a7/";
#endif
ImGuiFileDialog::Instance()->OpenDialog("OpenProjectDlgKey", "Choose File", ".json", home, 1, nullptr, ImGuiFileDialogFlags_Modal);
}
// Always center this window when appearing
@ -268,7 +305,6 @@ void MainWindow::OpenProjectDialog()
std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName();
std::string filePath = ImGuiFileDialog::Instance()->GetCurrentPath();
bool success = false;
m_project.Initialize(filePathName);
@ -276,38 +312,16 @@ void MainWindow::OpenProjectDialog()
if (m_project.Load(filePathName, model))
{
m_model.Load(model);
m_nodeEditorWindow.Load(model);
EnableProject();
}
else
{
qWarning() << errorMsg;
QMessageBox::critical(this, tr("Open project error"), errorMsg);
m_consoleWindow.AddMessage("Open project error");
}
m_resourceModel.EndChange();
RefreshProjectInformation();
/*
// action
std::filesystem::path p(filePathName);
std::filesystem::path p2 = m_project.AssetsPath() / p.filename().generic_string();
std::filesystem::copy(p, p2, std::filesystem::copy_options::overwrite_existing);
Resource res;
std::string ext = p.extension().string();
ext.erase(ext.begin()); // remove '.' dot sign
std::transform(ext.begin(), ext.end(), ext.begin(), ::toupper);
res.format = ext;
res.type = m_soundFile ? "sound" : "image";
res.file = p.filename().generic_string();
m_project.AppendResource(res);
*/
// RefreshProjectInformation();
}
// close
@ -317,17 +331,17 @@ void MainWindow::OpenProjectDialog()
void MainWindow::EnableProject()
{
auto proj = m_project.GetProjectFilePath();
// Add to recent if not exists
if (!m_recentProjects.contains(m_project.GetProjectFilePath().c_str()))
if (std::find(m_recentProjects.begin(), m_recentProjects.end(), proj) != m_recentProjects.end())
{
m_recentProjects.push_front(m_project.GetProjectFilePath().c_str());
m_recentProjects.push_back(proj);
// Limit to 10 recent projects
if (m_recentProjects.size() > 10) {
m_recentProjects.pop_back();
}
m_toolbar->GenerateRecentProjectsMenu(m_recentProjects);
}
/*
m_ostHmiDock->Open();
m_resourcesDock->Open();
m_scriptEditorDock->Open();
@ -338,6 +352,7 @@ void MainWindow::EnableProject()
m_toolbar->SetActionsActive(true);
m_view->setEnabled(true);
*/
}
@ -570,14 +585,19 @@ void MainWindow::Loop()
gui.StartFrame();
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());
SetupMainMenuBar();
DrawMainMenuBar();
// DrawStatusBar();
// ------------ Draw all windows
m_consoleWindow.Draw("Console", nullptr);
m_emulatorWindow.Draw();
editor.Draw();
m_resourcesWindow.Draw();
m_nodeEditorWindow.Draw();
console.Draw("Console", nullptr);
m_emulatorWindow.Draw("Emulator", nullptr);
editor.Draw("Code Editor", nullptr);
m_resourcesWindow.Draw("Resources", nullptr);
m_nodeEditorWindow.Draw("Blueprint", nullptr);
ShowOptionsWindow();
NewProjectPopup();

View file

@ -96,7 +96,7 @@ private:
Gui gui;
EmulatorWindow m_emulatorWindow;
ConsoleWindow console;
ConsoleWindow m_consoleWindow;
CodeEditor editor;
ResourcesWindow m_resourcesWindow;
@ -118,7 +118,7 @@ private:
void SaveParams();
void LoadParams();
void SetupMainMenuBar();
void DrawMainMenuBar();
void ShowOptionsWindow();
bool ShowQuitConfirm();
@ -127,6 +127,7 @@ private:
void EnableProject();
void CloseProject();
void OpenProjectDialog();
void DrawStatusBar();
};
#endif // MAINWINDOW_H

View file

@ -2,16 +2,17 @@
namespace ed = ax::NodeEditor;
#include "IconsMaterialDesignIcons.h"
#include "IconsFontAwesome5_c.h"
MediaNode::MediaNode(const std::string &title)
: BaseNode(title)
MediaNode::MediaNode(const std::string &title, StoryProject &proj)
: BaseNode(title, proj)
, m_project(proj)
{
Gui::LoadRawImage("fairy.png", m_image);
// Create defaut one input and one output
AddInput();
AddOutput();
AddOutputs(1);
}
@ -24,7 +25,8 @@ void MediaNode::Draw()
ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_SizingFixedFit;
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(10.0f, 10.0f));
if (ImGui::BeginTable("table1", 1, flags)) {
if (ImGui::BeginTable("table1", 1, flags))
{
ImGui::TableNextRow();
ImU32 bg_color = ImGui::GetColorU32(ImVec4(0.3f, 0.3f, 0.7f, 1.0f));
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, bg_color);
@ -52,12 +54,12 @@ void MediaNode::Draw()
ImGui::Text("Image");
ImGui::SameLine();
ImGui::Text("image.png");
ImGui::Text("%s", m_image.name.c_str());
ImGui::SameLine();
bool do_select = false;
if (ImGui::Button("Select")) {
if (ImGui::Button("Select...")) {
do_select = true; // Instead of saying OpenPopup() here, we set this bool, which is used later in the Deferred Pop-up Section
}
@ -68,15 +70,19 @@ void MediaNode::Draw()
ImGui::Text("Sound");
ImGui::SameLine();
ImGui::Text("sound.mp3");
ImGui::Text("%s", m_soundName.c_str());
ImGui::SameLine();
bool do_select_sound = false;
if (ImGui::Button("Select")) {
do_select_sound = true; // Instead of saying OpenPopup() here, we set this bool, which is used later in the Deferred Pop-up Section
if (ImGui::Button("Play " ICON_MDI_PLAY))
{
m_project.PlaySoundFile(m_soundPath);
}
bool do_select_sound = false;
if (ImGui::Button("Select...")) {
do_select_sound = true; // Instead of saying OpenPopup() here, we set this bool, which is used later in the Deferred Pop-up Section
}
ImGui::AlignTextToFramePadding();
ImGui::Text("Hold to repeat:");
@ -87,11 +93,11 @@ void MediaNode::Draw()
uint32_t counter = Outputs();
float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
ImGui::PushButtonRepeat(true);
std::string leftSingle = "##left" + GetId();
std::string leftSingle = "##left" + std::to_string(GetId());
if (ImGui::ArrowButton(leftSingle.c_str(), ImGuiDir_Left)) { if (counter > 1) counter--; }
ImGui::SameLine(0.0f, spacing);
std::string rightSingle = "##right" + GetId();
std::string rightSingle = "##right" + std::to_string(GetId());
if (ImGui::ArrowButton(rightSingle.c_str(), ImGuiDir_Right))
{
counter++;
@ -100,23 +106,27 @@ void MediaNode::Draw()
ImGui::SameLine();
ImGui::Text("%d", counter);
if (counter > Outputs())
{
for (int i = 0; i < (counter - Outputs()); i++)
{
AddOutput();
}
}
else if (counter < Outputs())
{
for (int i = 0; i < (Outputs() - counter); i++)
{
DeleteOutput();
}
}
SetOutputs(counter);
DrawPins();
BaseNode::FrameEnd();
}
/*
"internal-data": {
"image": "fairy.png",
"sound": "la_fee_luminelle.mp3"
},
*/
void MediaNode::FromJson(nlohmann::json &j)
{
m_image.name = j["image"].get<std::string>();
Gui::LoadRawImage(m_project.BuildFullAssetsPath(m_image.name), m_image);
m_soundName = j["sound"].get<std::string>();
m_soundPath = m_project.BuildFullAssetsPath(m_soundName);
}

View file

@ -13,11 +13,16 @@
class MediaNode : public BaseNode
{
public:
MediaNode(const std::string &title);
MediaNode(const std::string &title, StoryProject &proj);
void Draw() override;
virtual void FromJson(nlohmann::json &j) override;
private:
StoryProject &m_project;
Gui::Image m_image;
std::string m_soundName;
std::string m_soundPath;
};

View file

@ -1,15 +1,21 @@
#include "node_editor_window.h"
#include "imgui.h"
#include "imgui_internal.h"
#include <iostream>
#include <cstdint>
#include <algorithm>
#include "IconsFontAwesome5_c.h"
#include "media_node.h"
#include "gui.h"
NodeEditorWindow::NodeEditorWindow()
NodeEditorWindow::NodeEditorWindow(StoryProject &proj)
: WindowBase("Node editor")
, m_project(proj)
{
registerNode<MediaNode>("media-node");
}
NodeEditorWindow::~NodeEditorWindow()
@ -24,15 +30,6 @@ void NodeEditorWindow::Initialize()
m_context = ed::CreateEditor(&config);
ed::SetCurrentEditor(m_context);
auto n1 = std::make_shared<MediaNode>("Branch");
n1->SetPosition(0, 0);
m_nodes.push_back(n1);
auto n2 = std::make_shared<MediaNode>("Branch 2");
n2->SetPosition(100, 100);
m_nodes.push_back(n2);
}
void NodeEditorWindow::Clear()
@ -40,45 +37,123 @@ void NodeEditorWindow::Clear()
m_nodes.clear();
}
void NodeEditorWindow::Draw(const char *title, bool *p_open)
void NodeEditorWindow::LoadNode(const nlohmann::json &nodeJson)
{
static bool resetDockspace = true;
float menuHeight = 0;
if(ImGui::BeginMainMenuBar())
try
{
menuHeight = ImGui::GetWindowSize().y;
int restoredNodeId = nodeJson["id"].get<int>();
nlohmann::json internalDataJson = nodeJson["internal-data"];
std::string type = nodeJson["type"].get<std::string>();
if (ImGui::BeginMenu("Actions"))
auto n = createNode(type, "", m_project);
if (n)
{
if(ImGui::MenuItem("Quit"))
{
// mEvent.ExitGame();
n->SetId(restoredNodeId);
nlohmann::json posJson = nodeJson["position"];
n->SetOutputs(nodeJson["outPortCount"].get<int>());
n->SetPosition(posJson["x"].get<int>(), posJson["y"].get<int>());
n->FromJson(internalDataJson);
m_nodes[restoredNodeId] = n;
}
ImGui::EndMenu();
else
{
throw std::logic_error(std::string("No registered model with name ") + type);
}
}
catch (std::exception& e)
{
std::cout << "ERROR: " << e.what() << std::endl;
}
ImGui::EndMainMenuBar();
}
ed::PinId NodeEditorWindow::GetInputPin(int modelNodeId, int pinIndex)
{
ed::PinId id = -1;
for (auto & n : m_nodes)
{
if (n.first == modelNodeId)
{
id = n.second->GetInputPinAt(pinIndex);
}
}
static ImGuiWindowFlags window_flags = ImGuiWindowFlags_None;
return id;
}
ed::PinId NodeEditorWindow::GetOutputPin(int modelNodeId, int pinIndex)
{
ed::PinId id = -1;
for (auto & n : m_nodes)
{
if (n.first == modelNodeId)
{
id = n.second->GetOutputPinAt(pinIndex);
}
}
return id;
}
void NodeEditorWindow::Load(const nlohmann::json &model)
{
nlohmann::json nodesJsonArray = model["nodes"];
BaseNode::InitId();
m_nodes.clear();
m_links.clear();
for (auto& element : nodesJsonArray) {
LoadNode(element);
}
std::cout << model.dump(4) << std::endl;
nlohmann::json connectionJsonArray = model["connections"];
for (auto& connection : connectionJsonArray)
{
auto conn = std::make_shared<LinkInfo>();
// our model
conn->model = connection.get<Connection>();
if (ImGui::Begin("EditorView", NULL, window_flags))
// ImGui stuff for links
conn->Id = 100000 + BaseNode::GetNextId();
conn->InputId = GetInputPin(conn->model.inNodeId, conn->model.inPortIndex);
conn->OutputId = GetOutputPin(conn->model.outNodeId, conn->model.outPortIndex);
// Since we accepted new link, lets add one to our list of links.
m_links.push_back(conn);
}
}
void NodeEditorWindow::Draw()
{
if (WindowBase::BeginDraw())
{
ed::SetCurrentEditor(m_context);
ed::Begin("My Editor", ImVec2(0.0, 0.0f));
for (auto & n : m_nodes)
for (const auto & n : m_nodes)
{
n->Draw();
n.second->Draw();
}
for (auto& linkInfo : m_Links)
for (const auto& linkInfo : m_links)
{
ed::Link(linkInfo.Id, linkInfo.InputId, linkInfo.OutputId);
ed::Link(linkInfo->Id, linkInfo->OutputId, linkInfo->InputId);
}
// Handle creation action, returns true if editor want to create new object (node or link)
@ -105,10 +180,10 @@ void NodeEditorWindow::Draw(const char *title, bool *p_open)
if (ed::AcceptNewItem())
{
// Since we accepted new link, lets add one to our list of links.
m_Links.push_back({ ed::LinkId(m_NextLinkId++), inputPinId, outputPinId });
// m_Links.push_back({ ed::LinkId(BaseNode::GetNextId()), inputPinId, outputPinId });
// Draw new link.
ed::Link(m_Links.back().Id, m_Links.back().InputId, m_Links.back().OutputId);
// ed::Link(m_Links.back().Id, m_Links.back().InputId, m_Links.back().OutputId);
}
// You may choose to reject connection between these nodes
@ -130,15 +205,10 @@ void NodeEditorWindow::Draw(const char *title, bool *p_open)
// If you agree that link can be deleted, accept deletion.
if (ed::AcceptDeletedItem())
{
// Then remove link from your data.
for (auto& link : m_Links)
{
if (link.Id == deletedLinkId)
{
m_Links.erase(&link);
break;
}
}
m_links.erase(std::remove_if(m_links.begin(),
m_links.end(),
[deletedLinkId](std::shared_ptr<LinkInfo> inf) { return inf->Id == deletedLinkId; }));
}
// You may reject link deletion by calling:
@ -153,7 +223,7 @@ void NodeEditorWindow::Draw(const char *title, bool *p_open)
}
ImGui::End();
WindowBase::EndDraw();
}
void NodeEditorWindow::ToolbarUI()

View file

@ -9,6 +9,8 @@
#include <imgui_node_editor.h>
#include "base_node.h"
#include "window_base.h"
#include "story_project.h"
#include "json.hpp"
namespace ed = ax::NodeEditor;
@ -27,26 +29,31 @@ class NodeEditorWindow : public WindowBase
public:
struct LinkInfo
{
// Stuff from ImGuiNodeEditor
ed::LinkId Id;
ed::PinId InputId;
ed::PinId OutputId;
// Stuff from the project.json file, our model
Connection model;
};
NodeEditorWindow();
NodeEditorWindow(StoryProject &proj);
~NodeEditorWindow();
void Draw(const char *title, bool *p_open);
virtual void Draw() override;
void Initialize();
void Clear();
void Load(const nlohmann::json &model);
private:
StoryProject &m_project;
ed::EditorContext* m_context = nullptr;
std::vector<std::shared_ptr<BaseNode>> m_nodes;
ImVector<LinkInfo> m_Links; // List of live links. It is dynamic unless you want to create read-only view over nodes.
int m_NextLinkId = 100; // Counter to help generate link ids. In real application this will probably based on pointer to user data structure.
// key: Id
std::map<int, std::shared_ptr<BaseNode>> m_nodes;
std::vector<std::shared_ptr<LinkInfo>> m_links; // List of live links. It is dynamic unless you want to create read-only view over nodes.
void ToolbarUI();
@ -64,26 +71,34 @@ private:
output.Kind = PinKind::Output;
}
}
/*
void BuildNodes()
{
for (auto& node : m_Nodes)
BuildNode(&node);
template<class NodeType>
struct Factory {
static std::shared_ptr<BaseNode> create_func(const std::string &title, StoryProject &proj) {
return std::make_shared<NodeType>(title, proj);
}
};
typedef std::shared_ptr<BaseNode> (*GenericCreator)(const std::string &title, StoryProject &proj);
typedef std::map<std::string, GenericCreator> Registry;
Registry m_registry;
template<class Derived>
void registerNode(const std::string& key) {
m_registry.insert(typename Registry::value_type(key, Factory<Derived>::create_func));
}
Node* SpawnBranchNode()
{
m_Nodes.emplace_back(GetNextId(), "Branch");
m_Nodes.back().Inputs.emplace_back(GetNextId(), "", PinType::Flow);
m_Nodes.back().Inputs.emplace_back(GetNextId(), "Condition", PinType::Bool);
m_Nodes.back().Outputs.emplace_back(GetNextId(), "True", PinType::Flow);
m_Nodes.back().Outputs.emplace_back(GetNextId(), "False", PinType::Flow);
BuildNode(&m_Nodes.back());
return &m_Nodes.back();
std::shared_ptr<BaseNode> createNode(const std::string& key, const std::string &title, StoryProject &proj) {
typename Registry::const_iterator i = m_registry.find(key);
if (i == m_registry.end()) {
throw std::invalid_argument(std::string(__PRETTY_FUNCTION__) +
": key not registered");
}
else return i->second(title, proj);
}
*/
void LoadNode(const nlohmann::json &nodeJson);
ed::PinId GetInputPin(int modelNodeId, int pinIndex);
ed::PinId GetOutputPin(int modelNodeId, int pinIndex);
};

View file

@ -0,0 +1,468 @@
/*
Its is under the MIT license, to encourage reuse by cut-and-paste.
The original files are hosted here: https://github.com/sago007/PlatformFolders
Copyright (c) 2015-2016 Poul Sander
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "platform_folders.h"
#include <iostream>
#include <stdexcept>
#include <cstdio>
#include <cstdlib>
#ifndef _WIN32
#include <pwd.h>
#include <unistd.h>
/**
* Retrives the effective user's home dir.
* If the user is running as root we ignore the HOME environment. It works badly with sudo.
* Writing to $HOME as root implies security concerns that a multiplatform program cannot be assumed to handle.
* @return The home directory. HOME environment is respected for non-root users if it exists.
*/
static std::string getHome() {
std::string res;
int uid = getuid();
const char* homeEnv = std::getenv("HOME");
if ( uid != 0 && homeEnv) {
//We only acknowlegde HOME if not root.
res = homeEnv;
return res;
}
struct passwd* pw = nullptr;
struct passwd pwd;
long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (bufsize < 0) {
bufsize = 16384;
}
std::vector<char> buffer;
buffer.resize(bufsize);
int error_code = getpwuid_r(uid, &pwd, buffer.data(), buffer.size(), &pw);
if (error_code) {
throw std::runtime_error("Unable to get passwd struct.");
}
const char* tempRes = pw->pw_dir;
if (!tempRes) {
throw std::runtime_error("User has no home directory");
}
res = tempRes;
return res;
}
#endif
#ifdef _WIN32
// Make sure we don't bring in all the extra junk with windows.h
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
// stringapiset.h depends on this
#include <windows.h>
// For SUCCEEDED macro
#include <winerror.h>
// For WideCharToMultiByte
#include <stringapiset.h>
// For SHGetFolderPathW and various CSIDL "magic numbers"
#include <shlobj.h>
namespace pf {
namespace internal {
std::string win32_utf16_to_utf8(const wchar_t* wstr) {
std::string res;
// If the 6th parameter is 0 then WideCharToMultiByte returns the number of bytes needed to store the result.
int actualSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, nullptr, 0, nullptr, nullptr);
if (actualSize > 0) {
//If the converted UTF-8 string could not be in the initial buffer. Allocate one that can hold it.
std::vector<char> buffer(actualSize);
actualSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &buffer[0], static_cast<int>(buffer.size()), nullptr, nullptr);
res = buffer.data();
}
if (actualSize == 0) {
// WideCharToMultiByte return 0 for errors.
throw std::runtime_error("UTF16 to UTF8 failed with error code: " + std::to_string(GetLastError()));
}
return res;
}
} // namesapce internal
} // namespace pf
class FreeCoTaskMemory {
LPWSTR pointer = NULL;
public:
explicit FreeCoTaskMemory(LPWSTR pointer) : pointer(pointer) {};
~FreeCoTaskMemory() {
CoTaskMemFree(pointer);
}
};
static std::string GetKnownWindowsFolder(REFKNOWNFOLDERID folderId, const char* errorMsg) {
LPWSTR wszPath = NULL;
HRESULT hr;
hr = SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, NULL, &wszPath);
FreeCoTaskMemory scopeBoundMemory(wszPath);
if (!SUCCEEDED(hr)) {
throw std::runtime_error(errorMsg);
}
return pf::internal::win32_utf16_to_utf8(wszPath);
}
static std::string GetAppData() {
return GetKnownWindowsFolder(FOLDERID_RoamingAppData, "RoamingAppData could not be found");
}
static std::string GetAppDataCommon() {
return GetKnownWindowsFolder(FOLDERID_ProgramData, "ProgramData could not be found");
}
static std::string GetAppDataLocal() {
return GetKnownWindowsFolder(FOLDERID_LocalAppData, "LocalAppData could not be found");
}
#elif defined(__APPLE__)
#else
#include <map>
#include <fstream>
#include <sys/types.h>
// For strlen and strtok
#include <cstring>
#include <sstream>
//Typically Linux. For easy reading the comments will just say Linux but should work with most *nixes
static void throwOnRelative(const char* envName, const char* envValue) {
if (envValue[0] != '/') {
char buffer[200];
std::snprintf(buffer, sizeof(buffer), "Environment \"%s\" does not start with an '/'. XDG specifies that the value must be absolute. The current value is: \"%s\"", envName, envValue);
throw std::runtime_error(buffer);
}
}
static std::string getLinuxFolderDefault(const char* envName, const char* defaultRelativePath) {
std::string res;
const char* tempRes = std::getenv(envName);
if (tempRes) {
throwOnRelative(envName, tempRes);
res = tempRes;
return res;
}
res = getHome() + "/" + defaultRelativePath;
return res;
}
static void appendExtraFolders(const char* envName, const char* defaultValue, std::vector<std::string>& folders) {
const char* envValue = std::getenv(envName);
if (!envValue) {
envValue = defaultValue;
}
pf::internal::appendExtraFoldersTokenizer(envName, envValue, folders);
}
#endif
namespace pf {
#if !defined(_WIN32) && !defined(__APPLE__)
namespace internal {
void appendExtraFoldersTokenizer(const char* envName, const char* envValue, std::vector<std::string>& folders) {
std::stringstream ss(envValue);
std::string value;
while (std::getline(ss, value, ':')) {
if (value[0] == '/') {
folders.push_back(value);
}
else {
//Unless the system is wrongly configured this should never happen... But of course some systems will be incorectly configured.
//The XDG documentation indicates that the folder should be ignored but that the program should continue.
std::cerr << "Skipping path \"" << value << "\" in \"" << envName << "\" because it does not start with a \"/\"\n";
}
}
}
}
#endif
std::string getDataHome() {
#ifdef _WIN32
return GetAppData();
#elif defined(__APPLE__)
return getHome()+"/Library/Application Support";
#else
return getLinuxFolderDefault("XDG_DATA_HOME", ".local/share");
#endif
}
std::string getConfigHome() {
#ifdef _WIN32
return GetAppData();
#elif defined(__APPLE__)
return getHome()+"/Library/Application Support";
#else
return getLinuxFolderDefault("XDG_CONFIG_HOME", ".config");
#endif
}
std::string getCacheDir() {
#ifdef _WIN32
return GetAppDataLocal();
#elif defined(__APPLE__)
return getHome()+"/Library/Caches";
#else
return getLinuxFolderDefault("XDG_CACHE_HOME", ".cache");
#endif
}
std::string getUserHome()
{
#ifdef _WIN32
return std::getenv("USERPROFILE");
#else
return getHome();
#endif
}
std::string getStateDir() {
#ifdef _WIN32
return GetAppDataLocal();
#elif defined(__APPLE__)
return getHome()+"/Library/Application Support";
#else
return getLinuxFolderDefault("XDG_STATE_HOME", ".local/state");
#endif
}
void appendAdditionalDataDirectories(std::vector<std::string>& homes) {
#ifdef _WIN32
homes.push_back(GetAppDataCommon());
#elif !defined(__APPLE__)
appendExtraFolders("XDG_DATA_DIRS", "/usr/local/share/:/usr/share/", homes);
#endif
}
void appendAdditionalConfigDirectories(std::vector<std::string>& homes) {
#ifdef _WIN32
homes.push_back(GetAppDataCommon());
#elif !defined(__APPLE__)
appendExtraFolders("XDG_CONFIG_DIRS", "/etc/xdg", homes);
#endif
}
#if !defined(_WIN32) && !defined(__APPLE__)
struct PlatformFolders::PlatformFoldersData {
std::map<std::string, std::string> folders;
};
static void PlatformFoldersAddFromFile(const std::string& filename, std::map<std::string, std::string>& folders) {
std::ifstream infile(filename.c_str());
std::string line;
while (std::getline(infile, line)) {
if (line.length() == 0 || line.at(0) == '#' || line.substr(0, 4) != "XDG_" || line.find("_DIR") == std::string::npos) {
continue;
}
try {
std::size_t splitPos = line.find('=');
std::string key = line.substr(0, splitPos);
std::size_t valueStart = line.find('"', splitPos);
std::size_t valueEnd = line.find('"', valueStart+1);
std::string value = line.substr(valueStart+1, valueEnd - valueStart - 1);
folders[key] = value;
}
catch (std::exception& e) {
std::cerr << "WARNING: Failed to process \"" << line << "\" from \"" << filename << "\". Error: "<< e.what() << "\n";
continue;
}
}
}
static void PlatformFoldersFillData(std::map<std::string, std::string>& folders) {
folders["XDG_DOCUMENTS_DIR"] = "$HOME/Documents";
folders["XDG_DESKTOP_DIR"] = "$HOME/Desktop";
folders["XDG_DOWNLOAD_DIR"] = "$HOME/Downloads";
folders["XDG_MUSIC_DIR"] = "$HOME/Music";
folders["XDG_PICTURES_DIR"] = "$HOME/Pictures";
folders["XDG_PUBLICSHARE_DIR"] = "$HOME/Public";
folders["XDG_TEMPLATES_DIR"] = "$HOME/.Templates";
folders["XDG_VIDEOS_DIR"] = "$HOME/Videos";
PlatformFoldersAddFromFile( getConfigHome()+"/user-dirs.dirs", folders);
for (std::map<std::string, std::string>::iterator itr = folders.begin() ; itr != folders.end() ; ++itr ) {
std::string& value = itr->second;
if (value.compare(0, 5, "$HOME") == 0) {
value = getHome() + value.substr(5, std::string::npos);
}
}
}
#endif
PlatformFolders::PlatformFolders() {
#if !defined(_WIN32) && !defined(__APPLE__)
this->data = new PlatformFolders::PlatformFoldersData();
try {
PlatformFoldersFillData(data->folders);
}
catch (...) {
delete this->data;
throw;
}
#endif
}
PlatformFolders::~PlatformFolders() {
#if !defined(_WIN32) && !defined(__APPLE__)
delete this->data;
#endif
}
std::string PlatformFolders::getDocumentsFolder() const {
#ifdef _WIN32
return GetKnownWindowsFolder(FOLDERID_Documents, "Failed to find My Documents folder");
#elif defined(__APPLE__)
return getHome()+"/Documents";
#else
return data->folders["XDG_DOCUMENTS_DIR"];
#endif
}
std::string PlatformFolders::getDesktopFolder() const {
#ifdef _WIN32
return GetKnownWindowsFolder(FOLDERID_Desktop, "Failed to find Desktop folder");
#elif defined(__APPLE__)
return getHome()+"/Desktop";
#else
return data->folders["XDG_DESKTOP_DIR"];
#endif
}
std::string PlatformFolders::getPicturesFolder() const {
#ifdef _WIN32
return GetKnownWindowsFolder(FOLDERID_Pictures, "Failed to find My Pictures folder");
#elif defined(__APPLE__)
return getHome()+"/Pictures";
#else
return data->folders["XDG_PICTURES_DIR"];
#endif
}
std::string PlatformFolders::getPublicFolder() const {
#ifdef _WIN32
return GetKnownWindowsFolder(FOLDERID_Public, "Failed to find the Public folder");
#elif defined(__APPLE__)
return getHome()+"/Public";
#else
return data->folders["XDG_PUBLICSHARE_DIR"];
#endif
}
std::string PlatformFolders::getDownloadFolder1() const {
#ifdef _WIN32
return GetKnownWindowsFolder(FOLDERID_Downloads, "Failed to find My Downloads folder");
#elif defined(__APPLE__)
return getHome()+"/Downloads";
#else
return data->folders["XDG_DOWNLOAD_DIR"];
#endif
}
std::string PlatformFolders::getMusicFolder() const {
#ifdef _WIN32
return GetKnownWindowsFolder(FOLDERID_Music, "Failed to find My Music folder");
#elif defined(__APPLE__)
return getHome()+"/Music";
#else
return data->folders["XDG_MUSIC_DIR"];
#endif
}
std::string PlatformFolders::getVideoFolder() const {
#ifdef _WIN32
return GetKnownWindowsFolder(FOLDERID_Videos, "Failed to find My Video folder");
#elif defined(__APPLE__)
return getHome()+"/Movies";
#else
return data->folders["XDG_VIDEOS_DIR"];
#endif
}
std::string PlatformFolders::getSaveGamesFolder1() const {
#ifdef _WIN32
//A dedicated Save Games folder was not introduced until Vista. For XP and older save games are most often saved in a normal folder named "My Games".
//Data that should not be user accessible should be placed under GetDataHome() instead
return GetKnownWindowsFolder(FOLDERID_Documents, "Failed to find My Documents folder")+"\\My Games";
#elif defined(__APPLE__)
return getHome()+"/Library/Application Support";
#else
return getDataHome();
#endif
}
std::string getDesktopFolder() {
return PlatformFolders().getDesktopFolder();
}
std::string getDocumentsFolder() {
return PlatformFolders().getDocumentsFolder();
}
std::string getDownloadFolder() {
return PlatformFolders().getDownloadFolder1();
}
std::string getDownloadFolder1() {
return getDownloadFolder();
}
std::string getPicturesFolder() {
return PlatformFolders().getPicturesFolder();
}
std::string getPublicFolder() {
return PlatformFolders().getPublicFolder();
}
std::string getMusicFolder() {
return PlatformFolders().getMusicFolder();
}
std::string getVideoFolder() {
return PlatformFolders().getVideoFolder();
}
std::string getSaveGamesFolder1() {
return PlatformFolders().getSaveGamesFolder1();
}
std::string getSaveGamesFolder2() {
#ifdef _WIN32
return GetKnownWindowsFolder(FOLDERID_SavedGames, "Failed to find Saved Games folder");
#else
return PlatformFolders().getSaveGamesFolder1();
#endif
}
} //namespace pf

View file

@ -0,0 +1,290 @@
/*
Its is under the MIT license, to encourage reuse by cut-and-paste.
The original files are hosted here: https://github.com/sago007/PlatformFolders
Copyright (c) 2015 Poul Sander
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef PLATFORM_FOLDERS_H
#define PLATFORM_FOLDERS_H
#include <vector>
#include <string>
/**
* The namespace I use for common function. Nothing special about it.
*/
namespace pf {
#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace internal {
#if !defined(_WIN32) && !defined(__APPLE__)
void appendExtraFoldersTokenizer(const char* envName, const char* envValue, std::vector<std::string>& folders);
#endif
#ifdef _WIN32
std::string win32_utf16_to_utf8(const wchar_t* wstr);
#endif
}
#endif //DOXYGEN_SHOULD_SKIP_THIS
/**
* Retrives the base folder for storing data files.
* You must add the program name yourself like this:
* @code{.cpp}
* string data_home = getDataHome()+"/My Program Name/";
* @endcode
* On Windows this defaults to %APPDATA% (Roaming profile)
* On Linux this defaults to ~/.local/share but can be configured by the user
* @return The base folder for storing program data.
*/
std::string getDataHome();
std::string getUserHome();
/**
* Retrives the base folder for storing config files.
* You must add the program name yourself like this:
* @code{.cpp}
* string data_home = getConfigHome()+"/My Program Name/";
* @endcode
* On Windows this defaults to %APPDATA% (Roaming profile)
* On Linux this defaults to ~/.config but can be configured by the user
* @return The base folder for storing config data.
*/
std::string getConfigHome();
/**
* Retrives the base folder for storing cache files.
* You must add the program name yourself like this:
* @code{.cpp}
* string data_home = getCacheDir()+"/My Program Name/cache/";
* @endcode
* On Windows this defaults to %APPDATALOCAL%
* On Linux this defaults to ~/.cache but can be configured by the user
* Note that it is recommended to append "cache" after the program name to prevent conflicting with "StateDir" under Windows
* @return The base folder for storing data that do not need to be backed up and might be deleted.
*/
std::string getCacheDir();
/**
* Retrives the base folder used for state files.
* You must add the program name yourself like this:
* @code{.cpp}
* string data_home = getStateDir()+"/My Program Name/";
* @endcode
* On Windows this defaults to %APPDATALOCAL%
* On Linux this defaults to ~/.local/state but can be configured by the user
* On OS X this is the same as getDataHome()
* @return The base folder for storing data that do not need to be backed up but should not be reguarly deleted either.
*/
std::string getStateDir();
/**
* This will append extra folders that your program should be looking for data files in.
* This does not normally include the path returned by GetDataHome().
* If you want all the folders you should do something like:
* @code{.cpp}
* vector<string> folders;
* folders.push_back(getDataHome());
* appendAdditionalDataDirectories(folders);
* for (string s& : folders) {
* s+="/My Program Name/";
* }
* @endcode
* You must apply "/My Program Name/" to all the strings.
* The string at the lowest index has the highest priority.
* @param homes A vector that extra folders will be appended to.
*/
void appendAdditionalDataDirectories(std::vector<std::string>& homes);
/**
* This will append extra folders that your program should be looking for config files in.
* This does not normally include the path returned by GetConfigHome().
* If you want all the folders you should do something like:
* @code{.cpp}
* std::vector<std::string> folders;
* folders.push_back(pf::getConfigHome());
* pf::appendAdditionalConfigDirectories(folders);
* for (std::string s& : folders) {
* s+="/My Program Name/";
* }
* @endcode
* You must apply "/My Program Name/" to all the strings.
* The string at the lowest index has the highest priority.
* @param homes A vector that extra folders will be appended to.
*/
void appendAdditionalConfigDirectories(std::vector<std::string>& homes);
/**
* The folder that represents the desktop.
* Normally you should try not to use this folder.
* @return Absolute path to the user's desktop
*/
std::string getDesktopFolder();
/**
* The folder to store user documents to
* @return Absolute path to the "Documents" folder
*/
std::string getDocumentsFolder();
/**
* The folder where files are downloaded.
* @return Absolute path to the folder where files are downloaded to.
*/
std::string getDownloadFolder();
/**
* The folder where files are downloaded.
* @note This is provided for backward compatibility. Use getDownloadFolder instead.
* @return Absolute path to the folder where files are downloaded to.
*/
std::string getDownloadFolder1();
/**
* The folder for storing the user's pictures.
* @return Absolute path to the "Picture" folder
*/
std::string getPicturesFolder();
/**
* This returns the folder that can be used for sharing files with other users on the same system.
* @return Absolute path to the "Public" folder
*/
std::string getPublicFolder();
/**
* The folder where music is stored
* @return Absolute path to the music folder
*/
std::string getMusicFolder();
/**
* The folder where video is stored
* @return Absolute path to the video folder
*/
std::string getVideoFolder();
/**
* A base folder for storing saved games.
* You must add the program name to it like this:
* @code{.cpp}
* string saved_games_folder = pf::getSaveGamesFolder1()+"/My Program Name/";
* @endcode
* @note Windows: This is an XP compatible version and returns the path to "My Games" in Documents. Vista and later has an official folder.
* @note Linux: XDF does not define a folder for saved games. This will just return the same as GetDataHome()
* @return The folder base folder for storing save games.
*/
std::string getSaveGamesFolder1();
/**
* A base folder for storing saved games.
* You must add the program name to it like this:
* @code{.cpp}
* string saved_games_folder = pf::getSaveGamesFolder2()+"/My Program Name/";
* @endcode
* @note PlatformFolders provide different folders to for saved games as not all operating systems has support for Saved Games yet.
* It is recommended to pick the highest number (currently getSaveGamesFolder2) at the time your product enters production and stick with it
* @note Windows: This returns the "Saved Games" folder. This folder exist in Vista and later
* @note Linux: XDF does not define a folder for saved games. This will just return the same as GetDataHome()
* @return The folder base folder for storing save games.
*/
std::string getSaveGamesFolder2();
#ifndef DOXYGEN_SHOULD_SKIP_THIS
/**
* This class contains methods for finding the system depended special folders.
* For Windows these folders are either by convention or given by CSIDL.
* For Linux XDG convention is used.
* The Linux version has very little error checking and assumes that the config is correct
*/
class PlatformFolders {
public:
PlatformFolders();
~PlatformFolders();
/**
* The folder that represents the desktop.
* Normally you should try not to use this folder.
* @return Absolute path to the user's desktop
*/
std::string getDesktopFolder() const;
/**
* The folder to store user documents to
* @return Absolute path to the "Documents" folder
*/
std::string getDocumentsFolder() const;
/**
* The folder for storing the user's pictures.
* @return Absolute path to the "Picture" folder
*/
std::string getPicturesFolder() const;
/**
* Use pf::getPublicFolder() instead!
*/
std::string getPublicFolder() const;
/**
* The folder where files are downloaded.
* @note Windows: This version is XP compatible and returns the Desktop. Vista and later has a dedicated folder.
* @return Absolute path to the folder where files are downloaded to.
*/
std::string getDownloadFolder1() const;
/**
* The folder where music is stored
* @return Absolute path to the music folder
*/
std::string getMusicFolder() const;
/**
* The folder where video is stored
* @return Absolute path to the video folder
*/
std::string getVideoFolder() const;
/**
* The base folder for storing saved games.
* You must add the program name to it like this:
* @code{.cpp}
* PlatformFolders pf;
* string saved_games_folder = pf.getSaveGamesFolder1()+"/My Program Name/";
* @endcode
* @note Windows: This is an XP compatible version and returns the path to "My Games" in Documents. Vista and later has an official folder.
* @note Linux: XDF does not define a folder for saved games. This will just return the same as GetDataHome()
* @return The folder base folder for storing save games.
*/
std::string getSaveGamesFolder1() const;
private:
PlatformFolders(const PlatformFolders&);
PlatformFolders& operator=(const PlatformFolders&);
#if !defined(_WIN32) && !defined(__APPLE__)
struct PlatformFoldersData;
PlatformFoldersData* data;
#endif
};
#endif // skip doxygen
} //namespace pf
#endif /* PLATFORM_FOLDERS_H */

View file

@ -7,7 +7,8 @@
//static thread_pool pool;
ResourcesWindow::ResourcesWindow(StoryProject &project)
: m_project(project)
: WindowBase("Resources")
, m_project(project)
{
}
@ -62,11 +63,9 @@ void ResourcesWindow::ChooseFile()
}
void ResourcesWindow::Draw(const char *title, bool *p_open)
void ResourcesWindow::Draw()
{
(void) p_open;
ImGui::Begin(title, nullptr);
WindowBase::BeginDraw();
if (ImGui::Button("Add sound"))
@ -99,9 +98,11 @@ void ResourcesWindow::Draw(const char *title, bool *p_open)
ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Delete", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableHeadersRow();
for (auto & r : m_project)
{
ImGui::TableHeadersRow();
ImGui::TableNextColumn();
ImGui::Text("%s", r.file.c_str());
@ -121,6 +122,6 @@ void ResourcesWindow::Draw(const char *title, bool *p_open)
ImGui::EndTable();
}
ImGui::End();
WindowBase::EndDraw();
}

View file

@ -4,13 +4,14 @@
#include <map>
#include <mutex>
#include "story_project.h"
#include "window_base.h"
class ResourcesWindow
class ResourcesWindow : public WindowBase
{
public:
ResourcesWindow(StoryProject &project);
~ResourcesWindow();
void Draw(const char *title, bool *p_open);
virtual void Draw() override;
private:
StoryProject &m_project;

View file

@ -444,3 +444,24 @@ std::string StoryProject::GetWorkingDir() const
return m_working_dir.string();
}
std::string StoryProject::BuildFullAssetsPath(const std::string &fileName) const
{
return (AssetsPath() / fileName).generic_string();
}
void to_json(nlohmann::json &j, const Connection &p) {
j = nlohmann::json{
{"outNodeId", static_cast<int64_t>(p.outNodeId)},
{"outPortIndex", static_cast<int64_t>(p.outPortIndex)},
{"inNodeId", static_cast<int64_t>(p.inNodeId)},
{"inPortIndex", static_cast<int64_t>(p.inPortIndex)},
};
}
void from_json(const nlohmann::json &j, Connection &p) {
j.at("outNodeId").get_to(p.outNodeId);
j.at("outPortIndex").get_to(p.outPortIndex);
j.at("inNodeId").get_to(p.inNodeId);
j.at("inPortIndex").get_to(p.inPortIndex);
}

View file

@ -48,53 +48,34 @@ struct AudioCommand {
};
// Encaasulate the genaeration of a Version 4 UUID object
// A Version 4 UUID is a universally unique identifier that is generated using random numbers.
class UUID
struct Connection
{
public:
UUID() { New(); }
// Factory method for creating UUID object.
void New()
{
std::random_device rd;
std::mt19937 engine{rd()};
std::uniform_int_distribution<int> dist{0, 256}; //Limits of the interval
for (int index = 0; index < 16; ++index)
{
_data[index] = (unsigned char)dist(engine);
}
_data[6] = ((_data[6] & 0x0f) | 0x40); // Version 4
_data[8] = ((_data[8] & 0x3f) | 0x80); // Variant is 10
}
// Returns UUID as formatted string
std::string String()
{
// Formats to "0065e7d7-418c-4da4-b4d6-b54b6cf7466a"
char buffer[256] = {0};
std::snprintf(buffer, 255,
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
_data[0], _data[1], _data[2], _data[3],
_data[4], _data[5],
_data[6], _data[7],
_data[8], _data[9],
_data[10], _data[11], _data[12], _data[13], _data[14], _data[15]);
std::string uuid = buffer;
return uuid;
}
unsigned char _data[16] = {0};
int outNodeId;
int outPortIndex;
int inNodeId;
int inPortIndex;
};
inline bool operator==(Connection const &a, Connection const &b)
{
return a.outNodeId == b.outNodeId && a.outPortIndex == b.outPortIndex
&& a.inNodeId == b.inNodeId && a.inPortIndex == b.inPortIndex;
}
inline bool operator!=(Connection const &a, Connection const &b)
{
return !(a == b);
}
inline void invertConnection(Connection &id)
{
std::swap(id.outNodeId, id.inNodeId);
std::swap(id.outPortIndex, id.inPortIndex);
}
void to_json(nlohmann::json& j, const Connection& p);
void from_json(const nlohmann::json& j, Connection& p);
// FIXME : Structure très Lunii style, à utiliser pour la conversion peut-être ...
@ -173,6 +154,8 @@ struct StoryProject
std::string GetName() const { return m_name; }
std::string GetUuid() const { return m_uuid; }
std::string BuildFullAssetsPath(const std::string &fileName) const;
std::filesystem::path AssetsPath() const { return m_assetsPath; }
static std::string GetFileExtension(const std::string &FileName);

View file

@ -0,0 +1,54 @@
#ifndef UUID_H
#define UUID_H
#include <string>
#include <random>
// Encaasulate the genaeration of a Version 4 UUID object
// A Version 4 UUID is a universally unique identifier that is generated using random numbers.
class UUID
{
public:
UUID() { New(); }
// Factory method for creating UUID object.
void New()
{
std::random_device rd;
std::mt19937 engine{rd()};
std::uniform_int_distribution<int> dist{0, 256}; //Limits of the interval
for (int index = 0; index < 16; ++index)
{
_data[index] = (unsigned char)dist(engine);
}
_data[6] = ((_data[6] & 0x0f) | 0x40); // Version 4
_data[8] = ((_data[8] & 0x3f) | 0x80); // Variant is 10
}
// Returns UUID as formatted string
std::string String()
{
// Formats to "0065e7d7-418c-4da4-b4d6-b54b6cf7466a"
char buffer[256] = {0};
std::snprintf(buffer, 255,
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
_data[0], _data[1], _data[2], _data[3],
_data[4], _data[5],
_data[6], _data[7],
_data[8], _data[9],
_data[10], _data[11], _data[12], _data[13], _data[14], _data[15]);
std::string uuid = buffer;
return uuid;
}
unsigned char _data[16] = {0};
};
#endif // UUID_H

View file

@ -0,0 +1,31 @@
#include "window_base.h"
#include "imgui.h"
WindowBase::WindowBase(const std::string &title)
: m_title(title)
{
}
bool WindowBase::BeginDraw()
{
bool ok = ImGui::Begin(m_title.c_str(), nullptr);
if (m_disabled)
{
ImGui::BeginDisabled();
}
return ok;
}
void WindowBase::EndDraw()
{
ImGui::End();
if (m_disabled)
{
ImGui::EndDisabled();
}
}

View file

@ -1,25 +1,26 @@
#ifndef WINDOW_BASE_H
#define WINDOW_BASE_H
#ifndef WINDOWBASE_H
#define WINDOWBASE_H
#include <string>
class WindowBase
{
public:
WindowBase(bool display = false)
{
mDisplay = display;
WindowBase(const std::string &title);
bool IsDisabled() const {
return m_disabled;
}
void SetVisible(bool enable)
{
mDisplay = enable;
}
virtual void Draw() = 0;
bool BeginDraw();
void EndDraw();
bool IsVisible() const {
return mDisplay;
}
private:
bool mDisplay;
bool m_disabled{false};
std::string m_title;
};
#endif // WINDOW_BASE_H
#endif // WINDOWBASE_H