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.
|
|
@ -5,33 +5,36 @@ set(STORY_EDITOR_PROJECT story-editor)
|
|||
project(${STORY_EDITOR_PROJECT} LANGUAGES C CXX)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set (CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
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)
|
||||
|
||||
|
||||
if(POLICY CMP0072)
|
||||
cmake_policy(SET CMP0072 NEW)
|
||||
endif()
|
||||
|
||||
find_package(OpenGL REQUIRED)
|
||||
|
||||
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
|
||||
URL https://github.com/ocornut/imgui/archive/refs/tags/v${IMGUI_VERSION}-docking.zip
|
||||
)
|
||||
|
||||
|
||||
FetchContent_GetProperties(imgui)
|
||||
if (NOT imgui_POPULATED)
|
||||
|
||||
if(NOT imgui_POPULATED)
|
||||
set(FETCHCONTENT_QUIET NO)
|
||||
FetchContent_Populate(imgui)
|
||||
endif()
|
||||
|
|
@ -42,17 +45,15 @@ add_compile_definitions(CUSTOM_IMGUIFILEDIALOG_CONFIG="${CMAKE_SOURCE_DIR}/src/C
|
|||
add_compile_definitions(IMGUI_INCLUDE="imgui.h")
|
||||
add_subdirectory(libs/ImGuiFileDialog)
|
||||
|
||||
|
||||
#=========================================================================================================================
|
||||
# =========================================================================================================================
|
||||
# SDL
|
||||
#=========================================================================================================================
|
||||
|
||||
# =========================================================================================================================
|
||||
Set(FETCHCONTENT_QUIET FALSE)
|
||||
|
||||
FetchContent_Declare(
|
||||
sdl2
|
||||
GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
|
||||
GIT_TAG origin/SDL2
|
||||
GIT_TAG origin/SDL2
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
|
|
@ -60,29 +61,27 @@ FetchContent_Declare(
|
|||
set(BUILD_SHARED_LIBS TRUE)
|
||||
set(SDL_STATIC TRUE)
|
||||
FetchContent_MakeAvailable(sdl2)
|
||||
#add_subdirectory(libs/SDL)
|
||||
#include_directories(libs/SDL/include)
|
||||
|
||||
# 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
|
||||
#)
|
||||
|
||||
## START ADDITION
|
||||
#set(SDL2IMAGE_INSTALL OFF)
|
||||
#set(BUILD_SHARED_LIBS FALSE)
|
||||
## END ADDITION
|
||||
|
||||
#FetchContent_MakeAvailable(SDL2_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
|
||||
# )
|
||||
|
||||
# # START ADDITION
|
||||
# set(SDL2IMAGE_INSTALL OFF)
|
||||
# set(BUILD_SHARED_LIBS FALSE)
|
||||
# # END ADDITION
|
||||
|
||||
# FetchContent_MakeAvailable(SDL2_image)
|
||||
set(SRCS
|
||||
|
||||
src/main.cpp
|
||||
|
|
@ -147,7 +146,6 @@ set(SRCS
|
|||
${imgui_SOURCE_DIR}/imgui_tables.cpp
|
||||
${imgui_SOURCE_DIR}/imgui_draw.cpp
|
||||
|
||||
|
||||
../software/chip32/chip32_assembler.cpp
|
||||
../software/chip32/chip32_vm.c
|
||||
../software/library/audio_player.cpp
|
||||
|
|
@ -169,10 +167,10 @@ if(WIN32)
|
|||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_executable(${STORY_EDITOR_PROJECT}
|
||||
WIN32
|
||||
${SRCS}
|
||||
)
|
||||
add_executable(${STORY_EDITOR_PROJECT}
|
||||
WIN32
|
||||
${SRCS}
|
||||
)
|
||||
else()
|
||||
add_executable(${STORY_EDITOR_PROJECT}
|
||||
${SRCS}
|
||||
|
|
@ -191,8 +189,6 @@ target_include_directories(${STORY_EDITOR_PROJECT} PUBLIC
|
|||
../software/chip32/
|
||||
)
|
||||
|
||||
|
||||
|
||||
add_definitions(-DIMGUI_USE_WCHAR32)
|
||||
add_link_options(-static-libgcc -static-libstdc++)
|
||||
|
||||
|
|
@ -202,26 +198,48 @@ target_compile_definitions(${STORY_EDITOR_PROJECT} PUBLIC "$<$<CONFIG:DEBUG>:DEB
|
|||
|
||||
target_link_directories(${STORY_EDITOR_PROJECT} PUBLIC ${sdl2_BINARY_DIR})
|
||||
message(${sdl2_BINARY_DIR})
|
||||
if (UNIX)
|
||||
target_link_libraries(${STORY_EDITOR_PROJECT}
|
||||
pthread
|
||||
udev
|
||||
OpenGL::GL
|
||||
dl
|
||||
SDL2
|
||||
)
|
||||
set(SDL2_BIN_DIR ${sdl2_BINARY_DIR})
|
||||
|
||||
if(UNIX)
|
||||
target_link_libraries(${STORY_EDITOR_PROJECT}
|
||||
pthread
|
||||
udev
|
||||
OpenGL::GL
|
||||
dl
|
||||
SDL2
|
||||
)
|
||||
elseif(WIN32)
|
||||
|
||||
#target_compile_features("-Wl,-subsystem,windows")
|
||||
|
||||
target_link_libraries(${STORY_EDITOR_PROJECT}
|
||||
OpenGL::GL
|
||||
# SDL2::SDL2main
|
||||
SDL2
|
||||
ws2_32.lib psapi.lib setupapi.lib cfgmgr32.lib advapi32.lib Dbghelp.lib
|
||||
)
|
||||
#set_target_properties(${STORY_EDITOR_PROJECT} PROPERTIES
|
||||
#LINK_FLAGS /SUBSYSTEM:CONSOLE
|
||||
#)
|
||||
target_link_libraries(${STORY_EDITOR_PROJECT}
|
||||
OpenGL::GL
|
||||
SDL2
|
||||
ws2_32.lib psapi.lib setupapi.lib cfgmgr32.lib advapi32.lib
|
||||
)
|
||||
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
|
||||
#define CONSOLEWINDOW_H
|
||||
#pragma once
|
||||
|
||||
#include "gui.h"
|
||||
#include <string>
|
||||
|
|
@ -8,7 +7,6 @@
|
|||
|
||||
#include "window_base.h"
|
||||
|
||||
|
||||
// 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.
|
||||
struct ConsoleWindow : public WindowBase
|
||||
|
|
@ -18,17 +16,48 @@ public:
|
|||
~ConsoleWindow();
|
||||
|
||||
// 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 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; }
|
||||
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 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)
|
||||
{
|
||||
|
||||
|
||||
// FIXME-OPT
|
||||
Entry e{text, type};
|
||||
std::scoped_lock<std::mutex> mutex(mLogMutex);
|
||||
|
|
@ -41,22 +70,18 @@ public:
|
|||
|
||||
virtual void Draw() override;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
struct Entry {
|
||||
struct Entry
|
||||
{
|
||||
std::string text;
|
||||
uint32_t type;
|
||||
};
|
||||
|
||||
std::mutex mLogMutex;
|
||||
char InputBuf[256];
|
||||
std::vector<Entry> Items;
|
||||
|
||||
ImGuiTextFilter Filter;
|
||||
bool AutoScroll;
|
||||
bool ScrollToBottom;
|
||||
std::mutex mLogMutex;
|
||||
char InputBuf[256];
|
||||
std::vector<Entry> Items;
|
||||
|
||||
ImGuiTextFilter Filter;
|
||||
bool AutoScroll;
|
||||
bool ScrollToBottom;
|
||||
};
|
||||
|
||||
#endif // CONSOLEWINDOW_H
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ void MainWindow::DrawMainMenuBar()
|
|||
std::string home = pf::getUserHome() + "/";
|
||||
|
||||
#ifdef DEBUG
|
||||
home = "/home/anthony/ostproj/ba869e4b-03d6-4249-9202-85b4cec767a7/";
|
||||
home = "/mnt/work/git/open-stories/ba869e4b-03d6-4249-9202-85b4cec767a7/";
|
||||
#endif
|
||||
|
||||
ImGuiFileDialog::Instance()->OpenDialog("OpenProjectDlgKey", "Choose File", ".json", home, 1, nullptr, ImGuiFileDialogFlags_Modal);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,13 @@
|
|||
#include "media_node.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)
|
||||
: WindowBase("Node editor")
|
||||
|
|
@ -35,6 +42,7 @@ void NodeEditorWindow::Initialize()
|
|||
void NodeEditorWindow::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->FromJson(internalDataJson);
|
||||
|
||||
m_ids.insert(restoredNodeId);
|
||||
|
||||
m_nodes.push_back(n);
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
|
@ -409,6 +431,41 @@ void NodeEditorWindow::Draw()
|
|||
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::SetCurrentEditor(nullptr);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <imgui_node_editor.h>
|
||||
#include "base_node.h"
|
||||
#include "window_base.h"
|
||||
#include "i_story_manager.h"
|
||||
#include "story_project.h"
|
||||
#include "json.hpp"
|
||||
|
||||
|
||||
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.
|
||||
void ToolbarUI();
|
||||
|
||||
std::set<int> m_ids;
|
||||
|
||||
void BuildNode(Node* node)
|
||||
{
|
||||
|
|
@ -117,5 +116,6 @@ private:
|
|||
ed::PinId GetInputPin(unsigned long modelNodeId, int pinIndex);
|
||||
ed::PinId GetOutputPin(unsigned long modelNodeId, int pinIndex);
|
||||
uint32_t FindFirstNode() const;
|
||||
int GenerateNodeId();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -43,29 +43,34 @@ SOFTWARE.
|
|||
* 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() {
|
||||
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.
|
||||
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 *pw = nullptr;
|
||||
struct passwd pwd;
|
||||
long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||
if (bufsize < 0) {
|
||||
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) {
|
||||
if (error_code)
|
||||
{
|
||||
throw std::runtime_error("Unable to get passwd struct.");
|
||||
}
|
||||
const char* tempRes = pw->pw_dir;
|
||||
if (!tempRes) {
|
||||
const char *tempRes = pw->pw_dir;
|
||||
if (!tempRes)
|
||||
{
|
||||
throw std::runtime_error("User has no home directory");
|
||||
}
|
||||
res = tempRes;
|
||||
|
|
@ -85,62 +90,77 @@ static std::string getHome() {
|
|||
#include <winerror.h>
|
||||
// For WideCharToMultiByte
|
||||
#include <stringapiset.h>
|
||||
|
||||
#define _WIN32_WINNT 0x0600
|
||||
// For SHGetFolderPathW and various CSIDL "magic numbers"
|
||||
#include <shlobj.h>
|
||||
|
||||
namespace pf {
|
||||
namespace internal {
|
||||
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;
|
||||
}
|
||||
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
|
||||
} // namesapce internal
|
||||
} // namespace pf
|
||||
|
||||
class FreeCoTaskMemory {
|
||||
class FreeCoTaskMemory
|
||||
{
|
||||
LPWSTR pointer = NULL;
|
||||
|
||||
public:
|
||||
explicit FreeCoTaskMemory(LPWSTR pointer) : pointer(pointer) {};
|
||||
~FreeCoTaskMemory() {
|
||||
explicit FreeCoTaskMemory(LPWSTR pointer) : pointer(pointer){};
|
||||
~FreeCoTaskMemory()
|
||||
{
|
||||
CoTaskMemFree(pointer);
|
||||
}
|
||||
};
|
||||
|
||||
static std::string GetKnownWindowsFolder(REFKNOWNFOLDERID folderId, const char* errorMsg) {
|
||||
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)) {
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
static std::string GetAppDataCommon() {
|
||||
static std::string GetAppDataCommon()
|
||||
{
|
||||
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");
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
|
|
@ -151,22 +171,24 @@ static std::string GetAppDataLocal() {
|
|||
// 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
|
||||
// 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] != '/') {
|
||||
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) {
|
||||
static std::string getLinuxFolderDefault(const char *envName, const char *defaultRelativePath)
|
||||
{
|
||||
std::string res;
|
||||
const char* tempRes = std::getenv(envName);
|
||||
if (tempRes) {
|
||||
const char *tempRes = std::getenv(envName);
|
||||
if (tempRes)
|
||||
{
|
||||
throwOnRelative(envName, tempRes);
|
||||
res = tempRes;
|
||||
return res;
|
||||
|
|
@ -175,294 +197,336 @@ static std::string getLinuxFolderDefault(const char* envName, const char* defaul
|
|||
return res;
|
||||
}
|
||||
|
||||
static void appendExtraFolders(const char* envName, const char* defaultValue, std::vector<std::string>& folders) {
|
||||
const char* envValue = std::getenv(envName);
|
||||
if (!envValue) {
|
||||
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);
|
||||
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()
|
||||
namespace pf
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return std::getenv("USERPROFILE");
|
||||
#else
|
||||
return getHome();
|
||||
|
||||
#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 getStateDir() {
|
||||
std::string getDataHome()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return GetAppDataLocal();
|
||||
return GetAppData();
|
||||
#elif defined(__APPLE__)
|
||||
return getHome()+"/Library/Application Support";
|
||||
return getHome() + "/Library/Application Support";
|
||||
#else
|
||||
return getLinuxFolderDefault("XDG_STATE_HOME", ".local/state");
|
||||
return getLinuxFolderDefault("XDG_DATA_HOME", ".local/share");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void appendAdditionalDataDirectories(std::vector<std::string>& homes) {
|
||||
std::string getConfigHome()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
homes.push_back(GetAppDataCommon());
|
||||
#elif !defined(__APPLE__)
|
||||
appendExtraFolders("XDG_DATA_DIRS", "/usr/local/share/:/usr/share/", homes);
|
||||
return GetAppData();
|
||||
#elif defined(__APPLE__)
|
||||
return getHome() + "/Library/Application Support";
|
||||
#else
|
||||
return getLinuxFolderDefault("XDG_CONFIG_HOME", ".config");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void appendAdditionalConfigDirectories(std::vector<std::string>& homes) {
|
||||
std::string getCacheDir()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
homes.push_back(GetAppDataCommon());
|
||||
#elif !defined(__APPLE__)
|
||||
appendExtraFolders("XDG_CONFIG_DIRS", "/etc/xdg", homes);
|
||||
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;
|
||||
};
|
||||
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 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);
|
||||
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() {
|
||||
PlatformFolders::PlatformFolders()
|
||||
{
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
this->data = new PlatformFolders::PlatformFoldersData();
|
||||
try {
|
||||
PlatformFoldersFillData(data->folders);
|
||||
this->data = new PlatformFolders::PlatformFoldersData();
|
||||
try
|
||||
{
|
||||
PlatformFoldersFillData(data->folders);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete this->data;
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch (...) {
|
||||
|
||||
PlatformFolders::~PlatformFolders()
|
||||
{
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
delete this->data;
|
||||
throw;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PlatformFolders::~PlatformFolders() {
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
delete this->data;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string PlatformFolders::getDocumentsFolder() const {
|
||||
std::string PlatformFolders::getDocumentsFolder() const
|
||||
{
|
||||
#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__)
|
||||
return getHome()+"/Documents";
|
||||
return getHome() + "/Documents";
|
||||
#else
|
||||
return data->folders["XDG_DOCUMENTS_DIR"];
|
||||
return data->folders["XDG_DOCUMENTS_DIR"];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::string PlatformFolders::getDesktopFolder() const {
|
||||
std::string PlatformFolders::getDesktopFolder() const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return GetKnownWindowsFolder(FOLDERID_Desktop, "Failed to find Desktop folder");
|
||||
return GetKnownWindowsFolder(FOLDERID_Desktop, "Failed to find Desktop folder");
|
||||
#elif defined(__APPLE__)
|
||||
return getHome()+"/Desktop";
|
||||
return getHome() + "/Desktop";
|
||||
#else
|
||||
return data->folders["XDG_DESKTOP_DIR"];
|
||||
return data->folders["XDG_DESKTOP_DIR"];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::string PlatformFolders::getPicturesFolder() const {
|
||||
std::string PlatformFolders::getPicturesFolder() const
|
||||
{
|
||||
#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__)
|
||||
return getHome()+"/Pictures";
|
||||
return getHome() + "/Pictures";
|
||||
#else
|
||||
return data->folders["XDG_PICTURES_DIR"];
|
||||
return data->folders["XDG_PICTURES_DIR"];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::string PlatformFolders::getPublicFolder() const {
|
||||
std::string PlatformFolders::getPublicFolder() const
|
||||
{
|
||||
#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__)
|
||||
return getHome()+"/Public";
|
||||
return getHome() + "/Public";
|
||||
#else
|
||||
return data->folders["XDG_PUBLICSHARE_DIR"];
|
||||
return data->folders["XDG_PUBLICSHARE_DIR"];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::string PlatformFolders::getDownloadFolder1() const {
|
||||
std::string PlatformFolders::getDownloadFolder1() const
|
||||
{
|
||||
#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__)
|
||||
return getHome()+"/Downloads";
|
||||
return getHome() + "/Downloads";
|
||||
#else
|
||||
return data->folders["XDG_DOWNLOAD_DIR"];
|
||||
return data->folders["XDG_DOWNLOAD_DIR"];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::string PlatformFolders::getMusicFolder() const {
|
||||
std::string PlatformFolders::getMusicFolder() const
|
||||
{
|
||||
#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__)
|
||||
return getHome()+"/Music";
|
||||
return getHome() + "/Music";
|
||||
#else
|
||||
return data->folders["XDG_MUSIC_DIR"];
|
||||
return data->folders["XDG_MUSIC_DIR"];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::string PlatformFolders::getVideoFolder() const {
|
||||
std::string PlatformFolders::getVideoFolder() const
|
||||
{
|
||||
#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__)
|
||||
return getHome()+"/Movies";
|
||||
return getHome() + "/Movies";
|
||||
#else
|
||||
return data->folders["XDG_VIDEOS_DIR"];
|
||||
return data->folders["XDG_VIDEOS_DIR"];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::string PlatformFolders::getSaveGamesFolder1() const {
|
||||
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";
|
||||
// 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";
|
||||
return getHome() + "/Library/Application Support";
|
||||
#else
|
||||
return getDataHome();
|
||||
return getDataHome();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::string getDesktopFolder() {
|
||||
return PlatformFolders().getDesktopFolder();
|
||||
}
|
||||
std::string getDesktopFolder()
|
||||
{
|
||||
return PlatformFolders().getDesktopFolder();
|
||||
}
|
||||
|
||||
std::string getDocumentsFolder() {
|
||||
return PlatformFolders().getDocumentsFolder();
|
||||
}
|
||||
std::string getDocumentsFolder()
|
||||
{
|
||||
return PlatformFolders().getDocumentsFolder();
|
||||
}
|
||||
|
||||
std::string getDownloadFolder() {
|
||||
return PlatformFolders().getDownloadFolder1();
|
||||
}
|
||||
std::string getDownloadFolder()
|
||||
{
|
||||
return PlatformFolders().getDownloadFolder1();
|
||||
}
|
||||
|
||||
std::string getDownloadFolder1() {
|
||||
return getDownloadFolder();
|
||||
}
|
||||
std::string getDownloadFolder1()
|
||||
{
|
||||
return getDownloadFolder();
|
||||
}
|
||||
|
||||
std::string getPicturesFolder() {
|
||||
return PlatformFolders().getPicturesFolder();
|
||||
}
|
||||
std::string getPicturesFolder()
|
||||
{
|
||||
return PlatformFolders().getPicturesFolder();
|
||||
}
|
||||
|
||||
std::string getPublicFolder() {
|
||||
return PlatformFolders().getPublicFolder();
|
||||
}
|
||||
std::string getPublicFolder()
|
||||
{
|
||||
return PlatformFolders().getPublicFolder();
|
||||
}
|
||||
|
||||
std::string getMusicFolder() {
|
||||
return PlatformFolders().getMusicFolder();
|
||||
}
|
||||
std::string getMusicFolder()
|
||||
{
|
||||
return PlatformFolders().getMusicFolder();
|
||||
}
|
||||
|
||||
std::string getVideoFolder() {
|
||||
return PlatformFolders().getVideoFolder();
|
||||
}
|
||||
std::string getVideoFolder()
|
||||
{
|
||||
return PlatformFolders().getVideoFolder();
|
||||
}
|
||||
|
||||
std::string getSaveGamesFolder1() {
|
||||
return PlatformFolders().getSaveGamesFolder1();
|
||||
}
|
||||
std::string getSaveGamesFolder1()
|
||||
{
|
||||
return PlatformFolders().getSaveGamesFolder1();
|
||||
}
|
||||
|
||||
std::string getSaveGamesFolder2() {
|
||||
std::string getSaveGamesFolder2()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return GetKnownWindowsFolder(FOLDERID_SavedGames, "Failed to find Saved Games folder");
|
||||
return GetKnownWindowsFolder(FOLDERID_SavedGames, "Failed to find Saved Games folder");
|
||||
#else
|
||||
return PlatformFolders().getSaveGamesFolder1();
|
||||
return PlatformFolders().getSaveGamesFolder1();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} //namespace pf
|
||||
} // namespace pf
|
||||
|
|
|
|||
Loading…
Reference in a new issue