diff --git a/src/CollectionPlayState.cpp b/src/CollectionPlayState.cpp index 06e34b6..8bbbf4f 100644 --- a/src/CollectionPlayState.cpp +++ b/src/CollectionPlayState.cpp @@ -30,7 +30,6 @@ https://github.com/sago007/saland #include "SagoImGui.hpp" #include "nlohmann/json.hpp" #include -#include CollectionPlayState::CollectionPlayState(const std::string& collectionDir) : collectionDir(collectionDir) { @@ -204,13 +203,13 @@ void CollectionPlayState::Update() { if (currentPuzzleIndex >= 0 && currentPuzzleIndex < static_cast(puzzles.size())) { const CollectionPuzzleInfo& puzzle = puzzles[currentPuzzleIndex]; - std::string imagePath = GetImageFilesystemPath(puzzle.image); + std::string imagePath = GetImagePhysFSPath(puzzle.image); if (!imagePath.empty()) { PuzzleSingleImageState psi; psi.flipMode = puzzle.flip_mode; psi.rectangularMode = puzzle.rectangular_mode; - psi.LoadPictureFromFile(imagePath, globalData.screen); + psi.LoadPictureFromPhysFS(imagePath, globalData.screen); RunGameState(psi); globalData.mouseUp = true; @@ -280,22 +279,17 @@ void CollectionPlayState::LoadCollection() { void CollectionPlayState::LoadCurrentImage() { if (currentPuzzleIndex >= 0 && currentPuzzleIndex < static_cast(puzzles.size())) { - std::string imagePath = GetImageFilesystemPath(puzzles[currentPuzzleIndex].image); + std::string imagePath = GetImagePhysFSPath(puzzles[currentPuzzleIndex].image); ImageHolder newHolder; if (!imagePath.empty()) { - newHolder.LoadPictureFromFileLazy(imagePath); + newHolder.LoadPictureFromPhysFSLazy(imagePath); } currentImageHolder = std::move(newHolder); } } -std::string CollectionPlayState::GetImageFilesystemPath(const std::string& imageFilename) const { - std::string physfsPath = "collections/" + collectionDir + "/" + imageFilename; - const char* realDir = PHYSFS_getRealDir(physfsPath.c_str()); - if (realDir) { - return std::string(realDir) + "/" + physfsPath; - } - return ""; +std::string CollectionPlayState::GetImagePhysFSPath(const std::string& imageFilename) const { + return "collections/" + collectionDir + "/" + imageFilename; } int CollectionPlayState::FindFirstUnsolved() const { diff --git a/src/CollectionPlayState.hpp b/src/CollectionPlayState.hpp index 311793e..163a791 100644 --- a/src/CollectionPlayState.hpp +++ b/src/CollectionPlayState.hpp @@ -52,7 +52,7 @@ public: private: void LoadCollection(); void LoadCurrentImage(); - std::string GetImageFilesystemPath(const std::string& imageFilename) const; + std::string GetImagePhysFSPath(const std::string& imageFilename) const; int FindFirstUnsolved() const; bool isActive = true; diff --git a/src/ImageHolder.cpp b/src/ImageHolder.cpp index 5bf955c..8b101ee 100644 --- a/src/ImageHolder.cpp +++ b/src/ImageHolder.cpp @@ -23,6 +23,8 @@ https://github.com/sago007/saland #include "ImageHolder.hpp" #include +#include "sago/SagoMisc.hpp" +#include ImageHolder::ImageHolder() : pictureTex(nullptr), source_image_width(1), source_image_height(1) {} @@ -32,6 +34,7 @@ ImageHolder::ImageHolder(ImageHolder&& other) { source_image_height = other.source_image_height; source_filename = other.source_filename; do_lazy_load = other.do_lazy_load; + physfs_lazy_load = other.physfs_lazy_load; other.pictureTex = nullptr; } @@ -45,6 +48,7 @@ ImageHolder& ImageHolder::operator=(ImageHolder&& other) { source_image_height = other.source_image_height; source_filename = other.source_filename; do_lazy_load = other.do_lazy_load; + physfs_lazy_load = other.physfs_lazy_load; other.pictureTex = nullptr; } return *this; @@ -80,11 +84,42 @@ void ImageHolder::LoadPictureFromFile(const std::string& filename, SDL_Renderer* SDL_FreeSurface(pictureSurface); } +void ImageHolder::LoadPictureFromPhysFS(const std::string& physfsPath, SDL_Renderer* renderer) { + source_filename = physfsPath; + std::unique_ptr data; + unsigned int bytes = 0; + sago::ReadBytesFromFile(physfsPath.c_str(), data, bytes); + if (!data || bytes == 0) { + printf("ImageHolder::LoadPictureFromPhysFS() failed to read file: %s\n", physfsPath.c_str()); + return; + } + SDL_RWops* rw = SDL_RWFromMem(data.get(), bytes); + SDL_Surface* pictureSurface = IMG_Load_RW(rw, 0); + SDL_RWclose(rw); + if (pictureSurface == nullptr) { + printf("ImageHolder::LoadPictureFromPhysFS() failed to load image: %s\n", physfsPath.c_str()); + return; + } + if (pictureTex != nullptr) { + SDL_DestroyTexture(pictureTex); + } + pictureTex = SDL_CreateTextureFromSurface(renderer, pictureSurface); + source_image_width = pictureSurface->w; + source_image_height = pictureSurface->h; + SDL_FreeSurface(pictureSurface); +} + void ImageHolder::LoadPictureFromFileLazy(const std::string& filename) { source_filename = filename; do_lazy_load = true; } +void ImageHolder::LoadPictureFromPhysFSLazy(const std::string& physfsPath) { + source_filename = physfsPath; + do_lazy_load = true; + physfs_lazy_load = true; +} + int ImageHolder::GetWidth() const { return source_image_width; @@ -102,8 +137,13 @@ void ImageHolder::Draw(SDL_Renderer* target, int x, int y, int max_w, int max_h) if (do_lazy_load) { printf("Lazy loading image: %s\n", source_filename.c_str()); std::string filename = source_filename; - LoadPictureFromFile(filename, target); + if (physfs_lazy_load) { + LoadPictureFromPhysFS(filename, target); + } else { + LoadPictureFromFile(filename, target); + } do_lazy_load = false; + physfs_lazy_load = false; } if (pictureTex == nullptr) { //printf("ImageHolder::Draw() called with no image loaded. Filename: %s\n", source_filename.c_str()); diff --git a/src/ImageHolder.hpp b/src/ImageHolder.hpp index 28a15fd..d15f990 100644 --- a/src/ImageHolder.hpp +++ b/src/ImageHolder.hpp @@ -49,7 +49,9 @@ public: // Other member functions and variables void LoadPictureFromFile(const std::string& filename, SDL_Renderer* renderer); + void LoadPictureFromPhysFS(const std::string& physfsPath, SDL_Renderer* renderer); void LoadPictureFromFileLazy(const std::string& filename); + void LoadPictureFromPhysFSLazy(const std::string& physfsPath); int GetWidth() const; int GetHeight() const; SDL_Texture* GetTexture() const; @@ -70,6 +72,7 @@ private: // Private member variables SDL_Texture* pictureTex = NULL; bool do_lazy_load = false; + bool physfs_lazy_load = false; int source_image_height = 1; int source_image_width = 1; std::string source_filename; diff --git a/src/PuzzleSingleImageState.cpp b/src/PuzzleSingleImageState.cpp index c4ac61f..1a4abd9 100644 --- a/src/PuzzleSingleImageState.cpp +++ b/src/PuzzleSingleImageState.cpp @@ -28,8 +28,10 @@ https://github.com/sago007/saland #include "globals.hpp" #include #include +#include #include #include "SagoImGui.hpp" +#include "sago/SagoMisc.hpp" #include "rhash.hpp" #include "config.hpp" #include "sago_common.hpp" @@ -357,6 +359,60 @@ void PuzzleSingleImageState::LoadPictureFromFile(const std::string& filename, SD Shuffle(); } +void PuzzleSingleImageState::LoadPictureFromPhysFS(const std::string& physfsPath, SDL_Renderer* renderer) { + ClearPicture(); + imageFilePath = physfsPath; + IMG_Init(IMG_INIT_JPG|IMG_INIT_PNG); + std::unique_ptr data; + unsigned int bytes = 0; + sago::ReadBytesFromFile(physfsPath.c_str(), data, bytes); + if (!data || bytes == 0) { + std::cerr << "Failed to read " << physfsPath << " from PhysFS" << std::endl; + return; + } + SDL_RWops* rw = SDL_RWFromMem(data.get(), bytes); + SDL_Surface* bitmapSurface = IMG_Load_RW(rw, 0); + SDL_RWclose(rw); + if (!bitmapSurface) { + std::cerr << "Failed to load " << physfsPath << std::endl; + return; + } + RHash h(RHASH_SHA256); + h.update(physfsPath); + picture_id = h.hex(RHASH_SHA256); + source_image_height = bitmapSurface->h; + source_image_width = bitmapSurface->w; + ResizeImage(); + this->pictureTex = SDL_CreateTextureFromSurface(renderer, bitmapSurface); + std::cerr << resized_image_logical_width << ", " << resized_image_logical_height << ", id: " << picture_id << ", file: " << physfsPath << "\n"; + SDL_FreeSurface(bitmapSurface); + SDL_SetTextureBlendMode(this->pictureTex, SDL_BLENDMODE_BLEND); + pieces_logical.clear(); + + if (rectangularMode) { + if (!LoadCustomPieceLayout(picture_id, pieces_logical)) { + CreateRectangularPieces(4, 4); + } + else { + std::cerr << "Loaded custom piece layout with " << pieces_logical.size() << " pieces\n"; + } + } + else { + SDL_Rect piece; + piece.x = 0; + piece.y = 0; + piece.h = resized_image_logical_height; + piece.w = resized_image_logical_width; + pieces_logical.push_back(piece); + for (int i = 0; i<10; ++i) { + SplitPiece(); + } + } + + ResizeImagePhysical(); + Shuffle(); +} + void PuzzleSingleImageState::SplitPiece(size_t piece_number) { srand(time(NULL)); if (rand()%2==1) { diff --git a/src/PuzzleSingleImageState.hpp b/src/PuzzleSingleImageState.hpp index b55663c..6e3f9e6 100644 --- a/src/PuzzleSingleImageState.hpp +++ b/src/PuzzleSingleImageState.hpp @@ -40,6 +40,7 @@ public: void Update() override; void LoadPictureFromFile(const std::string& filename, SDL_Renderer* renderer); + void LoadPictureFromPhysFS(const std::string& physfsPath, SDL_Renderer* renderer); bool IsSolved() const { return puzzleSolved; }