mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
many many fixes for commercial story import, wip on transitions
This commit is contained in:
parent
879f5fbdbc
commit
6c76307f1b
20 changed files with 13528 additions and 3769 deletions
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
|
@ -104,7 +104,9 @@
|
||||||
"cfenv": "cpp",
|
"cfenv": "cpp",
|
||||||
"source_location": "cpp",
|
"source_location": "cpp",
|
||||||
"stdfloat": "cpp",
|
"stdfloat": "cpp",
|
||||||
"text_encoding": "cpp"
|
"text_encoding": "cpp",
|
||||||
|
"serializers.h": "c",
|
||||||
|
"ni_parser.h": "c"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#include "sys_lib.h"
|
#include "sys_lib.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
void SysLib::EraseString(std::string &theString, const std::string &toErase)
|
void SysLib::EraseString(std::string &theString, const std::string &toErase)
|
||||||
{
|
{
|
||||||
|
|
@ -20,6 +22,29 @@ std::string SysLib::ToUpper(const std::string &input)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SysLib::ToLower(const std::string &input)
|
||||||
|
{
|
||||||
|
std::string str = input;
|
||||||
|
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SysLib::ReadFile(const std::string &filename)
|
||||||
|
{
|
||||||
|
// Open the stream to 'lock' the file.
|
||||||
|
std::ifstream f(filename, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
// Obtain the size of the file.
|
||||||
|
const auto sz = std::filesystem::file_size(filename);
|
||||||
|
|
||||||
|
// Create a buffer.
|
||||||
|
std::string result(sz, '\0');
|
||||||
|
|
||||||
|
// Read the whole file into the buffer.
|
||||||
|
f.read(result.data(), sz);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::string SysLib::GetFileExtension(const std::string &fileName)
|
std::string SysLib::GetFileExtension(const std::string &fileName)
|
||||||
{
|
{
|
||||||
|
|
@ -52,6 +77,18 @@ std::string SysLib::GetFileName(const std::string &path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SysLib::GetDirectory(const std::string &filePath)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
std::filesystem::path absPath = std::filesystem::absolute(filePath);
|
||||||
|
std::filesystem::path dirPath = absPath.parent_path(); // Récupère le chemin sans le nom du fichier
|
||||||
|
return dirPath.string(); // Convertit le chemin en chaîne de caractères
|
||||||
|
} catch (const std::filesystem::filesystem_error& e) {
|
||||||
|
// std::cerr << "Erreur: " << e.what() << std::endl;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SysLib::ReplaceCharacter(std::string &theString, const std::string &toFind, const std::string &toReplace)
|
void SysLib::ReplaceCharacter(std::string &theString, const std::string &toFind, const std::string &toReplace)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,12 @@ public:
|
||||||
|
|
||||||
static std::string GetFileExtension(const std::string &FileName);
|
static std::string GetFileExtension(const std::string &FileName);
|
||||||
static std::string GetFileName(const std::string &path);
|
static std::string GetFileName(const std::string &path);
|
||||||
|
static std::string GetDirectory(const std::string &filePath);
|
||||||
static std::string RemoveFileExtension(const std::string &FileName);
|
static std::string RemoveFileExtension(const std::string &FileName);
|
||||||
static void ReplaceCharacter(std::string &theString, const std::string &toFind, const std::string &toReplace);
|
static void ReplaceCharacter(std::string &theString, const std::string &toFind, const std::string &toReplace);
|
||||||
static std::string Normalize(const std::string &input);
|
static std::string Normalize(const std::string &input);
|
||||||
static void EraseString(std::string &theString, const std::string &toErase);
|
static void EraseString(std::string &theString, const std::string &toErase);
|
||||||
static std::string ToUpper(const std::string &input);
|
static std::string ToUpper(const std::string &input);
|
||||||
|
static std::string ToLower(const std::string &input);
|
||||||
|
static std::string ReadFile(const std::string &filename);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,5 @@ add_library(ImGuiFileDialog STATIC
|
||||||
target_include_directories(ImGuiFileDialog PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(ImGuiFileDialog PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
target_compile_options(ImGuiFileDialog PUBLIC "-Wno-unknown-pragmas")
|
target_compile_options(ImGuiFileDialog PUBLIC -Wno-unknown-pragmas)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
1119
story-editor/libs/ImGuiFileDialog/Documentation.md
Normal file
1119
story-editor/libs/ImGuiFileDialog/Documentation.md
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -2,24 +2,39 @@
|
||||||
|
|
||||||
// uncomment and modify defines under for customize ImGuiFileDialog
|
// uncomment and modify defines under for customize ImGuiFileDialog
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
//// STL FILE SYSTEM ////////////
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
// uncomment if you need to use your FileSystem Interface
|
// uncomment if you need to use your FileSystem Interface
|
||||||
// if commented, you have two defualt interface, std::filesystem or dirent
|
// if commented, you have two defualt interface, std::filesystem or dirent
|
||||||
// #define USE_CUSTOM_FILESYSTEM
|
// #define USE_CUSTOM_FILESYSTEM
|
||||||
|
|
||||||
// this options need c++17
|
// this options need c++17
|
||||||
// #define USE_STD_FILESYSTEM
|
// #define USE_STD_FILESYSTEM
|
||||||
|
|
||||||
// #define MAX_FILE_DIALOG_NAME_BUFFER 1024
|
/////////////////////////////////
|
||||||
// #define MAX_PATH_BUFFER_SIZE 1024
|
//// MISC ///////////////////////
|
||||||
|
/////////////////////////////////
|
||||||
// the slash's buttons in path cna be used for quick select parallles directories
|
|
||||||
// #define USE_QUICK_PATH_SELECT
|
|
||||||
|
|
||||||
// the spacing between button path's can be customized.
|
// the spacing between button path's can be customized.
|
||||||
// if disabled the spacing is defined by the imgui theme
|
// if disabled the spacing is defined by the imgui theme
|
||||||
// define the space between path buttons
|
// define the space between path buttons
|
||||||
// #define CUSTOM_PATH_SPACING 2
|
// #define CUSTOM_PATH_SPACING 2
|
||||||
|
|
||||||
|
// #define MAX_FILE_DIALOG_NAME_BUFFER 1024
|
||||||
|
// #define MAX_PATH_BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
//// QUICK PATH /////////////////
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
// the slash's buttons in path cna be used for quick select parallles directories
|
||||||
|
// #define USE_QUICK_PATH_SELECT
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
//// THUMBNAILS /////////////////
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
// #define USE_THUMBNAILS
|
// #define USE_THUMBNAILS
|
||||||
// the thumbnail generation use the stb_image and stb_resize lib who need to define the implementation
|
// the thumbnail generation use the stb_image and stb_resize lib who need to define the implementation
|
||||||
// btw if you already use them in your app, you can have compiler error due to "implemntation found in double"
|
// btw if you already use them in your app, you can have compiler error due to "implemntation found in double"
|
||||||
|
|
@ -37,6 +52,10 @@
|
||||||
// #define DisplayMode_ThumbailsGrid_ButtonString "TG"
|
// #define DisplayMode_ThumbailsGrid_ButtonString "TG"
|
||||||
// #define DisplayMode_ThumbailsGrid_ButtonHelp "Thumbnails Grid"
|
// #define DisplayMode_ThumbailsGrid_ButtonHelp "Thumbnails Grid"
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
//// EXPLORATION BY KEYS ////////
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
// #define USE_EXPLORATION_BY_KEYS
|
// #define USE_EXPLORATION_BY_KEYS
|
||||||
// this mapping by default is for GLFW but you can use another
|
// this mapping by default is for GLFW but you can use another
|
||||||
// #include <GLFW/glfw3.h>
|
// #include <GLFW/glfw3.h>
|
||||||
|
|
@ -49,10 +68,24 @@
|
||||||
// BackSpace for comming back to the last directory
|
// BackSpace for comming back to the last directory
|
||||||
// #define IGFD_KEY_BACKSPACE ImGuiKey_Backspace
|
// #define IGFD_KEY_BACKSPACE ImGuiKey_Backspace
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
//// SHORTCUTS => ctrl + KEY ////
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
// #define SelectAllFilesKey ImGuiKey_A
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
//// DIALOG EXIT ////////////////
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
// by ex you can quit the dialog by pressing the key excape
|
// by ex you can quit the dialog by pressing the key excape
|
||||||
// #define USE_DIALOG_EXIT_WITH_KEY
|
// #define USE_DIALOG_EXIT_WITH_KEY
|
||||||
// #define IGFD_EXIT_KEY ImGuiKey_Escape
|
// #define IGFD_EXIT_KEY ImGuiKey_Escape
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
//// WIDGETS ////////////////////
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
// widget
|
// widget
|
||||||
// begin combo widget
|
// begin combo widget
|
||||||
// #define IMGUI_BEGIN_COMBO ImGui::BeginCombo
|
// #define IMGUI_BEGIN_COMBO ImGui::BeginCombo
|
||||||
|
|
@ -67,10 +100,14 @@
|
||||||
// standard button
|
// standard button
|
||||||
// #define IMGUI_BUTTON ImGui::Button
|
// #define IMGUI_BUTTON ImGui::Button
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
//// STRING'S ///////////////////
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
// locales string
|
// locales string
|
||||||
// #define createDirButtonString "+"
|
// #define createDirButtonString "+"
|
||||||
// #define resetButtonString "R"
|
// #define resetButtonString "R"
|
||||||
// #define drivesButtonString "Drives"
|
// #define devicesButtonString "Devices"
|
||||||
// #define editPathButtonString "E"
|
// #define editPathButtonString "E"
|
||||||
// #define searchString "Search"
|
// #define searchString "Search"
|
||||||
// #define dirEntryString "[DIR] "
|
// #define dirEntryString "[DIR] "
|
||||||
|
|
@ -79,7 +116,7 @@
|
||||||
// #define fileNameString "File Name : "
|
// #define fileNameString "File Name : "
|
||||||
// #define dirNameString "Directory Path :"
|
// #define dirNameString "Directory Path :"
|
||||||
// #define buttonResetSearchString "Reset search"
|
// #define buttonResetSearchString "Reset search"
|
||||||
// #define buttonDriveString "Drives"
|
// #define buttonDriveString "Devices"
|
||||||
// #define buttonEditPathString "Edit path\nYou can also right click on path buttons"
|
// #define buttonEditPathString "Edit path\nYou can also right click on path buttons"
|
||||||
// #define buttonResetPathString "Reset to current directory"
|
// #define buttonResetPathString "Reset to current directory"
|
||||||
// #define buttonCreateDirString "Create Directory"
|
// #define buttonCreateDirString "Create Directory"
|
||||||
|
|
@ -103,6 +140,10 @@
|
||||||
// "%Y/%m/%d %i:%M%p" give 2021:01:22 11:45PM
|
// "%Y/%m/%d %i:%M%p" give 2021:01:22 11:45PM
|
||||||
// #define DateTimeFormat "%Y/%m/%d %i:%M%p"
|
// #define DateTimeFormat "%Y/%m/%d %i:%M%p"
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
//// SORTING ICONS //////////////
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
// theses icons will appear in table headers
|
// theses icons will appear in table headers
|
||||||
// #define USE_CUSTOM_SORTING_ICON
|
// #define USE_CUSTOM_SORTING_ICON
|
||||||
// #define tableHeaderAscendingIcon "A|"
|
// #define tableHeaderAscendingIcon "A|"
|
||||||
|
|
@ -126,6 +167,10 @@
|
||||||
// #define defaultSortOrderDate true
|
// #define defaultSortOrderDate true
|
||||||
// #define defaultSortOrderThumbnails true
|
// #define defaultSortOrderThumbnails true
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
//// PLACES FEATURES ////////////
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
// #define USE_PLACES_FEATURE
|
// #define USE_PLACES_FEATURE
|
||||||
// #define PLACES_PANE_DEFAULT_SHOWN false
|
// #define PLACES_PANE_DEFAULT_SHOWN false
|
||||||
// #define placesPaneWith 150.0f
|
// #define placesPaneWith 150.0f
|
||||||
|
|
@ -137,12 +182,20 @@
|
||||||
// #define validatePlaceButtonString "ok"
|
// #define validatePlaceButtonString "ok"
|
||||||
// #define editPlaceButtonString "E"
|
// #define editPlaceButtonString "E"
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
//// PLACES FEATURES : BOOKMARKS /////
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
// a group for bookmarks will be added by default, but you can also create it yourself and many more
|
// a group for bookmarks will be added by default, but you can also create it yourself and many more
|
||||||
// #define USE_PLACES_BOOKMARKS
|
// #define USE_PLACES_BOOKMARKS
|
||||||
// #define PLACES_BOOKMARK_DEFAULT_OPEPEND true
|
// #define PLACES_BOOKMARK_DEFAULT_OPEPEND true
|
||||||
// #define placesBookmarksGroupName "Bookmarks"
|
// #define placesBookmarksGroupName "Bookmarks"
|
||||||
// #define placesBookmarksDisplayOrder 0 // to the first
|
// #define placesBookmarksDisplayOrder 0 // to the first
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
//// PLACES FEATURES : DEVICES ///////
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
// a group for system devices (returned by IFileSystem), but you can also add yours
|
// a group for system devices (returned by IFileSystem), but you can also add yours
|
||||||
// by ex if you would like to display a specific icon for some devices
|
// by ex if you would like to display a specific icon for some devices
|
||||||
// #define USE_PLACES_DEVICES
|
// #define USE_PLACES_DEVICES
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -5,46 +5,47 @@ stb
|
||||||
|
|
||||||
single-file public domain (or MIT licensed) libraries for C/C++
|
single-file public domain (or MIT licensed) libraries for C/C++
|
||||||
|
|
||||||
|
# This project discusses security-relevant bugs in public in Github Issues and Pull Requests, and it may take significant time for security fixes to be implemented or merged. If this poses an unreasonable risk to your project, do not use stb libraries.
|
||||||
|
|
||||||
Noteworthy:
|
Noteworthy:
|
||||||
|
|
||||||
* image loader: [stb_image.h](stb_image.h)
|
* image loader: [stb_image.h](stb_image.h)
|
||||||
* image writer: [stb_image_write.h](stb_image_write.h)
|
* image writer: [stb_image_write.h](stb_image_write.h)
|
||||||
* image resizer: [stb_image_resize.h](stb_image_resize.h)
|
* image resizer: [stb_image_resize2.h](stb_image_resize2.h)
|
||||||
* font text rasterizer: [stb_truetype.h](stb_truetype.h)
|
* font text rasterizer: [stb_truetype.h](stb_truetype.h)
|
||||||
* typesafe containers: [stb_ds.h](stb_ds.h)
|
* typesafe containers: [stb_ds.h](stb_ds.h)
|
||||||
|
|
||||||
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize
|
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, original stb_image_resize
|
||||||
by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts.
|
by Jorge L. "VinoBS" Rodriguez, and stb_image_resize2 and stb_sprintf by Jeff Roberts.
|
||||||
|
|
||||||
<a name="stb_libs"></a>
|
<a name="stb_libs"></a>
|
||||||
|
|
||||||
library | lastest version | category | LoC | description
|
library | lastest version | category | LoC | description
|
||||||
--------------------- | ---- | -------- | --- | --------------------------------
|
--------------------- | ---- | -------- | --- | --------------------------------
|
||||||
**[stb_vorbis.c](stb_vorbis.c)** | 1.20 | audio | 5563 | decode ogg vorbis files from file/memory to float/16-bit signed output
|
**[stb_vorbis.c](stb_vorbis.c)** | 1.22 | audio | 5584 | decode ogg vorbis files from file/memory to float/16-bit signed output
|
||||||
**[stb_image.h](stb_image.h)** | 2.26 | graphics | 7762 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
|
**[stb_hexwave.h](stb_hexwave.h)** | 0.5 | audio | 680 | audio waveform synthesizer
|
||||||
**[stb_truetype.h](stb_truetype.h)** | 1.24 | graphics | 5011 | parse, decode, and rasterize characters from truetype fonts
|
**[stb_image.h](stb_image.h)** | 2.29 | graphics | 7985 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
|
||||||
**[stb_image_write.h](stb_image_write.h)** | 1.15 | graphics | 1690 | image writing to disk: PNG, TGA, BMP
|
**[stb_truetype.h](stb_truetype.h)** | 1.26 | graphics | 5077 | parse, decode, and rasterize characters from truetype fonts
|
||||||
**[stb_image_resize.h](stb_image_resize.h)** | 0.96 | graphics | 2631 | resize images larger/smaller with good quality
|
**[stb_image_write.h](stb_image_write.h)** | 1.16 | graphics | 1724 | image writing to disk: PNG, TGA, BMP
|
||||||
**[stb_rect_pack.h](stb_rect_pack.h)** | 1.00 | graphics | 628 | simple 2D rectangle packer with decent quality
|
**[stb_image_resize2.h](stb_image_resize2.h)** | 2.04 | graphics | 10325 | resize images larger/smaller with good quality
|
||||||
**[stb_ds.h](stb_ds.h)** | 0.65 | utility | 1880 | typesafe dynamic array and hash tables for C, will compile in C++
|
**[stb_rect_pack.h](stb_rect_pack.h)** | 1.01 | graphics | 623 | simple 2D rectangle packer with decent quality
|
||||||
**[stb_sprintf.h](stb_sprintf.h)** | 1.09 | utility | 1879 | fast sprintf, snprintf for C/C++
|
**[stb_perlin.h](stb_perlin.h)** | 0.5 | graphics | 428 | perlin's revised simplex noise w/ different seeds
|
||||||
**[stretchy_buffer.h](stretchy_buffer.h)** | 1.04 | utility | 263 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++
|
**[stb_ds.h](stb_ds.h)** | 0.67 | utility | 1895 | typesafe dynamic array and hash tables for C, will compile in C++
|
||||||
**[stb_textedit.h](stb_textedit.h)** | 1.13 | user interface | 1404 | guts of a text editor for games etc implementing them from scratch
|
**[stb_sprintf.h](stb_sprintf.h)** | 1.10 | utility | 1906 | fast sprintf, snprintf for C/C++
|
||||||
|
**[stb_textedit.h](stb_textedit.h)** | 1.14 | user interface | 1429 | guts of a text editor for games etc implementing them from scratch
|
||||||
**[stb_voxel_render.h](stb_voxel_render.h)** | 0.89 | 3D graphics | 3807 | Minecraft-esque voxel rendering "engine" with many more features
|
**[stb_voxel_render.h](stb_voxel_render.h)** | 0.89 | 3D graphics | 3807 | Minecraft-esque voxel rendering "engine" with many more features
|
||||||
**[stb_dxt.h](stb_dxt.h)** | 1.10 | 3D graphics | 753 | Fabian "ryg" Giesen's real-time DXT compressor
|
**[stb_dxt.h](stb_dxt.h)** | 1.12 | 3D graphics | 719 | Fabian "ryg" Giesen's real-time DXT compressor
|
||||||
**[stb_perlin.h](stb_perlin.h)** | 0.5 | 3D graphics | 428 | revised Perlin noise (3D input, 1D output)
|
|
||||||
**[stb_easy_font.h](stb_easy_font.h)** | 1.1 | 3D graphics | 305 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
|
**[stb_easy_font.h](stb_easy_font.h)** | 1.1 | 3D graphics | 305 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
|
||||||
**[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.41 | game dev | 4161 | embeddable tilemap editor
|
**[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.42 | game dev | 4187 | embeddable tilemap editor
|
||||||
**[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.7 | game dev | 1221 | herringbone Wang tile map generator
|
**[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.7 | game dev | 1221 | herringbone Wang tile map generator
|
||||||
**[stb_c_lexer.h](stb_c_lexer.h)** | 0.11 | parsing | 966 | simplify writing parsers for C-like languages
|
**[stb_c_lexer.h](stb_c_lexer.h)** | 0.12 | parsing | 940 | simplify writing parsers for C-like languages
|
||||||
**[stb_divide.h](stb_divide.h)** | 0.93 | math | 430 | more useful 32-bit modulus e.g. "euclidean divide"
|
**[stb_divide.h](stb_divide.h)** | 0.94 | math | 433 | more useful 32-bit modulus e.g. "euclidean divide"
|
||||||
**[stb_connected_comp...](stb_connected_components.h)** | 0.96 | misc | 1049 | incrementally compute reachability on grids
|
**[stb_connected_comp...](stb_connected_components.h)** | 0.96 | misc | 1049 | incrementally compute reachability on grids
|
||||||
**[stb.h](stb.h)** | 2.37 | misc | 14454 | helper functions for C, mostly redundant in C++; basically author's personal stuff
|
|
||||||
**[stb_leakcheck.h](stb_leakcheck.h)** | 0.6 | misc | 194 | quick-and-dirty malloc/free leak-checking
|
**[stb_leakcheck.h](stb_leakcheck.h)** | 0.6 | misc | 194 | quick-and-dirty malloc/free leak-checking
|
||||||
**[stb_include.h](stb_include.h)** | 0.02 | misc | 295 | implement recursive #include support, particularly for GLSL
|
**[stb_include.h](stb_include.h)** | 0.02 | misc | 295 | implement recursive #include support, particularly for GLSL
|
||||||
|
|
||||||
Total libraries: 22
|
Total libraries: 21
|
||||||
Total lines of C code: 56774
|
Total lines of C code: 50806
|
||||||
|
|
||||||
|
|
||||||
FAQ
|
FAQ
|
||||||
|
|
@ -60,6 +61,24 @@ They are also licensed under the MIT open source license, if you have lawyers
|
||||||
who are unhappy with public domain. Every source file includes an explicit
|
who are unhappy with public domain. Every source file includes an explicit
|
||||||
dual-license for you to choose from.
|
dual-license for you to choose from.
|
||||||
|
|
||||||
|
#### How do I use these libraries?
|
||||||
|
|
||||||
|
The idea behind single-header file libraries is that they're easy to distribute and deploy
|
||||||
|
because all the code is contained in a single file. By default, the .h files in here act as
|
||||||
|
their own header files, i.e. they declare the functions contained in the file but don't
|
||||||
|
actually result in any code getting compiled.
|
||||||
|
|
||||||
|
So in addition, you should select _exactly one_ C/C++ source file that actually instantiates
|
||||||
|
the code, preferably a file you're not editing frequently. This file should define a
|
||||||
|
specific macro (this is documented per-library) to actually enable the function definitions.
|
||||||
|
For example, to use stb_image, you should have exactly one C/C++ file that doesn't
|
||||||
|
include stb_image.h regularly, but instead does
|
||||||
|
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
|
The right macro to define is pointed out right at the top of each of these libraries.
|
||||||
|
|
||||||
#### <a name="other_libs"></a> Are there other single-file public-domain/open source libraries with minimal dependencies out there?
|
#### <a name="other_libs"></a> Are there other single-file public-domain/open source libraries with minimal dependencies out there?
|
||||||
|
|
||||||
[Yes.](https://github.com/nothings/single_file_libs)
|
[Yes.](https://github.com/nothings/single_file_libs)
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
10270
story-editor/libs/ImGuiFileDialog/stb/stb_image_resize2.h
Normal file
10270
story-editor/libs/ImGuiFileDialog/stb/stb_image_resize2.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -37,6 +37,7 @@ your use of the corresponding standard functions.
|
||||||
#include "IconsMaterialDesignIcons.h"
|
#include "IconsMaterialDesignIcons.h"
|
||||||
#include "IconsFontAwesome5_c.h"
|
#include "IconsFontAwesome5_c.h"
|
||||||
|
|
||||||
|
#include "serializers.h"
|
||||||
|
|
||||||
static void glfw_error_callback(int error, const char* description)
|
static void glfw_error_callback(int error, const char* description)
|
||||||
{
|
{
|
||||||
|
|
@ -48,42 +49,313 @@ static SDL_Renderer* renderer{nullptr};
|
||||||
|
|
||||||
|
|
||||||
#include "stb_image.h"
|
#include "stb_image.h"
|
||||||
|
#include "sys_lib.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t type; /* Magic identifier */
|
||||||
|
uint32_t size; /* File size in bytes */
|
||||||
|
uint16_t reserved1;
|
||||||
|
uint16_t reserved2;
|
||||||
|
uint32_t offset; /* Offset to image data, bytes */
|
||||||
|
} bmp_header_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t size; /* Header size in bytes */
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height; /* Width and height of image */
|
||||||
|
uint16_t planes; /* Number of colour planes */
|
||||||
|
uint16_t bits; /* Bits per pixel */
|
||||||
|
uint32_t compression; /* Compression type */
|
||||||
|
uint32_t imagesize; /* Image size in bytes */
|
||||||
|
uint32_t xresolution;
|
||||||
|
uint32_t yresolution; /* Pixels per meter */
|
||||||
|
uint32_t ncolours; /* Number of colours */
|
||||||
|
uint32_t importantcolours; /* Important colours */
|
||||||
|
uint32_t rgb;
|
||||||
|
uint32_t rgb2;
|
||||||
|
} bmp_infoheader_t;
|
||||||
|
|
||||||
|
static const uint32_t HEADER_SIZE = 14;
|
||||||
|
static const uint32_t INFO_HEADER_SIZE = 40;
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t parse_bmp(const uint8_t *data, bmp_header_t *header, bmp_infoheader_t *info_header)
|
||||||
|
{
|
||||||
|
uint8_t isBmp = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Header is 14 bytes length
|
||||||
|
isBmp = (data[0] == 'B') && (data[1] == 'M') ? 1 : 0;
|
||||||
|
header->size = leu32_get(data + 2);
|
||||||
|
header->offset = leu32_get(data + 10);
|
||||||
|
|
||||||
|
isBmp = isBmp & 1;
|
||||||
|
info_header->size = leu32_get(data + HEADER_SIZE);
|
||||||
|
info_header->width = leu32_get(data + HEADER_SIZE + 4);
|
||||||
|
info_header->height = leu32_get(data + HEADER_SIZE + 8);
|
||||||
|
info_header->planes = leu16_get(data + HEADER_SIZE + 12);
|
||||||
|
info_header->bits = leu16_get(data + HEADER_SIZE + 14);
|
||||||
|
info_header->compression = leu32_get(data + HEADER_SIZE + 16);
|
||||||
|
info_header->imagesize = leu32_get(data + HEADER_SIZE + 20);
|
||||||
|
info_header->xresolution = leu32_get(data + HEADER_SIZE + 24);
|
||||||
|
info_header->yresolution = leu32_get(data + HEADER_SIZE + 28);
|
||||||
|
info_header->ncolours = leu32_get(data + HEADER_SIZE + 32);
|
||||||
|
info_header->importantcolours = leu32_get(data + HEADER_SIZE + 36);
|
||||||
|
info_header->rgb = leu32_get(data + HEADER_SIZE + 40);
|
||||||
|
info_header->rgb2 = leu32_get(data + HEADER_SIZE + 44);
|
||||||
|
|
||||||
|
return isBmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Code de décompression
|
||||||
|
void Decompress(uint8_t *bmpImage, uint32_t fileSize, SDL_Texture *texture)
|
||||||
|
{
|
||||||
|
uint32_t width = 320;
|
||||||
|
uint32_t height = 240;
|
||||||
|
|
||||||
|
bmp_header_t header;
|
||||||
|
bmp_infoheader_t info_header;
|
||||||
|
parse_bmp(bmpImage, &header, &info_header);
|
||||||
|
|
||||||
|
uint8_t *compressed = &bmpImage[header.offset];
|
||||||
|
uint32_t compressedSize = fileSize - header.offset;
|
||||||
|
|
||||||
|
uint32_t paletteSize = header.offset - (HEADER_SIZE + INFO_HEADER_SIZE);
|
||||||
|
|
||||||
|
printf("File size (from header):%d\r\n", (uint32_t)header.size);
|
||||||
|
printf("File size (from data):%d\r\n", (uint32_t)fileSize);
|
||||||
|
printf("Data offset:%d\r\n", (uint32_t)header.offset);
|
||||||
|
printf("Image size:%d\r\n", (uint32_t)info_header.size);
|
||||||
|
printf("width:%d\r\n", (uint32_t)info_header.width);
|
||||||
|
printf("height:%d\r\n", (uint32_t)info_header.height);
|
||||||
|
printf("Planes:%d\r\n", (uint32_t)info_header.planes);
|
||||||
|
printf("Bits:%d\r\n", (uint32_t)info_header.bits);
|
||||||
|
printf("Compression:%d\r\n", (uint32_t)info_header.compression); // 2 - 4 bit run length encoding
|
||||||
|
printf("Image size:%d\r\n", (uint32_t)info_header.imagesize);
|
||||||
|
printf("X resolution:%d\r\n", (uint32_t)info_header.xresolution);
|
||||||
|
printf("Y resolution:%d\r\n", (uint32_t)info_header.yresolution);
|
||||||
|
printf("Colors:%d\r\n", (uint32_t)info_header.ncolours);
|
||||||
|
printf("Important colors:%d\r\n", (uint32_t)info_header.importantcolours);
|
||||||
|
printf("RGB :%d\r\n", (uint32_t)info_header.rgb);
|
||||||
|
printf("RGB2 :%d\r\n", (uint32_t)info_header.rgb2);
|
||||||
|
|
||||||
|
uint8_t *palette = &bmpImage[HEADER_SIZE + INFO_HEADER_SIZE]; // 16 * 4 bytes = 64
|
||||||
|
|
||||||
|
// buffer de sortie, bitmap décompressé
|
||||||
|
uint8_t decompressed[320 * 240];
|
||||||
|
memset(decompressed, 0, 320*240);
|
||||||
|
|
||||||
|
// btea((uint32_t*) bmpImage, -128, key);
|
||||||
|
|
||||||
|
uint32_t pixel = 0; // specify the pixel offset
|
||||||
|
uint32_t i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
uint8_t rleCmd = compressed[i];
|
||||||
|
if (rleCmd > 0)
|
||||||
|
{
|
||||||
|
uint8_t val = compressed[i + 1];
|
||||||
|
// repeat number of pixels
|
||||||
|
for (uint32_t j = 0; j < rleCmd; j++)
|
||||||
|
{
|
||||||
|
if ((j & 1) == 0)
|
||||||
|
{
|
||||||
|
decompressed[pixel] = (val & 0xF0) >>4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
decompressed[pixel] = (val & 0x0F);
|
||||||
|
}
|
||||||
|
pixel++;
|
||||||
|
}
|
||||||
|
i += 2; // jump pair instruction
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint8_t second = compressed[i + 1];
|
||||||
|
if (second == 0)
|
||||||
|
{
|
||||||
|
if (pixel % width)
|
||||||
|
{
|
||||||
|
// end of line
|
||||||
|
uint32_t lines = pixel / width;
|
||||||
|
uint32_t remaining = width - (pixel - (lines * width));
|
||||||
|
|
||||||
|
pixel += remaining;
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
else if (second == 1)
|
||||||
|
{
|
||||||
|
std::cout << "End of bitmap" << std::endl;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
else if (second == 2)
|
||||||
|
{
|
||||||
|
// delta N pixels and M lines
|
||||||
|
pixel += compressed[i + 2] + compressed[i + 3] * width;
|
||||||
|
i += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// absolute mode
|
||||||
|
uint8_t *ptr = &compressed[i + 2];
|
||||||
|
// repeat number of pixels
|
||||||
|
for (uint32_t j = 0; j < second; j++)
|
||||||
|
{
|
||||||
|
if ((j & 1) == 0)
|
||||||
|
{
|
||||||
|
decompressed[pixel] = (*ptr & 0xF0) >> 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
decompressed[pixel] = (*ptr & 0x0F);
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
pixel++;
|
||||||
|
}
|
||||||
|
i += 2 + (second / 2);
|
||||||
|
|
||||||
|
// padded in word boundary, jump if necessary
|
||||||
|
if ((second / 2) % 2)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pixel > (width * height))
|
||||||
|
{
|
||||||
|
std::cout << "Error!" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while( i < compressedSize);
|
||||||
|
|
||||||
|
end:
|
||||||
|
void *pixels;
|
||||||
|
int pitch;
|
||||||
|
SDL_LockTexture(texture, NULL, &pixels, &pitch);
|
||||||
|
|
||||||
|
// Définir la texture comme cible de rendu
|
||||||
|
SDL_SetRenderTarget(renderer, texture);
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t x = 0, y = 0;
|
||||||
|
for (uint32_t i = 0; i < pixel; i++)
|
||||||
|
{
|
||||||
|
uint8_t val = decompressed[i];
|
||||||
|
if (val > 15)
|
||||||
|
{
|
||||||
|
std::cout << "Error!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *palettePtr = &palette[val * 4];
|
||||||
|
// Définir la couleur de rendu
|
||||||
|
SDL_SetRenderDrawColor(renderer, palettePtr[0], palettePtr[1], palettePtr[2], 255);
|
||||||
|
|
||||||
|
int flippedY = (height - 1) - y;
|
||||||
|
// Dessiner un point à la position (x, y)
|
||||||
|
SDL_RenderPoint(renderer, x, flippedY);
|
||||||
|
|
||||||
|
x++;
|
||||||
|
if (x >= width)
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetRenderTarget(renderer, NULL);
|
||||||
|
SDL_UnlockTexture(texture);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// std::ofstream outfile ("new.txt", std::ofstream::binary);
|
||||||
|
// outfile.write (reinterpret_cast<const char *>(decompressed), pixel / 2 );
|
||||||
|
// outfile.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Simple helper function to load an image into a OpenGL texture with common settings
|
// Simple helper function to load an image into a OpenGL texture with common settings
|
||||||
bool LoadTextureFromFile(const char* filename, Gui::Image &img)
|
bool LoadTextureFromFile(const char* filename, Gui::Image &img)
|
||||||
{
|
{
|
||||||
|
|
||||||
SDL_Surface *surface, *temp;
|
SDL_Surface *surface, *temp;
|
||||||
|
bool useSdlImage = true;
|
||||||
|
|
||||||
surface = IMG_Load(filename);
|
if (SysLib::GetFileExtension(filename) == "bmp")
|
||||||
if (!surface) {
|
{
|
||||||
SDL_Log("Couldn't load %s: %s\n", filename, SDL_GetError());
|
// BMP
|
||||||
|
bmp_header_t header;
|
||||||
|
bmp_infoheader_t info_header;
|
||||||
|
uint8_t *data = nullptr;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
|
||||||
|
FILE *fil;
|
||||||
|
uint32_t offset;
|
||||||
|
fil = fopen(filename, "r");
|
||||||
|
|
||||||
|
// Lire tout le ficher
|
||||||
|
fseek(fil, 0, SEEK_END);
|
||||||
|
size = ftell(fil);
|
||||||
|
fseek(fil, 0, SEEK_SET);
|
||||||
|
|
||||||
|
uint8_t *bmpImage = (uint8_t *)malloc(size);
|
||||||
|
fread(bmpImage, 1, size, fil);
|
||||||
|
|
||||||
|
parse_bmp(bmpImage, &header, &info_header);
|
||||||
|
|
||||||
|
if (info_header.bits == 4)
|
||||||
|
{
|
||||||
|
auto tex = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, info_header.width, info_header.height);
|
||||||
|
Decompress(bmpImage, size, tex);
|
||||||
|
useSdlImage = false;
|
||||||
|
|
||||||
|
img.texture = tex;
|
||||||
|
img.w = info_header.width;
|
||||||
|
img.h = info_header.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(bmpImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useSdlImage)
|
||||||
|
{
|
||||||
|
|
||||||
|
surface = IMG_Load(filename);
|
||||||
|
if (!surface)
|
||||||
|
{
|
||||||
|
SDL_Log("Couldn't load %s: %s\n", filename, SDL_GetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use the tonemap operator to convert to SDR output */
|
||||||
|
// const char *tonemap = NULL;
|
||||||
|
// SDL_SetStringProperty(SDL_GetSurfaceProperties(surface), SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING, tonemap);
|
||||||
|
temp = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA32);
|
||||||
|
SDL_DestroySurface(surface);
|
||||||
|
if (!temp)
|
||||||
|
{
|
||||||
|
SDL_Log("Couldn't convert surface: %s\n", SDL_GetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.texture = SDL_CreateTextureFromSurface(renderer, temp);
|
||||||
|
SDL_DestroySurface(temp);
|
||||||
|
if (!img.texture) {
|
||||||
|
SDL_Log("Couldn't create texture: %s\n", SDL_GetError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use the tonemap operator to convert to SDR output */
|
float w, h = 0;
|
||||||
const char *tonemap = NULL;
|
SDL_GetTextureSize(static_cast<SDL_Texture*>(img.texture), &w, &h);
|
||||||
SDL_SetStringProperty(SDL_GetSurfaceProperties(surface), SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING, tonemap);
|
img.w = (int)w;
|
||||||
temp = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA32);
|
img.h = (int)h;
|
||||||
SDL_DestroySurface(surface);
|
|
||||||
if (!temp) {
|
|
||||||
SDL_Log("Couldn't convert surface: %s\n", SDL_GetError());
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
img.texture = SDL_CreateTextureFromSurface(renderer, temp);
|
|
||||||
SDL_DestroySurface(temp);
|
|
||||||
if (!img.texture) {
|
|
||||||
SDL_Log("Couldn't create texture: %s\n", SDL_GetError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
float w, h = 0;
|
|
||||||
SDL_GetTextureSize(static_cast<SDL_Texture*>(img.texture), &w, &h);
|
|
||||||
img.w = (int)w;
|
|
||||||
img.h = (int)h;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,14 @@
|
||||||
#define MAX_NB_NODES 1000
|
#define MAX_NB_NODES 1000
|
||||||
static ni_node_t gNodes[MAX_NB_NODES];
|
static ni_node_t gNodes[MAX_NB_NODES];
|
||||||
|
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
uint32_t ri_size;
|
uint32_t ri_size;
|
||||||
uint32_t si_size;
|
uint32_t si_size;
|
||||||
uint32_t li_size;
|
uint32_t li_size;
|
||||||
uint8_t gRiBlock[512];
|
uint8_t gRiBlock[XI_BLOCK_SIZE];
|
||||||
uint8_t gSiBlock[512];
|
uint8_t gSiBlock[XI_BLOCK_SIZE];
|
||||||
uint8_t gLiBlock[512];
|
uint8_t gLiBlock[XI_BLOCK_SIZE];
|
||||||
} pack;
|
} pack;
|
||||||
|
|
||||||
#define DELTA 0x9e3779b9
|
#define DELTA 0x9e3779b9
|
||||||
|
|
@ -42,15 +43,6 @@ static void btea_decode(uint32_t *v, uint32_t n, const uint32_t *key)
|
||||||
|
|
||||||
static const uint32_t key[4] = {0x91bd7a0a, 0xa75440a9, 0xbbd49d6c, 0xe0dcc0e3};
|
static const uint32_t key[4] = {0x91bd7a0a, 0xa75440a9, 0xbbd49d6c, 0xe0dcc0e3};
|
||||||
|
|
||||||
|
|
||||||
void ni_set_ri_block(const uint8_t *data, uint32_t size)
|
|
||||||
{
|
|
||||||
memcpy(pack.gRiBlock, data, size);
|
|
||||||
pack.ri_size = size;
|
|
||||||
uint32_t n = size / 4;
|
|
||||||
btea_decode((uint32_t*)pack.gRiBlock, n, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ni_get_ri_block(uint8_t *data)
|
uint32_t ni_get_ri_block(uint8_t *data)
|
||||||
{
|
{
|
||||||
memcpy(data, pack.gRiBlock, pack.ri_size);
|
memcpy(data, pack.gRiBlock, pack.ri_size);
|
||||||
|
|
@ -69,20 +61,38 @@ uint32_t ni_get_li_block(uint8_t *data)
|
||||||
return pack.li_size;
|
return pack.li_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ni_set_ri_block(const uint8_t *data, uint32_t size)
|
||||||
|
{
|
||||||
|
memcpy(pack.gRiBlock, data, size);
|
||||||
|
pack.ri_size = size;
|
||||||
|
ni_decode_block(pack.gRiBlock, size);
|
||||||
|
}
|
||||||
|
|
||||||
void ni_set_si_block(const uint8_t *data, uint32_t size)
|
void ni_set_si_block(const uint8_t *data, uint32_t size)
|
||||||
{
|
{
|
||||||
memcpy(pack.gSiBlock, data, size);
|
memcpy(pack.gSiBlock, data, size);
|
||||||
pack.si_size = size;
|
pack.si_size = size;
|
||||||
uint32_t n = size / 4;
|
ni_decode_block(pack.gSiBlock, size);
|
||||||
btea_decode((uint32_t*)pack.gSiBlock, n, key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ni_set_li_block(const uint8_t *data, uint32_t size)
|
void ni_set_li_block(const uint8_t *data, uint32_t size)
|
||||||
{
|
{
|
||||||
memcpy(pack.gLiBlock, data, size);
|
memcpy(pack.gLiBlock, data, size);
|
||||||
pack.li_size = size;
|
pack.li_size = size;
|
||||||
uint32_t n = size / 4;
|
ni_decode_block(pack.gLiBlock, size);
|
||||||
btea_decode((uint32_t*) pack.gLiBlock, n, key);
|
}
|
||||||
|
|
||||||
|
void ni_decode_block(uint8_t *data, uint32_t size)
|
||||||
|
{
|
||||||
|
if (size < 512)
|
||||||
|
{
|
||||||
|
uint32_t n = size / 4;
|
||||||
|
btea_decode((uint32_t*) data, n, key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
btea_decode((uint32_t*) data, 128, key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ni_decode_block512(uint8_t *data)
|
void ni_decode_block512(uint8_t *data)
|
||||||
|
|
@ -115,14 +125,22 @@ bool ni_get_node_info(uint32_t index, node_info_t *node)
|
||||||
{
|
{
|
||||||
node->current = &gNodes[index];
|
node->current = &gNodes[index];
|
||||||
// Copy sound file name
|
// Copy sound file name
|
||||||
uint32_t offset = node->current->sound_asset_index_in_si * 12;
|
if (node->current->sound_asset_index_in_si != 0xFFFFFFFF)
|
||||||
memcpy(node->si_file, &pack.gSiBlock[offset], 12);
|
{
|
||||||
node->si_file[12] = '\0';
|
uint32_t offset = node->current->sound_asset_index_in_si * 12;
|
||||||
|
memcpy(node->si_file, &pack.gSiBlock[offset], 12);
|
||||||
|
node->si_file[12] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// pas de son pour ce noeud
|
||||||
|
node->si_file[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
// Copy image file name
|
// Copy image file name
|
||||||
if (node->current->image_asset_index_in_ri != 0xFFFFFFFF)
|
if (node->current->image_asset_index_in_ri != 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
offset = node->current->image_asset_index_in_ri * 12;
|
uint32_t offset = node->current->image_asset_index_in_ri * 12;
|
||||||
memcpy(node->ri_file, &pack.gRiBlock[offset], 12);
|
memcpy(node->ri_file, &pack.gRiBlock[offset], 12);
|
||||||
node->ri_file[12] = '\0';
|
node->ri_file[12] = '\0';
|
||||||
}
|
}
|
||||||
|
|
@ -168,11 +186,11 @@ void ni_parse_nodes(ni_file_t *ni_file, const uint8_t *data)
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
n->sound_asset_index_in_si = leu32_get(ptr);
|
n->sound_asset_index_in_si = leu32_get(ptr);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
n->ok_transition_action_node_index_in_li = leu32_get(ptr);
|
n->ok_btn_node_idx_in_li = leu32_get(ptr);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
n->ok_transition_number_of_options = leu32_get(ptr);
|
n->ok_btn_size_or_base_idx = leu32_get(ptr);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
n->ok_transition_selected_option_index = leu32_get(ptr);
|
n->ok_btn_offset_from_base = leu32_get(ptr);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
n->home_transition_action_node_index_in_li = leu32_get(ptr);
|
n->home_transition_action_node_index_in_li = leu32_get(ptr);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,15 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define XI_BLOCK_SIZE (8*1024)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t image_asset_index_in_ri;
|
uint32_t image_asset_index_in_ri;
|
||||||
uint32_t sound_asset_index_in_si;
|
uint32_t sound_asset_index_in_si;
|
||||||
uint32_t ok_transition_action_node_index_in_li;
|
uint32_t ok_btn_node_idx_in_li;
|
||||||
uint32_t ok_transition_number_of_options;
|
uint32_t ok_btn_size_or_base_idx;
|
||||||
uint32_t ok_transition_selected_option_index;
|
uint32_t ok_btn_offset_from_base;
|
||||||
uint32_t home_transition_action_node_index_in_li;
|
uint32_t home_transition_action_node_index_in_li;
|
||||||
uint32_t home_transition_number_of_options;
|
uint32_t home_transition_number_of_options;
|
||||||
uint32_t home_transition_selected_option_index;
|
uint32_t home_transition_selected_option_index;
|
||||||
|
|
@ -47,7 +50,12 @@ typedef struct
|
||||||
uint32_t ni_get_number_of_images();
|
uint32_t ni_get_number_of_images();
|
||||||
void ni_get_image(char buffer[13], uint32_t index);
|
void ni_get_image(char buffer[13], uint32_t index);
|
||||||
uint32_t ni_get_node_index_in_li(uint32_t index_in_li, uint32_t selected);
|
uint32_t ni_get_node_index_in_li(uint32_t index_in_li, uint32_t selected);
|
||||||
|
|
||||||
|
// Block size at least 512 bytes be careful
|
||||||
void ni_decode_block512(uint8_t *data);
|
void ni_decode_block512(uint8_t *data);
|
||||||
|
|
||||||
|
// block of any size
|
||||||
|
void ni_decode_block(uint8_t *data, uint32_t size);
|
||||||
bool ni_get_node_info(uint32_t index, node_info_t *node);
|
bool ni_get_node_info(uint32_t index, node_info_t *node);
|
||||||
|
|
||||||
bool ni_parser(ni_file_t *ni_file, const uint8_t *data);
|
bool ni_parser(ni_file_t *ni_file, const uint8_t *data);
|
||||||
|
|
|
||||||
|
|
@ -21,21 +21,6 @@ PackArchive::PackArchive(ILogger &log)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> PackArchive::GetImages()
|
|
||||||
{
|
|
||||||
std::vector<std::string> imgList;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < ni_get_number_of_images(); i++)
|
|
||||||
{
|
|
||||||
char buffer[13];
|
|
||||||
ni_get_image(buffer, i);
|
|
||||||
imgList.push_back(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return imgList;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PackArchive::Unzip(const std::string &filePath, const std::string &parent_dest_dir)
|
void PackArchive::Unzip(const std::string &filePath, const std::string &parent_dest_dir)
|
||||||
{
|
{
|
||||||
// std::string fileName = GetFileName(filePath);
|
// std::string fileName = GetFileName(filePath);
|
||||||
|
|
@ -63,10 +48,6 @@ void PackArchive::Unzip(const std::string &filePath, const std::string &parent_d
|
||||||
(void) Zip::Unzip(filePath, parent_dest_dir, "");
|
(void) Zip::Unzip(filePath, parent_dest_dir, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool endsWith(const std::string& str, const std::string& suffix)
|
|
||||||
{
|
|
||||||
return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StringToFile(const std::string &filePath, const std::string &data)
|
bool StringToFile(const std::string &filePath, const std::string &data)
|
||||||
{
|
{
|
||||||
|
|
@ -154,12 +135,12 @@ std::vector<std::string> PackArchive::FilesInMemory(const std::string &type, con
|
||||||
return resList;
|
return resList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackArchive::ConvertCommercialFormat(StoryProject &proj, const std::string &basePath)
|
void PackArchive::ConvertCommercialFormat(StoryProject &proj, const std::filesystem::path &importBaseDir)
|
||||||
{
|
{
|
||||||
ResourceManager res(m_log);
|
ResourceManager res(m_log);
|
||||||
|
|
||||||
// RI file is not ciphered
|
// RI file is not ciphered
|
||||||
uint8_t data[512];
|
uint8_t data[XI_BLOCK_SIZE];
|
||||||
uint32_t size = ni_get_ri_block(data);
|
uint32_t size = ni_get_ri_block(data);
|
||||||
|
|
||||||
auto page = proj.GetPage(proj.MainUuid());
|
auto page = proj.GetPage(proj.MainUuid());
|
||||||
|
|
@ -175,7 +156,7 @@ void PackArchive::ConvertCommercialFormat(StoryProject &proj, const std::string
|
||||||
auto rData = std::make_shared<Resource>();
|
auto rData = std::make_shared<Resource>();
|
||||||
|
|
||||||
// origin
|
// origin
|
||||||
auto from = std::filesystem::path(basePath) / mPackName / "rf" / l;
|
auto from = importBaseDir / "rf" / l;
|
||||||
from += ".bmp";
|
from += ".bmp";
|
||||||
|
|
||||||
// destination
|
// destination
|
||||||
|
|
@ -183,8 +164,8 @@ void PackArchive::ConvertCommercialFormat(StoryProject &proj, const std::string
|
||||||
auto to = proj.AssetsPath() / filename;
|
auto to = proj.AssetsPath() / filename;
|
||||||
|
|
||||||
rData->file = filename;
|
rData->file = filename;
|
||||||
rData->type = ResourceManager::ExtentionInfo(rData->file, ResourceManager::InfoType);
|
rData->type = ResourceManager::ExtentionInfo(".bmp", ResourceManager::InfoType);
|
||||||
rData->format = ResourceManager::ExtentionInfo(rData->file, ResourceManager::InfoFormat);
|
rData->format = ResourceManager::ExtentionInfo(".bmp", ResourceManager::InfoFormat);
|
||||||
res.Add(rData);
|
res.Add(rData);
|
||||||
|
|
||||||
std::filesystem::copy(from, to, std::filesystem::copy_options::overwrite_existing);
|
std::filesystem::copy(from, to, std::filesystem::copy_options::overwrite_existing);
|
||||||
|
|
@ -202,7 +183,7 @@ void PackArchive::ConvertCommercialFormat(StoryProject &proj, const std::string
|
||||||
auto rData = std::make_shared<Resource>();
|
auto rData = std::make_shared<Resource>();
|
||||||
|
|
||||||
// origin
|
// origin
|
||||||
auto from = std::filesystem::path(basePath) / mPackName / "sf" / l;
|
auto from = importBaseDir / "sf" / l;
|
||||||
from += ".mp3";
|
from += ".mp3";
|
||||||
|
|
||||||
// destination
|
// destination
|
||||||
|
|
@ -210,8 +191,8 @@ void PackArchive::ConvertCommercialFormat(StoryProject &proj, const std::string
|
||||||
auto to = proj.AssetsPath() / filename;
|
auto to = proj.AssetsPath() / filename;
|
||||||
|
|
||||||
rData->file = filename;
|
rData->file = filename;
|
||||||
rData->type = ResourceManager::ExtentionInfo(rData->file, ResourceManager::InfoType);
|
rData->type = ResourceManager::ExtentionInfo(".mp3", ResourceManager::InfoType);
|
||||||
rData->format = ResourceManager::ExtentionInfo(rData->file, ResourceManager::InfoFormat);
|
rData->format = ResourceManager::ExtentionInfo(".mp3", ResourceManager::InfoFormat);
|
||||||
res.Add(rData);
|
res.Add(rData);
|
||||||
|
|
||||||
std::filesystem::copy(from, to, std::filesystem::copy_options::overwrite_existing);
|
std::filesystem::copy(from, to, std::filesystem::copy_options::overwrite_existing);
|
||||||
|
|
@ -233,8 +214,13 @@ void PackArchive::ConvertCommercialFormat(StoryProject &proj, const std::string
|
||||||
// key: node index, value: node uuidV4
|
// key: node index, value: node uuidV4
|
||||||
std::map<int, std::string> nodeIds;
|
std::map<int, std::string> nodeIds;
|
||||||
|
|
||||||
// key: node index, value: list of transitions
|
// key: index in transition table
|
||||||
std::map<int, std::vector<uint32_t>> nodeTransitions;
|
// value: list of node ids in desination
|
||||||
|
std::map<int, std::vector<int>> referencedIndexes;
|
||||||
|
|
||||||
|
// Direct nodes (no choices)
|
||||||
|
// key: nodeID source, value: nodeID destination
|
||||||
|
std::map<int, int> nodeLinks;
|
||||||
|
|
||||||
for (int i = 0; i < mNiFile.node_size; i++)
|
for (int i = 0; i < mNiFile.node_size; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -255,33 +241,51 @@ void PackArchive::ConvertCommercialFormat(StoryProject &proj, const std::string
|
||||||
internalData["image"] = img.size() > 0 ? img + ".bmp" : "";
|
internalData["image"] = img.size() > 0 ? img + ".bmp" : "";
|
||||||
internalData["sound"] = snd.size() > 0 ? snd + ".mp3" : "";
|
internalData["sound"] = snd.size() > 0 ? snd + ".mp3" : "";
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << i << "\t==> Node\t" << img << "\t" << snd << std::endl;
|
||||||
|
std::cout << "\tOK node index in LI\t" << node_info.current->ok_btn_node_idx_in_li << std::endl;
|
||||||
|
std::cout << "\tOK number of options\t" << node_info.current->ok_btn_size_or_base_idx << std::endl;
|
||||||
|
std::cout << "\tOK selected option index\t" << node_info.current->ok_btn_offset_from_base << std::endl;
|
||||||
|
|
||||||
node->SetInternalData(internalData);
|
node->SetInternalData(internalData);
|
||||||
|
|
||||||
std::vector<uint32_t> jumpArray;
|
std::vector<uint32_t> jumpArray;
|
||||||
|
|
||||||
|
|
||||||
// Autre cas
|
|
||||||
if (node_info.current->ok_transition_number_of_options == 10)
|
|
||||||
|
if (node_info.current->wheel)
|
||||||
{
|
{
|
||||||
// For now, consider that this is a bad format
|
/*
|
||||||
// In the future, consider using ok_transition_selected_option_index when ok_transition_number_of_options == 10
|
Exemple d'un noeud de choix (wheel == true) avec trois noeuds :
|
||||||
|
node number 13 17 21
|
||||||
|
ok_btn_node_idx_in_li 36 36 36
|
||||||
|
ok_btn_size_or_base_idx 18 18 18
|
||||||
|
ok_btn_offset_from_base 0 2 4
|
||||||
|
|
||||||
// 00 00 00 00 ==> ok transition à zéro
|
Dans ce cas:
|
||||||
// 0A 00 00 00 ==> nombre spécial, ou vraiment l'offset dans le fichier LI ?
|
- le 18 est l'index de base où sont situés les 3 choix
|
||||||
// 01 00 00 00 ==> l'index dans le fichier LI à l'offset (disons, le premier élément)
|
- 36+0 est l'index où aller lors de l'appui sur OK pour le noeud 13
|
||||||
|
- 36+2 est l'index où aller lors de l'appui sur OK pour le noeud 17
|
||||||
|
- 36+4 est l'index où aller lors de l'appui sur OK pour le noeud 21
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// On ajouter ce noeud à la liste des références
|
||||||
jumpArray.push_back(transitions[node_info.current->ok_transition_action_node_index_in_li]);
|
// dans ce cas, le champs ok_btn_size_or_base_idx est interprété en tant que index
|
||||||
|
referencedIndexes[node_info.current->ok_btn_size_or_base_idx].push_back(i);
|
||||||
|
|
||||||
|
// On va créer le lien entre notre noeud et le noeud indiqué dans la table de transition
|
||||||
|
nodeLinks[i] = transitions[node_info.current->ok_btn_size_or_base_idx + node_info.current->ok_btn_offset_from_base];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Vraies transitions
|
/*
|
||||||
for (int jIndex = 0; jIndex < node_info.current->ok_transition_number_of_options; jIndex++)
|
ici, pas de wheel de sélection, donc c'est un son joué et un lien direct
|
||||||
{
|
*/
|
||||||
jumpArray.push_back(transitions[node_info.current->ok_transition_action_node_index_in_li + jIndex]);
|
nodeLinks[i] = transitions[node_info.current->ok_btn_size_or_base_idx + node_info.current->ok_btn_offset_from_base];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeTransitions[i] = jumpArray;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -291,59 +295,26 @@ void PackArchive::ConvertCommercialFormat(StoryProject &proj, const std::string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create links, parse again the nodes
|
// Create links, parse again the nodes
|
||||||
for (int i = 0; i < mNiFile.node_size; i++)
|
// for (int i = 0; i < mNiFile.node_size; i++)
|
||||||
{
|
//{
|
||||||
|
// std::cout << "Node id " << nodeIds[i] << " has " << nodeTransitions[i].size() << " transistions" << std::endl;
|
||||||
|
|
||||||
for (auto &j : nodeTransitions[i])
|
for (auto &j : nodeLinks)
|
||||||
{
|
{
|
||||||
auto c = std::make_shared<Connection>();
|
auto c = std::make_shared<Connection>();
|
||||||
|
|
||||||
c->outNodeId = nodeIds[i];
|
c->outNodeId = nodeIds[j.first]; // source
|
||||||
c->outPortIndex = 0;
|
c->outPortIndex = 0;
|
||||||
c->inNodeId = nodeIds[j];
|
c->inNodeId = nodeIds[j.second]; // destination
|
||||||
c->inPortIndex = 0;
|
c->inPortIndex = 0;
|
||||||
|
|
||||||
page->AddLink(c);
|
page->AddLink(c);
|
||||||
}
|
}
|
||||||
}
|
//}
|
||||||
|
|
||||||
proj.Save(res);
|
proj.Save(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PackArchive::LoadNiFile(const std::string &filePath)
|
|
||||||
{
|
|
||||||
bool success = false;
|
|
||||||
mZip.Close();
|
|
||||||
mCurrentNodeId = 0;
|
|
||||||
|
|
||||||
std::string fileName = SysLib::GetFileName(filePath);
|
|
||||||
std::string ext = SysLib::GetFileExtension(fileName);
|
|
||||||
SysLib::EraseString(fileName, "." + ext); // on retire l'extension du pack
|
|
||||||
mPackName = SysLib::ToUpper(fileName);
|
|
||||||
|
|
||||||
std::cout << "Pack name: " << mPackName << std::endl;
|
|
||||||
|
|
||||||
if (mZip.Open(filePath, true))
|
|
||||||
{
|
|
||||||
std::cout << "Number of files: " << mZip.NumberOfEntries() << std::endl;
|
|
||||||
|
|
||||||
if (ParseNIFile(mPackName))
|
|
||||||
{
|
|
||||||
success = true;
|
|
||||||
std::cout << "Parse NI file success\r\n" << std::endl;
|
|
||||||
ni_dump(&mNiFile);
|
|
||||||
|
|
||||||
ni_get_node_info(mCurrentNodeId, &mCurrentNode);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Parse NI file error\r\n" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PackArchive::OpenImage(const std::string &fileName)
|
std::string PackArchive::OpenImage(const std::string &fileName)
|
||||||
{
|
{
|
||||||
std::string f;
|
std::string f;
|
||||||
|
|
@ -461,127 +432,15 @@ bool PackArchive::ImportStudioFormat(const std::string &fileName, const std::str
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PackArchive::GetImage(const std::string &fileName)
|
bool PackArchive::ParseRootFiles(const std::filesystem::path &root)
|
||||||
{
|
|
||||||
//"C8B39950DE174EAA8E852A07FC468267/rf/000/05FB5530"
|
|
||||||
std::string imagePath = mPackName + "/rf/" + fileName;
|
|
||||||
SysLib::ReplaceCharacter(imagePath, "\\", "/");
|
|
||||||
|
|
||||||
std::cout << "Loading " + imagePath << std::endl;
|
|
||||||
return OpenImage(imagePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PackArchive::CurrentImage()
|
|
||||||
{
|
|
||||||
return GetImage(std::string(mCurrentNode.ri_file));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PackArchive::CurrentSound()
|
|
||||||
{
|
|
||||||
//"C8B39950DE174EAA8E852A07FC468267/sf/000/05FB5530"
|
|
||||||
std::string soundPath = mPackName + "/sf/" + std::string(mCurrentNode.si_file);
|
|
||||||
SysLib::ReplaceCharacter(soundPath, "\\", "/");
|
|
||||||
|
|
||||||
std::cout << "Loading " + soundPath << std::endl;
|
|
||||||
|
|
||||||
std::string f;
|
|
||||||
if (mZip.GetFile(soundPath, f))
|
|
||||||
{
|
|
||||||
ni_decode_block512(reinterpret_cast<uint8_t *>(f.data()));
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Cannot load file from ZIP" << std::endl;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PackArchive::CurrentSoundName()
|
|
||||||
{
|
|
||||||
return std::string(mCurrentNode.si_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PackArchive::AutoPlay()
|
|
||||||
{
|
|
||||||
return mCurrentNode.current->auto_play;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PackArchive::IsRoot() const
|
|
||||||
{
|
|
||||||
return mCurrentNodeId == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PackArchive::IsWheelEnabled() const
|
|
||||||
{
|
|
||||||
return mCurrentNode.current->wheel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackArchive::Next()
|
|
||||||
{
|
|
||||||
// L'index de circulation dans le tableau des transitions commence à 1 (pas à zéro ...)
|
|
||||||
uint32_t index = 1;
|
|
||||||
if (mCurrentNode.current->ok_transition_selected_option_index < mNodeForChoice.current->ok_transition_number_of_options)
|
|
||||||
{
|
|
||||||
index = mCurrentNode.current->ok_transition_selected_option_index + 1;
|
|
||||||
}
|
|
||||||
// sinon on revient à l'index 0 (début du tableau des transitions)
|
|
||||||
|
|
||||||
mCurrentNodeId = ni_get_node_index_in_li(mNodeForChoice.current->ok_transition_action_node_index_in_li, index - 1);
|
|
||||||
ni_get_node_info(mCurrentNodeId, &mCurrentNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackArchive::Previous()
|
|
||||||
{
|
|
||||||
// L'index de circulation dans le tableau des transitions commence à 1 (pas à zéro ...)
|
|
||||||
uint32_t index = 1;
|
|
||||||
if (mCurrentNode.current->ok_transition_selected_option_index > 1)
|
|
||||||
{
|
|
||||||
index = mCurrentNode.current->ok_transition_selected_option_index - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = mNodeForChoice.current->ok_transition_number_of_options;
|
|
||||||
}
|
|
||||||
|
|
||||||
mCurrentNodeId = ni_get_node_index_in_li(mNodeForChoice.current->ok_transition_action_node_index_in_li, index - 1);
|
|
||||||
ni_get_node_info(mCurrentNodeId, &mCurrentNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackArchive::OkButton()
|
|
||||||
{
|
|
||||||
if (mCurrentNode.current->home_transition_number_of_options > 0)
|
|
||||||
{
|
|
||||||
// On doit faire un choix!
|
|
||||||
// On sauvegarde ce noeud car il va servir pour naviguer dans les choix
|
|
||||||
mNodeIdForChoice = mCurrentNodeId;
|
|
||||||
ni_get_node_info(mNodeIdForChoice, &mNodeForChoice);
|
|
||||||
}
|
|
||||||
mCurrentNodeId = ni_get_node_index_in_li(mCurrentNode.current->ok_transition_action_node_index_in_li, mCurrentNode.current->ok_transition_selected_option_index);
|
|
||||||
ni_get_node_info(mCurrentNodeId, &mCurrentNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PackArchive::HasImage()
|
|
||||||
{
|
|
||||||
return std::string(mCurrentNode.ri_file).size() > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PackArchive::ParseNIFile(const std::string &root)
|
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
std::string f;
|
std::string f;
|
||||||
if (mZip.GetFile(root + "/li", f))
|
|
||||||
{
|
|
||||||
ni_set_li_block(reinterpret_cast<const uint8_t *>(f.data()), f.size());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
success = false;
|
|
||||||
std::cout << "[PACK_ARCHIVE] Cannot find LI file" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mZip.GetFile(root + "/ri", f))
|
f = SysLib::ReadFile(root / "ri");
|
||||||
|
if (f.size() > 0)
|
||||||
{
|
{
|
||||||
|
// Deciphering is done in this function
|
||||||
ni_set_ri_block(reinterpret_cast<const uint8_t *>(f.data()), f.size());
|
ni_set_ri_block(reinterpret_cast<const uint8_t *>(f.data()), f.size());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -590,8 +449,10 @@ bool PackArchive::ParseNIFile(const std::string &root)
|
||||||
std::cout << "[PACK_ARCHIVE] Cannot find RI file" << std::endl;
|
std::cout << "[PACK_ARCHIVE] Cannot find RI file" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mZip.GetFile(root + "/si", f))
|
f = SysLib::ReadFile(root / "si");
|
||||||
|
if (f.size() > 0)
|
||||||
{
|
{
|
||||||
|
// Deciphering is done in this function
|
||||||
ni_set_si_block(reinterpret_cast<const uint8_t *>(f.data()), f.size());
|
ni_set_si_block(reinterpret_cast<const uint8_t *>(f.data()), f.size());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -600,12 +461,26 @@ bool PackArchive::ParseNIFile(const std::string &root)
|
||||||
std::cout << "[PACK_ARCHIVE] Cannot find SI file" << std::endl;
|
std::cout << "[PACK_ARCHIVE] Cannot find SI file" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mZip.GetFile(root + "/ni", f))
|
f = SysLib::ReadFile(root / "li");
|
||||||
|
if (f.size() > 0)
|
||||||
|
{
|
||||||
|
// Deciphering is done in this function
|
||||||
|
ni_set_li_block(reinterpret_cast<const uint8_t *>(f.data()), f.size());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
std::cout << "[PACK_ARCHIVE] Cannot find LI file" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = SysLib::ReadFile(root / "ni");
|
||||||
|
if (f.size() > 0)
|
||||||
{
|
{
|
||||||
success = success & ni_parser(&mNiFile, reinterpret_cast<const uint8_t *>(f.data()));
|
success = success & ni_parser(&mNiFile, reinterpret_cast<const uint8_t *>(f.data()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
success = false;
|
||||||
std::cout << "[PACK_ARCHIVE] Cannot find NI file" << std::endl;
|
std::cout << "[PACK_ARCHIVE] Cannot find NI file" << std::endl;
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
#include "zip.h"
|
#include "zip.h"
|
||||||
#include "ni_parser.h"
|
#include "ni_parser.h"
|
||||||
|
|
@ -12,35 +13,92 @@
|
||||||
#include "i_logger.h"
|
#include "i_logger.h"
|
||||||
#include "i_story_db.h"
|
#include "i_story_db.h"
|
||||||
#include "story_project.h"
|
#include "story_project.h"
|
||||||
|
#include "sys_lib.h"
|
||||||
|
|
||||||
class PackArchive
|
class PackArchive
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PackArchive(ILogger &log);
|
PackArchive(ILogger &log);
|
||||||
|
|
||||||
bool LoadNiFile(const std::string &filePath);
|
|
||||||
std::string OpenImage(const std::string &fileName);
|
std::string OpenImage(const std::string &fileName);
|
||||||
|
|
||||||
bool ImportStudioFormat(const std::string &fileName, const std::string &outputDir);
|
bool ImportStudioFormat(const std::string &fileName, const std::string &outputDir);
|
||||||
|
|
||||||
template<typename Range>
|
template<typename Range>
|
||||||
// requires std::ranges::range<Range>
|
// requires std::ranges::range<Range>
|
||||||
void ImportCommercialFormat(const std::string &packFileName, const std::string &outputDir, Range&& range)
|
void ImportCommercialFormat(const std::string &packFileName, const std::string &libraryBaseDir, Range&& range)
|
||||||
{
|
{
|
||||||
auto uuid = Uuid().String();
|
auto uuid = Uuid().String();
|
||||||
std::string basePath = outputDir + "/" + uuid;
|
std::string outputBaseDir = libraryBaseDir + "/" + uuid;
|
||||||
|
|
||||||
Unzip(packFileName, basePath);
|
auto ext = SysLib::GetFileExtension(packFileName);
|
||||||
LoadNiFile(packFileName);
|
|
||||||
|
std::filesystem::path importBaseDir;
|
||||||
|
|
||||||
|
// Selon l'importation, l'UUID peut être partiel (à partir d'une carte SD) ou complet (pour un .pk)
|
||||||
|
std::string packUuidv4;
|
||||||
|
|
||||||
|
if (ext == "pk")
|
||||||
|
{
|
||||||
|
// Unzip all before analyze the pack
|
||||||
|
Unzip(packFileName, outputBaseDir);
|
||||||
|
|
||||||
|
// Le pack Lunii contient un répertoire contenant l'UUID sans tirets, upper case
|
||||||
|
packUuidv4 = SysLib::GetFileName(packFileName);
|
||||||
|
SysLib::EraseString(packUuidv4, "." + ext); // on retire l'extension du pack
|
||||||
|
importBaseDir = std::filesystem::path(outputBaseDir) / SysLib::ToUpper(packUuidv4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Ici on a choisi le fichier ni, donc on prend juste le répertoire parent
|
||||||
|
importBaseDir = SysLib::GetDirectory(packFileName);
|
||||||
|
std::string packDirNameOnly = SysLib::GetFileName(importBaseDir);
|
||||||
|
|
||||||
|
// Ici on va copier le répertoire dans un dossier de travail pour éviter de corrompre le
|
||||||
|
// répertoire d'origine (vu qu'on decipher tout)
|
||||||
|
const auto copyOptions = std::filesystem::copy_options::recursive
|
||||||
|
| std::filesystem::copy_options::update_existing
|
||||||
|
| std::filesystem::copy_options::overwrite_existing
|
||||||
|
;
|
||||||
|
|
||||||
|
std::string workingDir = std::filesystem::path(outputBaseDir) / packDirNameOnly;
|
||||||
|
std::filesystem::create_directories(workingDir);
|
||||||
|
std::filesystem::copy(importBaseDir, workingDir, copyOptions);
|
||||||
|
|
||||||
|
importBaseDir = workingDir; // on travaille là maintenant
|
||||||
|
packUuidv4 = SysLib::ToLower(packDirNameOnly); // le répertoire parent est l'UUID mais partiel !! (la fin d'un full UUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ParseRootFiles(importBaseDir))
|
||||||
|
{
|
||||||
|
m_log.Log("Parse NI file success");
|
||||||
|
ni_dump(&mNiFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.Log("Parse NI file error", true);
|
||||||
|
}
|
||||||
|
|
||||||
StoryProject proj(m_log);
|
StoryProject proj(m_log);
|
||||||
proj.New(uuid, outputDir);
|
proj.New(uuid, libraryBaseDir);
|
||||||
|
|
||||||
auto packUuidv4 = normalizeUUID(mPackName);
|
|
||||||
for (auto &info : range)
|
for (auto &info : range)
|
||||||
{
|
{
|
||||||
std::cout << info.uuid << std::endl;
|
bool foundStory = false;
|
||||||
if (info.uuid == packUuidv4)
|
|
||||||
|
// full UUIDv4 size
|
||||||
|
if (packUuidv4.size() == 32)
|
||||||
|
{
|
||||||
|
packUuidv4 = normalizeUUID(packUuidv4);
|
||||||
|
foundStory = (info.uuid == packUuidv4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Partial UUIDv4, uniquement les 8 derniers caractères
|
||||||
|
foundStory = info.uuid.ends_with(packUuidv4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundStory)
|
||||||
{
|
{
|
||||||
m_log.Log("Found commercial story: " + info.title);
|
m_log.Log("Found commercial story: " + info.title);
|
||||||
proj.SetName(info.title);
|
proj.SetName(info.title);
|
||||||
|
|
@ -53,8 +111,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string path = basePath + "/" + mPackName + "/rf";
|
for (const auto & entry : std::filesystem::directory_iterator(importBaseDir / "rf"))
|
||||||
for (const auto & entry : std::filesystem::directory_iterator(path))
|
|
||||||
{
|
{
|
||||||
if (entry.is_directory())
|
if (entry.is_directory())
|
||||||
{
|
{
|
||||||
|
|
@ -63,8 +120,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
path = basePath + "/" + mPackName + "/sf";
|
for (const auto & entry : std::filesystem::directory_iterator(importBaseDir / "sf"))
|
||||||
for (const auto & entry : std::filesystem::directory_iterator(path))
|
|
||||||
{
|
{
|
||||||
if (entry.is_directory())
|
if (entry.is_directory())
|
||||||
{
|
{
|
||||||
|
|
@ -73,21 +129,9 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ConvertCommercialFormat(proj, basePath);
|
ConvertCommercialFormat(proj, importBaseDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CurrentImage();
|
|
||||||
std::string CurrentSound();
|
|
||||||
std::string CurrentSoundName();
|
|
||||||
bool AutoPlay();
|
|
||||||
void OkButton();
|
|
||||||
bool HasImage();
|
|
||||||
std::vector<std::string> GetImages();
|
|
||||||
std::string GetImage(const std::string &fileName);
|
|
||||||
bool IsRoot() const;
|
|
||||||
bool IsWheelEnabled() const;
|
|
||||||
void Next();
|
|
||||||
void Previous();
|
|
||||||
void Unzip(const std::string &filePath, const std::string &parent_dest_dir);
|
void Unzip(const std::string &filePath, const std::string &parent_dest_dir);
|
||||||
|
|
||||||
bool ConvertJsonStudioToOst(const std::string &basePath, const std::string &uuid, const std::string &outputDir);
|
bool ConvertJsonStudioToOst(const std::string &basePath, const std::string &uuid, const std::string &outputDir);
|
||||||
|
|
@ -96,16 +140,11 @@ public:
|
||||||
private:
|
private:
|
||||||
ILogger &m_log;
|
ILogger &m_log;
|
||||||
Zip mZip;
|
Zip mZip;
|
||||||
std::string mPackName;
|
|
||||||
uint32_t mCurrentNodeId = 0;
|
|
||||||
uint32_t mNodeIdForChoice = 0;
|
|
||||||
node_info_t mNodeForChoice;
|
|
||||||
node_info_t mCurrentNode;
|
|
||||||
ni_file_t mNiFile;
|
ni_file_t mNiFile;
|
||||||
|
|
||||||
void ConvertCommercialFormat(StoryProject &proj, const std::string &basePath);
|
void ConvertCommercialFormat(StoryProject &proj, const std::filesystem::path &importBaseDir);
|
||||||
|
|
||||||
bool ParseNIFile(const std::string &root);
|
bool ParseRootFiles(const std::filesystem::path &root);
|
||||||
|
|
||||||
// Convertit un UUID de type "3ADE540306254FFFA22B9025AC3678D9"
|
// Convertit un UUID de type "3ADE540306254FFFA22B9025AC3678D9"
|
||||||
// en standard : 3ade5403-0625-4fff-a22b-9025ac3678d9
|
// en standard : 3ade5403-0625-4fff-a22b-9025ac3678d9
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ void LibraryWindow::Initialize()
|
||||||
std::cout << "Commercial store file already exists, skipping download" << std::endl;
|
std::cout << "Commercial store file already exists, skipping download" << std::endl;
|
||||||
ParseCommercialStoreDataCallback(true, m_commercialStoreFile);
|
ParseCommercialStoreDataCallback(true, m_commercialStoreFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_downloadQueue.push({
|
m_downloadQueue.push({
|
||||||
"dl_commercial",
|
"dl_commercial",
|
||||||
|
|
@ -469,12 +469,14 @@ void LibraryWindow::Draw()
|
||||||
IGFD::FileDialogConfig config;
|
IGFD::FileDialogConfig config;
|
||||||
config.path = m_libraryManager.LibraryPath();
|
config.path = m_libraryManager.LibraryPath();
|
||||||
config.countSelectionMax = 1;
|
config.countSelectionMax = 1;
|
||||||
config.sidePane = std::bind(&InfosPane, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
// config.sidePane = std::bind(&InfosPane, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||||
config.sidePaneWidth = 350.0f;
|
// config.sidePaneWidth = 350.0f;
|
||||||
config.flags = ImGuiFileDialogFlags_Modal;
|
config.flags = ImGuiFileDialogFlags_Modal;
|
||||||
|
const char *filters = "Commercial stories (*.pk ni){.pk, ((ni))}, Community stories (*.zip *.json){.zip,.json}";
|
||||||
|
|
||||||
ImGuiFileDialog::Instance()->OpenDialog("ImportStoryDlgKey",
|
ImGuiFileDialog::Instance()->OpenDialog("ImportStoryDlgKey",
|
||||||
"Import story",
|
"Import story",
|
||||||
".zip, .json, .pk",
|
filters,
|
||||||
config
|
config
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -649,11 +651,16 @@ void LibraryWindow::Draw()
|
||||||
{
|
{
|
||||||
if (ImGuiFileDialog::Instance()->IsOk())
|
if (ImGuiFileDialog::Instance()->IsOk())
|
||||||
{
|
{
|
||||||
std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName();
|
std::map<std::string, std::string> sel = ImGuiFileDialog::Instance()->GetSelection();
|
||||||
std::string filePath = ImGuiFileDialog::Instance()->GetCurrentPath();
|
|
||||||
std::string filter = ImGuiFileDialog::Instance()->GetCurrentFilter();
|
if (sel.size() > 0)
|
||||||
// Import "Studio" or "Commercial" format
|
{
|
||||||
m_storyManager.ImportProject(filePathName, formatFilter);
|
std::string fileName = sel.begin()->first;
|
||||||
|
std::string filePathName = sel.begin()->second;
|
||||||
|
|
||||||
|
// Import "Studio" or "Commercial" format
|
||||||
|
m_storyManager.ImportProject(filePathName, formatFilter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// close
|
// close
|
||||||
ImGuiFileDialog::Instance()->Close();
|
ImGuiFileDialog::Instance()->Close();
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "pack_archive.h"
|
#include "pack_archive.h"
|
||||||
#include "uuid.h"
|
#include "uuid.h"
|
||||||
|
#include "sys_lib.h"
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_OS
|
#ifdef USE_WINDOWS_OS
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
|
@ -47,6 +48,12 @@ MainWindow::MainWindow()
|
||||||
m_chip32_ctx.syscall = static_cast<syscall_t>(Callback<uint8_t(chip32_ctx_t *, uint8_t)>::callback);
|
m_chip32_ctx.syscall = static_cast<syscall_t>(Callback<uint8_t(chip32_ctx_t *, uint8_t)>::callback);
|
||||||
|
|
||||||
CloseProject();
|
CloseProject();
|
||||||
|
|
||||||
|
// define style for all directories
|
||||||
|
ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByTypeDir, "", ImVec4(0.5f, 1.0f, 0.9f, 0.9f), ICON_MDI_FOLDER);
|
||||||
|
// define style for all files
|
||||||
|
ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByTypeFile, "", ImVec4(1.0f, 1.0f, 1.0f, 1.0f), ICON_MDI_FILE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
|
|
@ -793,19 +800,27 @@ void MainWindow::OpenProject(const std::string &uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::ImportProject(const std::string &fileName, int format)
|
void MainWindow::ImportProject(const std::string &filePathName, int format)
|
||||||
{
|
{
|
||||||
|
(void) format;
|
||||||
PackArchive archive(*this);
|
PackArchive archive(*this);
|
||||||
|
|
||||||
if (format == 0)
|
// On va déterminer le type de fichier selon l'extension
|
||||||
{
|
auto ext = SysLib::GetFileExtension(filePathName);
|
||||||
archive.ImportStudioFormat(fileName, m_libraryManager.LibraryPath());
|
auto filename = SysLib::GetFileName(filePathName);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
archive.ImportCommercialFormat(fileName, m_libraryManager.LibraryPath(), m_libraryManager.CommercialDbView());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if ((ext == "pk") || (filename == "ni"))
|
||||||
|
{
|
||||||
|
archive.ImportCommercialFormat(filePathName, m_libraryManager.LibraryPath(), m_libraryManager.CommercialDbView());
|
||||||
|
}
|
||||||
|
else if ((ext == "json") || (ext == "zip"))
|
||||||
|
{
|
||||||
|
archive.ImportStudioFormat(filePathName, m_libraryManager.LibraryPath());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log("Unknown file format: " + filePathName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::RefreshProjectInformation()
|
void MainWindow::RefreshProjectInformation()
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ private:
|
||||||
|
|
||||||
// From IStoryManager (proxy to StoryProject class)
|
// From IStoryManager (proxy to StoryProject class)
|
||||||
virtual void OpenProject(const std::string &uuid) override;
|
virtual void OpenProject(const std::string &uuid) override;
|
||||||
virtual void ImportProject(const std::string &fileName, int format);
|
virtual void ImportProject(const std::string &filePathName, int format);
|
||||||
virtual void PlaySoundFile(const std::string &fileName) override;;
|
virtual void PlaySoundFile(const std::string &fileName) override;;
|
||||||
virtual std::string BuildFullAssetsPath(const std::string_view fileName) const override;
|
virtual std::string BuildFullAssetsPath(const std::string_view fileName) const override;
|
||||||
virtual std::pair<FilterIterator, FilterIterator> Images() override;
|
virtual std::pair<FilterIterator, FilterIterator> Images() override;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue