mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
Add Dockerfile + add cross build for WIn32 + Add create node
This commit is contained in:
parent
5710356308
commit
a25112d170
14 changed files with 663 additions and 335 deletions
28
.vscode/launch.json
vendored
Normal file
28
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
// Utilisez IntelliSense pour en savoir plus sur les attributs possibles.
|
||||||
|
// Pointez pour afficher la description des attributs existants.
|
||||||
|
// Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Debug Story Editor (GDB)",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/story-editor/build/story-editor", // Remplacez par le chemin de votre exécutable
|
||||||
|
"args": [],
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"cwd": "${workspaceFolder}/story-editor",
|
||||||
|
"environment": [],
|
||||||
|
"externalConsole": false,
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"description": "Enable pretty-printing for gdb",
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
9
.vscode/settings.json
vendored
Normal file
9
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
|
||||||
|
"cmake.sourceDirectory": [
|
||||||
|
"${workspaceFolder}/story-editor",
|
||||||
|
"${workspaceFolder}/story-player",
|
||||||
|
"${workspaceFolder}/software"
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
BIN
hardware/kicad/libs/47219-2001.zip
Normal file
BIN
hardware/kicad/libs/47219-2001.zip
Normal file
Binary file not shown.
BIN
hardware/kicad/libs/472192001_sd.pdf
Normal file
BIN
hardware/kicad/libs/472192001_sd.pdf
Normal file
Binary file not shown.
|
|
@ -9,19 +9,22 @@ set (CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
# Version du projet
|
||||||
|
set(PROJECT_VERSION_MAJOR 1)
|
||||||
|
set(PROJECT_VERSION_MINOR 0)
|
||||||
|
set(PROJECT_VERSION_PATCH 0)
|
||||||
|
|
||||||
# set(CMAKE_VERBOSE_MAKEFILE on)
|
# set(CMAKE_VERBOSE_MAKEFILE on)
|
||||||
|
|
||||||
|
|
||||||
if(POLICY CMP0072)
|
if(POLICY CMP0072)
|
||||||
cmake_policy(SET CMP0072 NEW)
|
cmake_policy(SET CMP0072 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
|
|
||||||
set(IMGUI_VERSION 1.90)
|
set(IMGUI_VERSION 1.90)
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
|
|
||||||
# =========================================================================================================================
|
# =========================================================================================================================
|
||||||
# IMGUI and plugins
|
# IMGUI and plugins
|
||||||
# =========================================================================================================================
|
# =========================================================================================================================
|
||||||
|
|
@ -29,8 +32,8 @@ FetchContent_Declare(imgui
|
||||||
URL https://github.com/ocornut/imgui/archive/refs/tags/v${IMGUI_VERSION}-docking.zip
|
URL https://github.com/ocornut/imgui/archive/refs/tags/v${IMGUI_VERSION}-docking.zip
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
FetchContent_GetProperties(imgui)
|
FetchContent_GetProperties(imgui)
|
||||||
|
|
||||||
if(NOT imgui_POPULATED)
|
if(NOT imgui_POPULATED)
|
||||||
set(FETCHCONTENT_QUIET NO)
|
set(FETCHCONTENT_QUIET NO)
|
||||||
FetchContent_Populate(imgui)
|
FetchContent_Populate(imgui)
|
||||||
|
|
@ -42,11 +45,9 @@ add_compile_definitions(CUSTOM_IMGUIFILEDIALOG_CONFIG="${CMAKE_SOURCE_DIR}/src/C
|
||||||
add_compile_definitions(IMGUI_INCLUDE="imgui.h")
|
add_compile_definitions(IMGUI_INCLUDE="imgui.h")
|
||||||
add_subdirectory(libs/ImGuiFileDialog)
|
add_subdirectory(libs/ImGuiFileDialog)
|
||||||
|
|
||||||
|
|
||||||
# =========================================================================================================================
|
# =========================================================================================================================
|
||||||
# SDL
|
# SDL
|
||||||
# =========================================================================================================================
|
# =========================================================================================================================
|
||||||
|
|
||||||
Set(FETCHCONTENT_QUIET FALSE)
|
Set(FETCHCONTENT_QUIET FALSE)
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
|
|
@ -60,10 +61,10 @@ FetchContent_Declare(
|
||||||
set(BUILD_SHARED_LIBS TRUE)
|
set(BUILD_SHARED_LIBS TRUE)
|
||||||
set(SDL_STATIC TRUE)
|
set(SDL_STATIC TRUE)
|
||||||
FetchContent_MakeAvailable(sdl2)
|
FetchContent_MakeAvailable(sdl2)
|
||||||
|
|
||||||
# add_subdirectory(libs/SDL)
|
# add_subdirectory(libs/SDL)
|
||||||
# include_directories(libs/SDL/include)
|
# include_directories(libs/SDL/include)
|
||||||
|
|
||||||
|
|
||||||
# =========================================================================================================================
|
# =========================================================================================================================
|
||||||
# SDL3-Image
|
# SDL3-Image
|
||||||
# =========================================================================================================================
|
# =========================================================================================================================
|
||||||
|
|
@ -81,8 +82,6 @@ FetchContent_MakeAvailable(sdl2)
|
||||||
# # END ADDITION
|
# # END ADDITION
|
||||||
|
|
||||||
# FetchContent_MakeAvailable(SDL2_image)
|
# FetchContent_MakeAvailable(SDL2_image)
|
||||||
|
|
||||||
|
|
||||||
set(SRCS
|
set(SRCS
|
||||||
|
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
|
|
@ -147,7 +146,6 @@ set(SRCS
|
||||||
${imgui_SOURCE_DIR}/imgui_tables.cpp
|
${imgui_SOURCE_DIR}/imgui_tables.cpp
|
||||||
${imgui_SOURCE_DIR}/imgui_draw.cpp
|
${imgui_SOURCE_DIR}/imgui_draw.cpp
|
||||||
|
|
||||||
|
|
||||||
../software/chip32/chip32_assembler.cpp
|
../software/chip32/chip32_assembler.cpp
|
||||||
../software/chip32/chip32_vm.c
|
../software/chip32/chip32_vm.c
|
||||||
../software/library/audio_player.cpp
|
../software/library/audio_player.cpp
|
||||||
|
|
@ -191,8 +189,6 @@ target_include_directories(${STORY_EDITOR_PROJECT} PUBLIC
|
||||||
../software/chip32/
|
../software/chip32/
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
add_definitions(-DIMGUI_USE_WCHAR32)
|
add_definitions(-DIMGUI_USE_WCHAR32)
|
||||||
add_link_options(-static-libgcc -static-libstdc++)
|
add_link_options(-static-libgcc -static-libstdc++)
|
||||||
|
|
||||||
|
|
@ -202,6 +198,8 @@ target_compile_definitions(${STORY_EDITOR_PROJECT} PUBLIC "$<$<CONFIG:DEBUG>:DEB
|
||||||
|
|
||||||
target_link_directories(${STORY_EDITOR_PROJECT} PUBLIC ${sdl2_BINARY_DIR})
|
target_link_directories(${STORY_EDITOR_PROJECT} PUBLIC ${sdl2_BINARY_DIR})
|
||||||
message(${sdl2_BINARY_DIR})
|
message(${sdl2_BINARY_DIR})
|
||||||
|
set(SDL2_BIN_DIR ${sdl2_BINARY_DIR})
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
target_link_libraries(${STORY_EDITOR_PROJECT}
|
target_link_libraries(${STORY_EDITOR_PROJECT}
|
||||||
pthread
|
pthread
|
||||||
|
|
@ -211,17 +209,37 @@ target_link_libraries(${STORY_EDITOR_PROJECT}
|
||||||
SDL2
|
SDL2
|
||||||
)
|
)
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
|
|
||||||
#target_compile_features("-Wl,-subsystem,windows")
|
|
||||||
|
|
||||||
target_link_libraries(${STORY_EDITOR_PROJECT}
|
target_link_libraries(${STORY_EDITOR_PROJECT}
|
||||||
OpenGL::GL
|
OpenGL::GL
|
||||||
# SDL2::SDL2main
|
|
||||||
SDL2
|
SDL2
|
||||||
ws2_32.lib psapi.lib setupapi.lib cfgmgr32.lib advapi32.lib Dbghelp.lib
|
ws2_32.lib psapi.lib setupapi.lib cfgmgr32.lib advapi32.lib
|
||||||
)
|
)
|
||||||
#set_target_properties(${STORY_EDITOR_PROJECT} PROPERTIES
|
|
||||||
#LINK_FLAGS /SUBSYSTEM:CONSOLE
|
|
||||||
#)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# =========================================================================================================================
|
||||||
|
# CPACK INSTALLER
|
||||||
|
# =========================================================================================================================
|
||||||
|
install(TARGETS ${STORY_EDITOR_PROJECT} RUNTIME DESTINATION ".")
|
||||||
|
|
||||||
|
# Personnaliser les options d'installation
|
||||||
|
set(CPACK_PACKAGE_NAME "Open-Story-Editor")
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION "Open Story Teller - Node based editor")
|
||||||
|
set(CPACK_PACKAGE_VENDOR "D8S")
|
||||||
|
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
|
||||||
|
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
|
||||||
|
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
|
||||||
|
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
|
||||||
|
|
||||||
|
# install(DIRECTORY "${PROJECT_SOURCE_DIR}/assets/" DESTINATION "assets")
|
||||||
|
install(DIRECTORY "${PROJECT_SOURCE_DIR}/fonts/" DESTINATION "fonts")
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
install_files("." FILES "${SDL2_BIN_DIR}/SDL2.dll")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Personnaliser l'icône pour les installateurs Windows
|
||||||
|
if(WIN32)
|
||||||
|
set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/story-editor-logo.ico")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(CPack)
|
||||||
|
|
|
||||||
16
story-editor/Dockerfile
Normal file
16
story-editor/Dockerfile
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
FROM ubuntu:22.04
|
||||||
|
LABEL Description="Build environment"
|
||||||
|
|
||||||
|
ENV HOME /root
|
||||||
|
|
||||||
|
SHELL ["/bin/bash", "-c"]
|
||||||
|
|
||||||
|
RUN mkdir /workspace
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get -y --no-install-recommends install \
|
||||||
|
build-essential \
|
||||||
|
cmake \
|
||||||
|
nsis \
|
||||||
|
mingw-w64 \
|
||||||
|
git \
|
||||||
|
wget
|
||||||
21
story-editor/LICENSE
Normal file
21
story-editor/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Anthony Rabine
|
||||||
|
|
||||||
|
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.
|
||||||
65
story-editor/README.md
Normal file
65
story-editor/README.md
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Story Editor
|
||||||
|
|
||||||
|
## How to generate a Windows executable and setup executable on Ubuntu
|
||||||
|
|
||||||
|
All the commands listed here are invoked from this `story-editor` root directory.
|
||||||
|
Make sure to have Docker installed:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt install docker.io
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the Docker image that contains all the necessary development tools:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build -t cpp-dev .
|
||||||
|
```
|
||||||
|
|
||||||
|
Run it:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run -it -v $(pwd)/..:/workspace cpp-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Make sure to use the POSIX version of MinGW:
|
||||||
|
|
||||||
|
```
|
||||||
|
update-alternatives --config x86_64-w64-mingw32-g++
|
||||||
|
|
||||||
|
|
||||||
|
Selection Path Priority Status
|
||||||
|
------------------------------------------------------------
|
||||||
|
0 /usr/bin/x86_64-w64-mingw32-g++-win32 60 auto mode
|
||||||
|
* 1 /usr/bin/x86_64-w64-mingw32-g++-posix 30 manual mode
|
||||||
|
2 /usr/bin/x86_64-w64-mingw32-g++-win32 60 manual mode
|
||||||
|
|
||||||
|
|
||||||
|
update-alternatives --config x86_64-w64-mingw32-gcc
|
||||||
|
|
||||||
|
Selection Path Priority Status
|
||||||
|
------------------------------------------------------------
|
||||||
|
0 /usr/bin/x86_64-w64-mingw32-gcc-win32 60 auto mode
|
||||||
|
* 1 /usr/bin/x86_64-w64-mingw32-gcc-posix 30 manual mode
|
||||||
|
2 /usr/bin/x86_64-w64-mingw32-gcc-win32 60 manual mode
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Cross build, first generate the Makefile:
|
||||||
|
|
||||||
|
```
|
||||||
|
git config --global http.sslverify false # avoid error during clone
|
||||||
|
cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/mingw-w64-x86_64.cmake ..
|
||||||
|
```
|
||||||
|
|
||||||
|
Then build the executable and then the installer:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
make -j4
|
||||||
|
make package
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
25
story-editor/cmake/mingw-w64-x86_64.cmake
Normal file
25
story-editor/cmake/mingw-w64-x86_64.cmake
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Sample toolchain file for building for Windows from an Ubuntu Linux system.
|
||||||
|
#
|
||||||
|
# Typical usage:
|
||||||
|
# *) install cross compiler: `sudo apt-get install mingw-w64`
|
||||||
|
# *) cd build
|
||||||
|
# *) cmake -DCMAKE_TOOLCHAIN_FILE=~/mingw-w64-x86_64.cmake ..
|
||||||
|
# This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
set(CMAKE_SYSTEM_NAME Windows)
|
||||||
|
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
|
||||||
|
|
||||||
|
# cross compilers to use for C, C++ and Fortran
|
||||||
|
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
|
||||||
|
set(CMAKE_Fortran_COMPILER ${TOOLCHAIN_PREFIX}-gfortran)
|
||||||
|
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
|
||||||
|
|
||||||
|
# target environment on the build host system
|
||||||
|
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
|
||||||
|
|
||||||
|
# modify default behavior of FIND_XXX() commands
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#ifndef CONSOLEWINDOW_H
|
#pragma once
|
||||||
#define CONSOLEWINDOW_H
|
|
||||||
|
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -8,7 +7,6 @@
|
||||||
|
|
||||||
#include "window_base.h"
|
#include "window_base.h"
|
||||||
|
|
||||||
|
|
||||||
// Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
|
// Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
|
||||||
// For the console example, we are using a more C++ like approach of declaring a class to hold both data and functions.
|
// For the console example, we are using a more C++ like approach of declaring a class to hold both data and functions.
|
||||||
struct ConsoleWindow : public WindowBase
|
struct ConsoleWindow : public WindowBase
|
||||||
|
|
@ -18,17 +16,48 @@ public:
|
||||||
~ConsoleWindow();
|
~ConsoleWindow();
|
||||||
|
|
||||||
// Portable helpers
|
// Portable helpers
|
||||||
static int Stricmp(const char* s1, const char* s2) { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; }
|
static int Stricmp(const char *s1, const char *s2)
|
||||||
static int Strnicmp(const char* s1, const char* s2, int n) { int d = 0; while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; n--; } return d; }
|
{
|
||||||
static char* Strdup(const char* s) { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); }
|
int d;
|
||||||
static void Strtrim(char* s) { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; }
|
while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1)
|
||||||
|
{
|
||||||
|
s1++;
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
static int Strnicmp(const char *s1, const char *s2, int n)
|
||||||
|
{
|
||||||
|
int d = 0;
|
||||||
|
while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1)
|
||||||
|
{
|
||||||
|
s1++;
|
||||||
|
s2++;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
static char *Strdup(const char *s)
|
||||||
|
{
|
||||||
|
IM_ASSERT(s);
|
||||||
|
size_t len = strlen(s) + 1;
|
||||||
|
void *buf = malloc(len);
|
||||||
|
IM_ASSERT(buf);
|
||||||
|
return (char *)memcpy(buf, (const void *)s, len);
|
||||||
|
}
|
||||||
|
static void Strtrim(char *s)
|
||||||
|
{
|
||||||
|
char *str_end = s + strlen(s);
|
||||||
|
while (str_end > s && str_end[-1] == ' ')
|
||||||
|
str_end--;
|
||||||
|
*str_end = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ClearLog();
|
void ClearLog();
|
||||||
|
|
||||||
void AddLog(const std::string &text, uint32_t type)
|
void AddLog(const std::string &text, uint32_t type)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
// FIXME-OPT
|
// FIXME-OPT
|
||||||
Entry e{text, type};
|
Entry e{text, type};
|
||||||
std::scoped_lock<std::mutex> mutex(mLogMutex);
|
std::scoped_lock<std::mutex> mutex(mLogMutex);
|
||||||
|
|
@ -41,10 +70,9 @@ public:
|
||||||
|
|
||||||
virtual void Draw() override;
|
virtual void Draw() override;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Entry
|
||||||
struct Entry {
|
{
|
||||||
std::string text;
|
std::string text;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
};
|
};
|
||||||
|
|
@ -56,7 +84,4 @@ private:
|
||||||
ImGuiTextFilter Filter;
|
ImGuiTextFilter Filter;
|
||||||
bool AutoScroll;
|
bool AutoScroll;
|
||||||
bool ScrollToBottom;
|
bool ScrollToBottom;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONSOLEWINDOW_H
|
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,7 @@ void MainWindow::DrawMainMenuBar()
|
||||||
std::string home = pf::getUserHome() + "/";
|
std::string home = pf::getUserHome() + "/";
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
home = "/home/anthony/ostproj/ba869e4b-03d6-4249-9202-85b4cec767a7/";
|
home = "/mnt/work/git/open-stories/ba869e4b-03d6-4249-9202-85b4cec767a7/";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ImGuiFileDialog::Instance()->OpenDialog("OpenProjectDlgKey", "Choose File", ".json", home, 1, nullptr, ImGuiFileDialogFlags_Modal);
|
ImGuiFileDialog::Instance()->OpenDialog("OpenProjectDlgKey", "Choose File", ".json", home, 1, nullptr, ImGuiFileDialogFlags_Modal);
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,13 @@
|
||||||
#include "media_node.h"
|
#include "media_node.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
|
||||||
|
#include <stdexcept> // for std::runtime_error
|
||||||
|
#define JSON_ASSERT(x) \
|
||||||
|
if (!(x)) { \
|
||||||
|
throw std::runtime_error("Assertion failed: " #x); \
|
||||||
|
}
|
||||||
|
#include "json.hpp"
|
||||||
|
|
||||||
|
|
||||||
NodeEditorWindow::NodeEditorWindow(IStoryManager &proj)
|
NodeEditorWindow::NodeEditorWindow(IStoryManager &proj)
|
||||||
: WindowBase("Node editor")
|
: WindowBase("Node editor")
|
||||||
|
|
@ -35,6 +42,7 @@ void NodeEditorWindow::Initialize()
|
||||||
void NodeEditorWindow::Clear()
|
void NodeEditorWindow::Clear()
|
||||||
{
|
{
|
||||||
m_nodes.clear();
|
m_nodes.clear();
|
||||||
|
m_ids.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -57,6 +65,8 @@ void NodeEditorWindow::LoadNode(const nlohmann::json &nodeJson)
|
||||||
n->SetPosition(posJson["x"].get<float>(), posJson["y"].get<float>());
|
n->SetPosition(posJson["x"].get<float>(), posJson["y"].get<float>());
|
||||||
n->FromJson(internalDataJson);
|
n->FromJson(internalDataJson);
|
||||||
|
|
||||||
|
m_ids.insert(restoredNodeId);
|
||||||
|
|
||||||
m_nodes.push_back(n);
|
m_nodes.push_back(n);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -71,6 +81,18 @@ void NodeEditorWindow::LoadNode(const nlohmann::json &nodeJson)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int NodeEditorWindow::GenerateNodeId()
|
||||||
|
{
|
||||||
|
int max = 1;
|
||||||
|
if (m_ids.size() > 0)
|
||||||
|
{
|
||||||
|
auto max = *m_ids.rbegin();
|
||||||
|
max++;
|
||||||
|
m_ids.insert(max);
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ed::PinId NodeEditorWindow::GetInputPin(unsigned long modelNodeId, int pinIndex)
|
ed::PinId NodeEditorWindow::GetInputPin(unsigned long modelNodeId, int pinIndex)
|
||||||
{
|
{
|
||||||
|
|
@ -409,6 +431,41 @@ void NodeEditorWindow::Draw()
|
||||||
ed::EndDelete(); // Wrap up deletion action
|
ed::EndDelete(); // Wrap up deletion action
|
||||||
|
|
||||||
|
|
||||||
|
auto openPopupPosition = ImGui::GetMousePos();
|
||||||
|
ed::Suspend();
|
||||||
|
|
||||||
|
if (ed::ShowBackgroundContextMenu())
|
||||||
|
{
|
||||||
|
ImGui::OpenPopup("Create New Node");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginPopup("Create New Node"))
|
||||||
|
{
|
||||||
|
auto newNodePostion = openPopupPosition;
|
||||||
|
Node* node = nullptr;
|
||||||
|
if (ImGui::MenuItem("Media Node"))
|
||||||
|
{
|
||||||
|
auto n = createNode("media-node", "", m_story);
|
||||||
|
if (n)
|
||||||
|
{
|
||||||
|
n->SetType("media-node"); // FIXME: set type in createNode factory?
|
||||||
|
n->SetId(GenerateNodeId());
|
||||||
|
n->SetPosition(newNodePostion.x, newNodePostion.y);
|
||||||
|
m_nodes.push_back(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (node)
|
||||||
|
// {
|
||||||
|
// ed::SetNodePosition(node->ID, newNodePostion);
|
||||||
|
// }
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
ed::Resume();
|
||||||
|
|
||||||
|
|
||||||
ed::End();
|
ed::End();
|
||||||
ed::SetCurrentEditor(nullptr);
|
ed::SetCurrentEditor(nullptr);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include <imgui_node_editor.h>
|
#include <imgui_node_editor.h>
|
||||||
#include "base_node.h"
|
#include "base_node.h"
|
||||||
#include "window_base.h"
|
#include "window_base.h"
|
||||||
#include "i_story_manager.h"
|
#include "i_story_manager.h"
|
||||||
#include "story_project.h"
|
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace ed = ax::NodeEditor;
|
namespace ed = ax::NodeEditor;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -72,6 +70,7 @@ private:
|
||||||
std::list<std::shared_ptr<LinkInfo>> m_links; // List of live links. It is dynamic unless you want to create read-only view over nodes.
|
std::list<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();
|
void ToolbarUI();
|
||||||
|
|
||||||
|
std::set<int> m_ids;
|
||||||
|
|
||||||
void BuildNode(Node* node)
|
void BuildNode(Node* node)
|
||||||
{
|
{
|
||||||
|
|
@ -117,5 +116,6 @@ private:
|
||||||
ed::PinId GetInputPin(unsigned long modelNodeId, int pinIndex);
|
ed::PinId GetInputPin(unsigned long modelNodeId, int pinIndex);
|
||||||
ed::PinId GetOutputPin(unsigned long modelNodeId, int pinIndex);
|
ed::PinId GetOutputPin(unsigned long modelNodeId, int pinIndex);
|
||||||
uint32_t FindFirstNode() const;
|
uint32_t FindFirstNode() const;
|
||||||
|
int GenerateNodeId();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,13 @@ SOFTWARE.
|
||||||
* Writing to $HOME as root implies security concerns that a multiplatform program cannot be assumed to handle.
|
* 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.
|
* @return The home directory. HOME environment is respected for non-root users if it exists.
|
||||||
*/
|
*/
|
||||||
static std::string getHome() {
|
static std::string getHome()
|
||||||
|
{
|
||||||
std::string res;
|
std::string res;
|
||||||
int uid = getuid();
|
int uid = getuid();
|
||||||
const char *homeEnv = std::getenv("HOME");
|
const char *homeEnv = std::getenv("HOME");
|
||||||
if ( uid != 0 && homeEnv) {
|
if (uid != 0 && homeEnv)
|
||||||
|
{
|
||||||
// We only acknowlegde HOME if not root.
|
// We only acknowlegde HOME if not root.
|
||||||
res = homeEnv;
|
res = homeEnv;
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -55,17 +57,20 @@ static std::string getHome() {
|
||||||
struct passwd *pw = nullptr;
|
struct passwd *pw = nullptr;
|
||||||
struct passwd pwd;
|
struct passwd pwd;
|
||||||
long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
|
long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||||
if (bufsize < 0) {
|
if (bufsize < 0)
|
||||||
|
{
|
||||||
bufsize = 16384;
|
bufsize = 16384;
|
||||||
}
|
}
|
||||||
std::vector<char> buffer;
|
std::vector<char> buffer;
|
||||||
buffer.resize(bufsize);
|
buffer.resize(bufsize);
|
||||||
int error_code = getpwuid_r(uid, &pwd, buffer.data(), buffer.size(), &pw);
|
int error_code = getpwuid_r(uid, &pwd, buffer.data(), buffer.size(), &pw);
|
||||||
if (error_code) {
|
if (error_code)
|
||||||
|
{
|
||||||
throw std::runtime_error("Unable to get passwd struct.");
|
throw std::runtime_error("Unable to get passwd struct.");
|
||||||
}
|
}
|
||||||
const char *tempRes = pw->pw_dir;
|
const char *tempRes = pw->pw_dir;
|
||||||
if (!tempRes) {
|
if (!tempRes)
|
||||||
|
{
|
||||||
throw std::runtime_error("User has no home directory");
|
throw std::runtime_error("User has no home directory");
|
||||||
}
|
}
|
||||||
res = tempRes;
|
res = tempRes;
|
||||||
|
|
@ -85,23 +90,30 @@ static std::string getHome() {
|
||||||
#include <winerror.h>
|
#include <winerror.h>
|
||||||
// For WideCharToMultiByte
|
// For WideCharToMultiByte
|
||||||
#include <stringapiset.h>
|
#include <stringapiset.h>
|
||||||
|
|
||||||
|
#define _WIN32_WINNT 0x0600
|
||||||
// For SHGetFolderPathW and various CSIDL "magic numbers"
|
// For SHGetFolderPathW and various CSIDL "magic numbers"
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
|
|
||||||
namespace pf {
|
namespace pf
|
||||||
namespace internal {
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
std::string win32_utf16_to_utf8(const wchar_t* wstr) {
|
std::string win32_utf16_to_utf8(const wchar_t *wstr)
|
||||||
|
{
|
||||||
std::string res;
|
std::string res;
|
||||||
// If the 6th parameter is 0 then WideCharToMultiByte returns the number of bytes needed to store the result.
|
// 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);
|
int actualSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, nullptr, 0, nullptr, nullptr);
|
||||||
if (actualSize > 0) {
|
if (actualSize > 0)
|
||||||
|
{
|
||||||
// If the converted UTF-8 string could not be in the initial buffer. Allocate one that can hold it.
|
// If the converted UTF-8 string could not be in the initial buffer. Allocate one that can hold it.
|
||||||
std::vector<char> buffer(actualSize);
|
std::vector<char> buffer(actualSize);
|
||||||
actualSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &buffer[0], static_cast<int>(buffer.size()), nullptr, nullptr);
|
actualSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &buffer[0], static_cast<int>(buffer.size()), nullptr, nullptr);
|
||||||
res = buffer.data();
|
res = buffer.data();
|
||||||
}
|
}
|
||||||
if (actualSize == 0) {
|
if (actualSize == 0)
|
||||||
|
{
|
||||||
// WideCharToMultiByte return 0 for errors.
|
// WideCharToMultiByte return 0 for errors.
|
||||||
throw std::runtime_error("UTF16 to UTF8 failed with error code: " + std::to_string(GetLastError()));
|
throw std::runtime_error("UTF16 to UTF8 failed with error code: " + std::to_string(GetLastError()));
|
||||||
}
|
}
|
||||||
|
|
@ -111,36 +123,44 @@ std::string win32_utf16_to_utf8(const wchar_t* wstr) {
|
||||||
} // namesapce internal
|
} // namesapce internal
|
||||||
} // namespace pf
|
} // namespace pf
|
||||||
|
|
||||||
class FreeCoTaskMemory {
|
class FreeCoTaskMemory
|
||||||
|
{
|
||||||
LPWSTR pointer = NULL;
|
LPWSTR pointer = NULL;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FreeCoTaskMemory(LPWSTR pointer) : pointer(pointer){};
|
explicit FreeCoTaskMemory(LPWSTR pointer) : pointer(pointer){};
|
||||||
~FreeCoTaskMemory() {
|
~FreeCoTaskMemory()
|
||||||
|
{
|
||||||
CoTaskMemFree(pointer);
|
CoTaskMemFree(pointer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string GetKnownWindowsFolder(REFKNOWNFOLDERID folderId, const char* errorMsg) {
|
static std::string GetKnownWindowsFolder(REFKNOWNFOLDERID folderId, const char *errorMsg)
|
||||||
|
{
|
||||||
LPWSTR wszPath = NULL;
|
LPWSTR wszPath = NULL;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
hr = SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, NULL, &wszPath);
|
hr = SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, NULL, &wszPath);
|
||||||
FreeCoTaskMemory scopeBoundMemory(wszPath);
|
FreeCoTaskMemory scopeBoundMemory(wszPath);
|
||||||
|
|
||||||
if (!SUCCEEDED(hr)) {
|
if (!SUCCEEDED(hr))
|
||||||
|
{
|
||||||
throw std::runtime_error(errorMsg);
|
throw std::runtime_error(errorMsg);
|
||||||
}
|
}
|
||||||
return pf::internal::win32_utf16_to_utf8(wszPath);
|
return pf::internal::win32_utf16_to_utf8(wszPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetAppData() {
|
static std::string GetAppData()
|
||||||
|
{
|
||||||
return GetKnownWindowsFolder(FOLDERID_RoamingAppData, "RoamingAppData could not be found");
|
return GetKnownWindowsFolder(FOLDERID_RoamingAppData, "RoamingAppData could not be found");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetAppDataCommon() {
|
static std::string GetAppDataCommon()
|
||||||
|
{
|
||||||
return GetKnownWindowsFolder(FOLDERID_ProgramData, "ProgramData could not be found");
|
return GetKnownWindowsFolder(FOLDERID_ProgramData, "ProgramData could not be found");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetAppDataLocal() {
|
static std::string GetAppDataLocal()
|
||||||
|
{
|
||||||
return GetKnownWindowsFolder(FOLDERID_LocalAppData, "LocalAppData could not be found");
|
return GetKnownWindowsFolder(FOLDERID_LocalAppData, "LocalAppData could not be found");
|
||||||
}
|
}
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
|
@ -153,20 +173,22 @@ static std::string GetAppDataLocal() {
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
// Typically Linux. For easy reading the comments will just say Linux but should work with most *nixes
|
// 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) {
|
static void throwOnRelative(const char *envName, const char *envValue)
|
||||||
if (envValue[0] != '/') {
|
{
|
||||||
|
if (envValue[0] != '/')
|
||||||
|
{
|
||||||
char buffer[200];
|
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);
|
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);
|
throw std::runtime_error(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string getLinuxFolderDefault(const char *envName, const char *defaultRelativePath)
|
||||||
|
{
|
||||||
static std::string getLinuxFolderDefault(const char* envName, const char* defaultRelativePath) {
|
|
||||||
std::string res;
|
std::string res;
|
||||||
const char *tempRes = std::getenv(envName);
|
const char *tempRes = std::getenv(envName);
|
||||||
if (tempRes) {
|
if (tempRes)
|
||||||
|
{
|
||||||
throwOnRelative(envName, tempRes);
|
throwOnRelative(envName, tempRes);
|
||||||
res = tempRes;
|
res = tempRes;
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -175,9 +197,11 @@ static std::string getLinuxFolderDefault(const char* envName, const char* defaul
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void appendExtraFolders(const char* envName, const char* defaultValue, std::vector<std::string>& folders) {
|
static void appendExtraFolders(const char *envName, const char *defaultValue, std::vector<std::string> &folders)
|
||||||
|
{
|
||||||
const char *envValue = std::getenv(envName);
|
const char *envValue = std::getenv(envName);
|
||||||
if (!envValue) {
|
if (!envValue)
|
||||||
|
{
|
||||||
envValue = defaultValue;
|
envValue = defaultValue;
|
||||||
}
|
}
|
||||||
pf::internal::appendExtraFoldersTokenizer(envName, envValue, folders);
|
pf::internal::appendExtraFoldersTokenizer(envName, envValue, folders);
|
||||||
|
|
@ -185,19 +209,24 @@ static void appendExtraFolders(const char* envName, const char* defaultValue, st
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace pf
|
||||||
namespace pf {
|
{
|
||||||
|
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||||
namespace internal {
|
namespace internal
|
||||||
void appendExtraFoldersTokenizer(const char* envName, const char* envValue, std::vector<std::string>& folders) {
|
{
|
||||||
|
void appendExtraFoldersTokenizer(const char *envName, const char *envValue, std::vector<std::string> &folders)
|
||||||
|
{
|
||||||
std::stringstream ss(envValue);
|
std::stringstream ss(envValue);
|
||||||
std::string value;
|
std::string value;
|
||||||
while (std::getline(ss, value, ':')) {
|
while (std::getline(ss, value, ':'))
|
||||||
if (value[0] == '/') {
|
{
|
||||||
|
if (value[0] == '/')
|
||||||
|
{
|
||||||
folders.push_back(value);
|
folders.push_back(value);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
// Unless the system is wrongly configured this should never happen... But of course some systems will be incorectly configured.
|
// 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.
|
// 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";
|
std::cerr << "Skipping path \"" << value << "\" in \"" << envName << "\" because it does not start with a \"/\"\n";
|
||||||
|
|
@ -207,7 +236,8 @@ void appendExtraFoldersTokenizer(const char* envName, const char* envValue, std:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string getDataHome() {
|
std::string getDataHome()
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetAppData();
|
return GetAppData();
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
|
@ -217,7 +247,8 @@ std::string getDataHome() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getConfigHome() {
|
std::string getConfigHome()
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetAppData();
|
return GetAppData();
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
|
@ -227,7 +258,8 @@ std::string getConfigHome() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getCacheDir() {
|
std::string getCacheDir()
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetAppDataLocal();
|
return GetAppDataLocal();
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
|
@ -246,8 +278,8 @@ std::string getUserHome()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string getStateDir()
|
||||||
std::string getStateDir() {
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetAppDataLocal();
|
return GetAppDataLocal();
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
|
@ -257,7 +289,8 @@ std::string getStateDir() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendAdditionalDataDirectories(std::vector<std::string>& homes) {
|
void appendAdditionalDataDirectories(std::vector<std::string> &homes)
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
homes.push_back(GetAppDataCommon());
|
homes.push_back(GetAppDataCommon());
|
||||||
#elif !defined(__APPLE__)
|
#elif !defined(__APPLE__)
|
||||||
|
|
@ -265,7 +298,8 @@ void appendAdditionalDataDirectories(std::vector<std::string>& homes) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendAdditionalConfigDirectories(std::vector<std::string>& homes) {
|
void appendAdditionalConfigDirectories(std::vector<std::string> &homes)
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
homes.push_back(GetAppDataCommon());
|
homes.push_back(GetAppDataCommon());
|
||||||
#elif !defined(__APPLE__)
|
#elif !defined(__APPLE__)
|
||||||
|
|
@ -274,18 +308,23 @@ void appendAdditionalConfigDirectories(std::vector<std::string>& homes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||||
struct PlatformFolders::PlatformFoldersData {
|
struct PlatformFolders::PlatformFoldersData
|
||||||
|
{
|
||||||
std::map<std::string, std::string> folders;
|
std::map<std::string, std::string> folders;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void PlatformFoldersAddFromFile(const std::string& filename, 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::ifstream infile(filename.c_str());
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(infile, line)) {
|
while (std::getline(infile, line))
|
||||||
if (line.length() == 0 || line.at(0) == '#' || line.substr(0, 4) != "XDG_" || line.find("_DIR") == std::string::npos) {
|
{
|
||||||
|
if (line.length() == 0 || line.at(0) == '#' || line.substr(0, 4) != "XDG_" || line.find("_DIR") == std::string::npos)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
std::size_t splitPos = line.find('=');
|
std::size_t splitPos = line.find('=');
|
||||||
std::string key = line.substr(0, splitPos);
|
std::string key = line.substr(0, splitPos);
|
||||||
std::size_t valueStart = line.find('"', splitPos);
|
std::size_t valueStart = line.find('"', splitPos);
|
||||||
|
|
@ -293,14 +332,16 @@ static void PlatformFoldersAddFromFile(const std::string& filename, std::map<std
|
||||||
std::string value = line.substr(valueStart + 1, valueEnd - valueStart - 1);
|
std::string value = line.substr(valueStart + 1, valueEnd - valueStart - 1);
|
||||||
folders[key] = value;
|
folders[key] = value;
|
||||||
}
|
}
|
||||||
catch (std::exception& e) {
|
catch (std::exception &e)
|
||||||
|
{
|
||||||
std::cerr << "WARNING: Failed to process \"" << line << "\" from \"" << filename << "\". Error: " << e.what() << "\n";
|
std::cerr << "WARNING: Failed to process \"" << line << "\" from \"" << filename << "\". Error: " << e.what() << "\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PlatformFoldersFillData(std::map<std::string, std::string>& folders) {
|
static void PlatformFoldersFillData(std::map<std::string, std::string> &folders)
|
||||||
|
{
|
||||||
folders["XDG_DOCUMENTS_DIR"] = "$HOME/Documents";
|
folders["XDG_DOCUMENTS_DIR"] = "$HOME/Documents";
|
||||||
folders["XDG_DESKTOP_DIR"] = "$HOME/Desktop";
|
folders["XDG_DESKTOP_DIR"] = "$HOME/Desktop";
|
||||||
folders["XDG_DOWNLOAD_DIR"] = "$HOME/Downloads";
|
folders["XDG_DOWNLOAD_DIR"] = "$HOME/Downloads";
|
||||||
|
|
@ -310,35 +351,42 @@ static void PlatformFoldersFillData(std::map<std::string, std::string>& folders)
|
||||||
folders["XDG_TEMPLATES_DIR"] = "$HOME/.Templates";
|
folders["XDG_TEMPLATES_DIR"] = "$HOME/.Templates";
|
||||||
folders["XDG_VIDEOS_DIR"] = "$HOME/Videos";
|
folders["XDG_VIDEOS_DIR"] = "$HOME/Videos";
|
||||||
PlatformFoldersAddFromFile(getConfigHome() + "/user-dirs.dirs", folders);
|
PlatformFoldersAddFromFile(getConfigHome() + "/user-dirs.dirs", folders);
|
||||||
for (std::map<std::string, std::string>::iterator itr = folders.begin() ; itr != folders.end() ; ++itr ) {
|
for (std::map<std::string, std::string>::iterator itr = folders.begin(); itr != folders.end(); ++itr)
|
||||||
|
{
|
||||||
std::string &value = itr->second;
|
std::string &value = itr->second;
|
||||||
if (value.compare(0, 5, "$HOME") == 0) {
|
if (value.compare(0, 5, "$HOME") == 0)
|
||||||
|
{
|
||||||
value = getHome() + value.substr(5, std::string::npos);
|
value = getHome() + value.substr(5, std::string::npos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PlatformFolders::PlatformFolders() {
|
PlatformFolders::PlatformFolders()
|
||||||
|
{
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||||
this->data = new PlatformFolders::PlatformFoldersData();
|
this->data = new PlatformFolders::PlatformFoldersData();
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
PlatformFoldersFillData(data->folders);
|
PlatformFoldersFillData(data->folders);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...)
|
||||||
|
{
|
||||||
delete this->data;
|
delete this->data;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
PlatformFolders::~PlatformFolders() {
|
PlatformFolders::~PlatformFolders()
|
||||||
|
{
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||||
delete this->data;
|
delete this->data;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PlatformFolders::getDocumentsFolder() const {
|
std::string PlatformFolders::getDocumentsFolder() const
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetKnownWindowsFolder(FOLDERID_Documents, "Failed to find My Documents folder");
|
return GetKnownWindowsFolder(FOLDERID_Documents, "Failed to find My Documents folder");
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
|
@ -348,7 +396,8 @@ std::string PlatformFolders::getDocumentsFolder() const {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PlatformFolders::getDesktopFolder() const {
|
std::string PlatformFolders::getDesktopFolder() const
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetKnownWindowsFolder(FOLDERID_Desktop, "Failed to find Desktop folder");
|
return GetKnownWindowsFolder(FOLDERID_Desktop, "Failed to find Desktop folder");
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
|
@ -358,7 +407,8 @@ std::string PlatformFolders::getDesktopFolder() const {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PlatformFolders::getPicturesFolder() const {
|
std::string PlatformFolders::getPicturesFolder() const
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetKnownWindowsFolder(FOLDERID_Pictures, "Failed to find My Pictures folder");
|
return GetKnownWindowsFolder(FOLDERID_Pictures, "Failed to find My Pictures folder");
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
|
@ -368,7 +418,8 @@ std::string PlatformFolders::getPicturesFolder() const {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PlatformFolders::getPublicFolder() const {
|
std::string PlatformFolders::getPublicFolder() const
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetKnownWindowsFolder(FOLDERID_Public, "Failed to find the Public folder");
|
return GetKnownWindowsFolder(FOLDERID_Public, "Failed to find the Public folder");
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
|
@ -378,7 +429,8 @@ std::string PlatformFolders::getPublicFolder() const {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PlatformFolders::getDownloadFolder1() const {
|
std::string PlatformFolders::getDownloadFolder1() const
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetKnownWindowsFolder(FOLDERID_Downloads, "Failed to find My Downloads folder");
|
return GetKnownWindowsFolder(FOLDERID_Downloads, "Failed to find My Downloads folder");
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
|
@ -388,7 +440,8 @@ std::string PlatformFolders::getDownloadFolder1() const {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PlatformFolders::getMusicFolder() const {
|
std::string PlatformFolders::getMusicFolder() const
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetKnownWindowsFolder(FOLDERID_Music, "Failed to find My Music folder");
|
return GetKnownWindowsFolder(FOLDERID_Music, "Failed to find My Music folder");
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
|
@ -398,7 +451,8 @@ std::string PlatformFolders::getMusicFolder() const {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PlatformFolders::getVideoFolder() const {
|
std::string PlatformFolders::getVideoFolder() const
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetKnownWindowsFolder(FOLDERID_Videos, "Failed to find My Video folder");
|
return GetKnownWindowsFolder(FOLDERID_Videos, "Failed to find My Video folder");
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
|
@ -408,7 +462,8 @@ std::string PlatformFolders::getVideoFolder() const {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PlatformFolders::getSaveGamesFolder1() const {
|
std::string PlatformFolders::getSaveGamesFolder1() const
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#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".
|
// 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
|
// Data that should not be user accessible should be placed under GetDataHome() instead
|
||||||
|
|
@ -420,43 +475,53 @@ std::string PlatformFolders::getSaveGamesFolder1() const {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getDesktopFolder() {
|
std::string getDesktopFolder()
|
||||||
|
{
|
||||||
return PlatformFolders().getDesktopFolder();
|
return PlatformFolders().getDesktopFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getDocumentsFolder() {
|
std::string getDocumentsFolder()
|
||||||
|
{
|
||||||
return PlatformFolders().getDocumentsFolder();
|
return PlatformFolders().getDocumentsFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getDownloadFolder() {
|
std::string getDownloadFolder()
|
||||||
|
{
|
||||||
return PlatformFolders().getDownloadFolder1();
|
return PlatformFolders().getDownloadFolder1();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getDownloadFolder1() {
|
std::string getDownloadFolder1()
|
||||||
|
{
|
||||||
return getDownloadFolder();
|
return getDownloadFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getPicturesFolder() {
|
std::string getPicturesFolder()
|
||||||
|
{
|
||||||
return PlatformFolders().getPicturesFolder();
|
return PlatformFolders().getPicturesFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getPublicFolder() {
|
std::string getPublicFolder()
|
||||||
|
{
|
||||||
return PlatformFolders().getPublicFolder();
|
return PlatformFolders().getPublicFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getMusicFolder() {
|
std::string getMusicFolder()
|
||||||
|
{
|
||||||
return PlatformFolders().getMusicFolder();
|
return PlatformFolders().getMusicFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getVideoFolder() {
|
std::string getVideoFolder()
|
||||||
|
{
|
||||||
return PlatformFolders().getVideoFolder();
|
return PlatformFolders().getVideoFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getSaveGamesFolder1() {
|
std::string getSaveGamesFolder1()
|
||||||
|
{
|
||||||
return PlatformFolders().getSaveGamesFolder1();
|
return PlatformFolders().getSaveGamesFolder1();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getSaveGamesFolder2() {
|
std::string getSaveGamesFolder2()
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetKnownWindowsFolder(FOLDERID_SavedGames, "Failed to find Saved Games folder");
|
return GetKnownWindowsFolder(FOLDERID_SavedGames, "Failed to find Saved Games folder");
|
||||||
#else
|
#else
|
||||||
|
|
@ -464,5 +529,4 @@ std::string getSaveGamesFolder2() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace pf
|
} // namespace pf
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue