AniResourceUtilities.cpp 8.84 KB
//
//  AniResourceUtilities.cpp
//  SteveMaggieCpp
//
//  Created by Katarzyna Kalinowska-Górska on 23.06.2017.
//
//

#include <stdio.h>
#include "AniResourceUtilities.h"
#include "AniJSONParseUtils.h"
#include "AniValueStorage.h"
//#include "ResourceDownloader_cpp.h"
#include "AniResourcesConfig.h"

#define RESOURCES_LOAD_FROM_ASSETS
//#define FORCE_REDOWNLOAD_RESOURCES


std::string AniResourceUtilities::getDownloadedResourcesPath(bool deviceDependentFiles)
{
#ifdef RESOURCES_LOAD_FROM_ASSETS
    return "";
#endif
//    std::string resDownloadDir = ResourceDownloader_getResourceDownloadDirectoryPath();
//
//    if(deviceDependentFiles){
//        return resDownloadDir + "/" + this->getDeviceSpecificFolderName();
//    }
//
//    return resDownloadDir + "/" + AniResourcesConfig::UNIVERSAL_RESOURCES_FOLDER_NAME;
}

std::string AniResourceUtilities::getFullPathForDownloadedFile(const std::string& path, bool isDeviceDependent)
{
#ifdef RESOURCES_LOAD_FROM_ASSETS
    return path;
#endif
//    std::string resDownloadDir = this->getDownloadedResourcesPath(isDeviceDependent);
//    return resDownloadDir + "/" + path;
}

std::vector< std::string> AniResourceUtilities::getFullPathsForDownloadedFiles(const std::vector< std::string>& paths, bool areDeviceDependent)
{
    std::vector< std::string> fullPaths;
    fullPaths.reserve(paths.size());
    for(const auto& path : paths){
        fullPaths.push_back(this->getFullPathForDownloadedFile(path, areDeviceDependent));
    }
    return fullPaths;
}
/*
std::vector<std::string> AniResourceUtilities::getFullPathsForDownloadedFiles(const std::vector<std::string>& paths, bool areDeviceDependent)
{
    std::vector<std::string> fullPaths;
    fullPaths.reserve(paths.size());
    for(const auto& path : paths){
        fullPaths.push_back(this->getFullPathForDownloadedFile(path, areDeviceDependent));
    }
    return fullPaths;
}
*/
std::vector<std::string> AniResourceUtilities::extractAllImagePathsFromJSONFile(std::string layoutJSONFilePath, std::string givenResourceFolderPath, std::string givenAltResourceFolderPath, std::string givenObjLayoutsFolderPath)
{
    std::string fullPath = cocos2d::FileUtils::getInstance()->fullPathForFilename(this->getFullPathForDownloadedFile(layoutJSONFilePath));
    auto layoutString = cocos2d::FileUtils::getInstance()->getStringFromFile(fullPath);
    return AniResourceUtilities::extractAllImagePathsFromLayoutString(layoutString, givenResourceFolderPath, givenAltResourceFolderPath, givenObjLayoutsFolderPath);
}

std::vector<std::string> AniResourceUtilities::extractAllImagePathsFromLayoutString(std::string layoutJSONString, std::string givenResourceFolderPath, std::string givenAltResourceFolderPath, std::string givenObjLayoutsFolderPath)
{
    rapidjson::Document document;
    document.Parse(layoutJSONString.c_str());
    std::string resFolderPath = givenResourceFolderPath, altResFolderPath = givenAltResourceFolderPath, objLayoutsFolderPath = givenObjLayoutsFolderPath;
    if(AniJSONParseUtils::hasMemberObject(document, "resFolder")){
        const auto& resFolder = document["resFolder"];
        if(AniJSONParseUtils::hasMemberString(resFolder, "path")){
            resFolderPath = this->getFullPathForDownloadedFile(resFolder["path"].GetString());
        }
        if(AniJSONParseUtils::hasMemberString(resFolder, "alternativePath")){
            altResFolderPath = this->getFullPathForDownloadedFile(resFolder["alternativePath"].GetString());
        }
        if(AniJSONParseUtils::hasMemberString(resFolder, "objectLayoutsPath")){
            objLayoutsFolderPath = this->getFullPathForDownloadedFile(resFolder["objectLayoutsPath"].GetString());
        }
    }
    return AniResourceUtilities::extractAllImagePaths(document, resFolderPath, altResFolderPath, objLayoutsFolderPath);
}


//!! TODO
//"loadObjectFromFile" : "buttons/horizontalButtonPanel.obl",

std::vector<std::string> AniResourceUtilities::extractAllImagePaths(const rapidjson::Value& value, std::string resourceFolderPath, std::string altResourceFolderPath, std::string objLayoutsFolderPath)
{
    std::vector<std::string> allImagePaths;
    
    if(value.IsArray()){
        for(const auto& element : value.GetArray()){
            if(element.IsObject() || element.IsArray()){
                auto imagePaths = this->extractAllImagePaths(element, resourceFolderPath, altResourceFolderPath, objLayoutsFolderPath);
                allImagePaths.insert(allImagePaths.end(), imagePaths.begin(), imagePaths.end());
            }
        }
        
    } else if(value.IsObject()){
    
        std::string resourceFolderString = resourceFolderPath;
    
        if(AniJSONParseUtils::checkMemberBool(value, "useAlternativePath", true)){
            resourceFolderString = altResourceFolderPath;
        }
    
        for(const auto& pair : value.GetObject()){
            std::string key = pair.name.GetString();
            
            if(key.find("imagePath") != std::string::npos || key.find("ImagePath") != std::string::npos){
                if(pair.value.IsString()){
                    allImagePaths.push_back(resourceFolderString + pair.value.GetString());
                }
                else if(pair.value.IsArray()){
                    for(const auto& element : pair.value.GetArray()){
                        if(element.IsString()){
                            allImagePaths.push_back(resourceFolderString + element.GetString());
                        }
                    }
                }
            }
            else if(key.find("filePath") != std::string::npos || key.find("FilePath") != std::string::npos){
            
                if(pair.value.IsString()){
                    auto imagePaths = this->extractAllImagePathsFromJSONFile(resourceFolderString + pair.value.GetString());
                    allImagePaths.insert(allImagePaths.end(), imagePaths.begin(), imagePaths.end());
//                    cocos2d::log("extracted %d image paths from file %s", (int)imagePaths.size(), pair.value.GetString());
                }
            
            }
            else if(key.find("loadObjectFromFile") != std::string::npos){
            
                if(pair.value.IsString()){
                    auto filePath = objLayoutsFolderPath + pair.value.GetString();
                    auto imagePaths = this->extractAllImagePathsFromJSONFile(filePath, resourceFolderPath, altResourceFolderPath, objLayoutsFolderPath);
                    allImagePaths.insert(allImagePaths.end(), imagePaths.begin(), imagePaths.end());
//                    cocos2d::log("extracted %d image paths from file %s", (int)imagePaths.size(), filePath.c_str());
                }
            
            } else if(pair.value.IsObject() || pair.value.IsArray()){
                auto imagePaths = this->extractAllImagePaths(pair.value, resourceFolderPath, altResourceFolderPath, objLayoutsFolderPath);
                allImagePaths.insert(allImagePaths.end(), imagePaths.begin(), imagePaths.end());
            }
        }
    }
    
//    cocos2d::log("extractAllImagePaths: IN TOTAL %d IMAGE PATHS", (int)allImagePaths.size());
    return allImagePaths;
}

void AniResourceUtilities::preloadResourcesForFile(std::string layoutJSONFilePath, std::function<void(std::vector<std::string>)> callback)
{
    //TODO fail callback?
    auto allImageFiles = extractAllImagePathsFromJSONFile(layoutJSONFilePath);
    
    if(allImageFiles.size() == 0){
        callback(allImageFiles);
    } else {
        preloadFiles(allImageFiles, callback);
    }
}

void AniResourceUtilities::preloadFiles(std::vector<std::string> files, std::function<void(std::vector<std::string>)> callback){
    auto textureCache = cocos2d::Director::getInstance()->getTextureCache();
    float counterF = files.size();
    AniSimpleValue counter(counterF);
    auto counterKey = AniValueStorage::getInstance().storeAniSimpleValue(counter);
    auto callbackKey = AniValueStorage::getInstance().storeFunction(std::bind(callback, files));
    for(auto imagePath : files){
//        cocos2d::log("loading texture: %s", imagePath.c_str());
            textureCache->addImageAsync(imagePath, std::bind([&](cocos2d::Texture2D* loadedTexture, std::string pCounterKey, std::string pCallbackKey){
//                if(loadedTexture){
//                    cocos2d::log("texture loaded successfully: %s", imagePath.c_str());
//                } else {
//                    cocos2d::log("failed to load texture: %s", imagePath.c_str());
//                }
    //
                AniSimpleValue* counter = AniValueStorage::getInstance().getStoredAniSimpleValue(pCounterKey);
                counter->setNumberValue(counter->getNumberValue()-1);
                if(counter->getNumberValue() <= 0){
                    AniValueStorage::getInstance().removeStoredValue(pCounterKey);
                    AniValueStorage::getInstance().runAndRemoveStoredFunction(pCallbackKey);
                }
                
            }, std::placeholders::_1, counterKey, callbackKey));
        }
}