| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305 |
- /****************************************************************************
- Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
- http://www.cocos.com
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated engine source code (the "Software"), a limited,
- worldwide, royalty-free, non-assignable, revocable and non-exclusive license
- to use Cocos Creator solely to develop games on your target platforms. You shall
- not use Cocos Creator software for developing other software or tools that's
- used for developing games. You are not granted to publish, distribute,
- sublicense, and/or sell copies of Cocos Creator.
- The software or tools in this License Agreement are licensed, not sold.
- Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- ****************************************************************************/
- #include "jsb_global.h"
- #include "jsb_conversions.hpp"
- #include "xxtea/xxtea.h"
- #include "base/CCScheduler.h"
- #include "base/CCThreadPool.h"
- #include "network/HttpClient.h"
- #include "platform/CCApplication.h"
- #include "ui/edit-box/EditBox.h"
- #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
- #include "platform/android/jni/JniImp.h"
- #endif
- #include <regex>
- using namespace cocos2d;
- se::Object* __jsbObj = nullptr;
- se::Object* __glObj = nullptr;
- static std::shared_ptr<ThreadPool> g_threadPool;
- static std::shared_ptr<cocos2d::network::Downloader> g_localDownloader = nullptr;
- static std::map<std::string, std::function<void(const std::string&, unsigned char*, int ,const std::string&)>> g_localDownloaderHandlers;
- static uint64_t g_localDownloaderTaskId = 1000000;
- static std::string xxteaKey = "";
- void jsb_set_xxtea_key(const std::string& key)
- {
- xxteaKey = key;
- }
- static cocos2d::network::Downloader *localDownloader()
- {
- if(!g_localDownloader)
- {
- g_localDownloader = std::make_shared<cocos2d::network::Downloader>();
- g_localDownloader->onDataTaskSuccess = [=](const cocos2d::network::DownloadTask& task,
- std::vector<unsigned char>& data) {
- if(data.empty())
- {
- SE_REPORT_ERROR("Getting image from (%s) failed!", task.requestURL.c_str());
- return;
- }
- auto callback = g_localDownloaderHandlers.find(task.identifier);
- if(callback == g_localDownloaderHandlers.end())
- {
- SE_REPORT_ERROR("Getting image from (%s), callback not found!!", task.requestURL.c_str());
- return;
- }
- size_t imageBytes = data.size();
- unsigned char* imageData = (unsigned char*)malloc(imageBytes);
- memcpy(imageData, data.data(), imageBytes);
- (callback->second)("", imageData, imageBytes, "");
- //initImageFunc("", imageData, imageBytes);
- g_localDownloaderHandlers.erase(callback);
- };
- g_localDownloader->onTaskError = [=](const cocos2d::network::DownloadTask& task,
- int errorCode,
- int errorCodeInternal,
- const std::string& errorStr) {
- SE_REPORT_ERROR("Getting image from (%s) failed!", task.requestURL.c_str());
- auto callback = g_localDownloaderHandlers.find(task.identifier);
- if(callback == g_localDownloaderHandlers.end())
- {
- SE_REPORT_ERROR("Getting image from (%s), callback not found!!", task.requestURL.c_str());
- return;
- }
- (callback->second)("", nullptr, 0, errorStr);
- g_localDownloaderHandlers.erase(task.identifier);
- };
- }
- return g_localDownloader.get();
- }
- static void localDownloaderCreateTask(const std::string &url, std::function<void(const std::string&, unsigned char*, int, const std::string&)> callback)
- {
- std::stringstream ss;
- ss << "jsb_loadimage_" << (g_localDownloaderTaskId++);
- std::string key = ss.str();
- auto task = localDownloader()->createDownloadDataTask(url, key);
- g_localDownloaderHandlers.emplace(std::make_pair(task->identifier, callback));
- }
- static const char* BYTE_CODE_FILE_EXT = ".jsc";
- static std::string removeFileExt(const std::string& filePath)
- {
- size_t pos = filePath.rfind('.');
- if (0 < pos)
- {
- return filePath.substr(0, pos);
- }
- return filePath;
- }
- void jsb_init_file_operation_delegate()
- {
- static se::ScriptEngine::FileOperationDelegate delegate;
- if (!delegate.isValid())
- {
- delegate.onGetDataFromFile = [](const std::string& path, const std::function<void(const uint8_t*, size_t)>& readCallback) -> void{
- assert(!path.empty());
- Data fileData;
- std::string byteCodePath = removeFileExt(path) + BYTE_CODE_FILE_EXT;
- if (FileUtils::getInstance()->isFileExist(byteCodePath)) {
- fileData = FileUtils::getInstance()->getDataFromFile(byteCodePath);
- size_t dataLen = 0;
- uint8_t* data = xxtea_decrypt((unsigned char*)fileData.getBytes(), (uint32_t)fileData.getSize(), (unsigned char*)xxteaKey.c_str(), (uint32_t)xxteaKey.size(), (uint32_t*)&dataLen);
- if (data == nullptr) {
- SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
- return;
- }
- if (ZipUtils::isGZipBuffer(data,dataLen)) {
- uint8_t* unpackedData;
- ssize_t unpackedLen = ZipUtils::inflateMemory(data, dataLen,&unpackedData);
- if (unpackedData == nullptr) {
- SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
- return;
- }
- readCallback(unpackedData, unpackedLen);
- free(data);
- free(unpackedData);
- }
- else {
- readCallback(data, dataLen);
- free(data);
- }
- return;
- }
- fileData = FileUtils::getInstance()->getDataFromFile(path);
- readCallback(fileData.getBytes(), fileData.getSize());
- };
- delegate.onGetStringFromFile = [](const std::string& path) -> std::string{
- assert(!path.empty());
- std::string byteCodePath = removeFileExt(path) + BYTE_CODE_FILE_EXT;
- if (FileUtils::getInstance()->isFileExist(byteCodePath)) {
- Data fileData = FileUtils::getInstance()->getDataFromFile(byteCodePath);
- uint32_t dataLen;
- uint8_t* data = xxtea_decrypt((uint8_t*)fileData.getBytes(), (uint32_t)fileData.getSize(), (uint8_t*)xxteaKey.c_str(), (uint32_t)xxteaKey.size(), &dataLen);
- if (data == nullptr) {
- SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
- return "";
- }
- if (ZipUtils::isGZipBuffer(data,dataLen)) {
- uint8_t* unpackedData;
- ssize_t unpackedLen = ZipUtils::inflateMemory(data, dataLen,&unpackedData);
- if (unpackedData == nullptr) {
- SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
- return "";
- }
- std::string ret(reinterpret_cast<const char*>(unpackedData), unpackedLen);
- free(unpackedData);
- free(data);
- return ret;
- }
- else {
- std::string ret(reinterpret_cast<const char*>(data), dataLen);
- free(data);
- return ret;
- }
- }
- if (FileUtils::getInstance()->isFileExist(path)) {
- return FileUtils::getInstance()->getStringFromFile(path);
- }
- else {
- SE_LOGE("ScriptEngine::onGetStringFromFile %s not found, possible missing file.\n", path.c_str());
- }
- return "";
- };
- delegate.onGetFullPath = [](const std::string& path) -> std::string{
- assert(!path.empty());
- std::string byteCodePath = removeFileExt(path) + BYTE_CODE_FILE_EXT;
- if (FileUtils::getInstance()->isFileExist(byteCodePath)) {
- return FileUtils::getInstance()->fullPathForFilename(byteCodePath);
- }
- return FileUtils::getInstance()->fullPathForFilename(path);
- };
- delegate.onCheckFileExist = [](const std::string& path) -> bool{
- assert(!path.empty());
- return FileUtils::getInstance()->isFileExist(path);
- };
- assert(delegate.isValid());
- se::ScriptEngine::getInstance()->setFileOperationDelegate(delegate);
- }
- }
- bool jsb_enable_debugger(const std::string& debuggerServerAddr, uint32_t port, bool isWaitForConnect)
- {
- if (debuggerServerAddr.empty() || port == 0)
- return false;
- auto se = se::ScriptEngine::getInstance();
- se->enableDebugger(debuggerServerAddr.c_str(), port, isWaitForConnect);
- // For debugger main loop
- class SimpleRunLoop
- {
- public:
- void update(float dt)
- {
- se::ScriptEngine::getInstance()->mainLoopUpdate();
- }
- };
- // static SimpleRunLoop runLoop;
- //cjh IDEA: Director::getInstance()->getScheduler()->scheduleUpdate(&runLoop, 0, false);
- return true;
- }
- bool jsb_set_extend_property(const char* ns, const char* clsName)
- {
- se::Object* globalObj = se::ScriptEngine::getInstance()->getGlobalObject();
- se::Value nsVal;
- if (globalObj->getProperty(ns, &nsVal) && nsVal.isObject())
- {
- se::Value ccVal;
- if (globalObj->getProperty("cc", &ccVal) && ccVal.isObject())
- {
- se::Value ccClassVal;
- if (ccVal.toObject()->getProperty("Class", &ccClassVal) && ccClassVal.isObject())
- {
- se::Value extendVal;
- if (ccClassVal.toObject()->getProperty("extend", &extendVal) && extendVal.isObject() && extendVal.toObject()->isFunction())
- {
- se::Value targetClsVal;
- if (nsVal.toObject()->getProperty(clsName, &targetClsVal) && targetClsVal.isObject())
- {
- return targetClsVal.toObject()->setProperty("extend", extendVal);
- }
- }
- }
- }
- }
- return false;
- }
- namespace {
- std::unordered_map<std::string, se::Value> __moduleCache;
- static bool require(se::State& s)
- {
- const auto& args = s.args();
- int argc = (int)args.size();
- assert(argc >= 1);
- assert(args[0].isString());
- return jsb_run_script(args[0].toString(), &s.rval());
- }
- SE_BIND_FUNC(require)
- static bool doModuleRequire(const std::string& path, se::Value* ret, const std::string& prevScriptFileDir)
- {
- se::AutoHandleScope hs;
- assert(!path.empty());
- const auto& fileOperationDelegate = se::ScriptEngine::getInstance()->getFileOperationDelegate();
- assert(fileOperationDelegate.isValid());
- std::string fullPath;
- std::string pathWithSuffix = path;
- if (pathWithSuffix.rfind(".js") != (pathWithSuffix.length() - 3))
- pathWithSuffix += ".js";
- std::string scriptBuffer = fileOperationDelegate.onGetStringFromFile(pathWithSuffix);
- if (scriptBuffer.empty() && !prevScriptFileDir.empty())
- {
- std::string secondPath = prevScriptFileDir;
- if (secondPath[secondPath.length()-1] != '/')
- secondPath += "/";
- secondPath += path;
- if (FileUtils::getInstance()->isDirectoryExist(secondPath))
- {
- if (secondPath[secondPath.length()-1] != '/')
- secondPath += "/";
- secondPath += "index.js";
- }
- else
- {
- if (path.rfind(".js") != (path.length() - 3))
- secondPath += ".js";
- }
- fullPath = fileOperationDelegate.onGetFullPath(secondPath);
- scriptBuffer = fileOperationDelegate.onGetStringFromFile(fullPath);
- }
- else
- {
- fullPath = fileOperationDelegate.onGetFullPath(pathWithSuffix);
- }
- if (!scriptBuffer.empty())
- {
- const auto& iter = __moduleCache.find(fullPath);
- if (iter != __moduleCache.end())
- {
- *ret = iter->second;
- // printf("Found cache: %s, value: %d\n", fullPath.c_str(), (int)ret->getType());
- return true;
- }
- std::string currentScriptFileDir = FileUtils::getInstance()->getFileDir(fullPath);
- // Add closure for evalutate the script
- char prefix[] = "(function(currentScriptDir){ window.module = window.module || {}; var exports = window.module.exports = {}; ";
- char suffix[512] = {0};
- snprintf(suffix, sizeof(suffix), "\nwindow.module.exports = window.module.exports || exports;\n})('%s'); ", currentScriptFileDir.c_str());
- // Add current script path to require function invocation
- scriptBuffer = prefix + std::regex_replace(scriptBuffer, std::regex("([^A-Za-z0-9]|^)requireModule\\((.*?)\\)"), "$1requireModule($2, currentScriptDir)") + suffix;
- // FILE* fp = fopen("/Users/james/Downloads/test.txt", "wb");
- // fwrite(scriptBuffer.c_str(), scriptBuffer.length(), 1, fp);
- // fclose(fp);
- std::string reletivePath = fullPath;
- #if CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_IOS
- #if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
- const std::string reletivePathKey = "/Contents/Resources";
- #else
- const std::string reletivePathKey = ".app";
- #endif
- size_t pos = reletivePath.find(reletivePathKey);
- if (pos != std::string::npos)
- {
- reletivePath = reletivePath.substr(pos + reletivePathKey.length() + 1);
- }
- #endif
- // RENDERER_LOGD("Evaluate: %s", fullPath.c_str());
- auto se = se::ScriptEngine::getInstance();
- bool succeed = se->evalString(scriptBuffer.c_str(), scriptBuffer.length(), nullptr, reletivePath.c_str());
- se::Value moduleVal;
- if (succeed && se->getGlobalObject()->getProperty("module", &moduleVal) && moduleVal.isObject())
- {
- se::Value exportsVal;
- if (moduleVal.toObject()->getProperty("exports", &exportsVal))
- {
- if (ret != nullptr)
- *ret = exportsVal;
- __moduleCache[fullPath] = std::move(exportsVal);
- }
- else
- {
- __moduleCache[fullPath] = se::Value::Undefined;
- }
- // clear module.exports
- moduleVal.toObject()->setProperty("exports", se::Value::Undefined);
- }
- else
- {
- __moduleCache[fullPath] = se::Value::Undefined;
- }
- assert(succeed);
- return succeed;
- }
- SE_LOGE("doModuleRequire %s, buffer is empty!\n", path.c_str());
- assert(false);
- return false;
- }
- static bool moduleRequire(se::State& s)
- {
- const auto& args = s.args();
- int argc = (int)args.size();
- assert(argc >= 2);
- assert(args[0].isString());
- assert(args[1].isString());
- return doModuleRequire(args[0].toString(), &s.rval(), args[1].toString());
- }
- SE_BIND_FUNC(moduleRequire)
- } // namespace {
- bool jsb_run_script(const std::string& filePath, se::Value* rval/* = nullptr */)
- {
- se::AutoHandleScope hs;
- return se::ScriptEngine::getInstance()->runScript(filePath, rval);
- }
- bool jsb_run_script_module(const std::string& filePath, se::Value* rval/* = nullptr */)
- {
- return doModuleRequire(filePath, rval, "");
- }
- static bool jsc_garbageCollect(se::State& s)
- {
- se::ScriptEngine::getInstance()->garbageCollect();
- return true;
- }
- SE_BIND_FUNC(jsc_garbageCollect)
- static bool jsc_dumpNativePtrToSeObjectMap(se::State& s)
- {
- cocos2d::log(">>> total: %d, Dump (native -> jsobj) map begin", (int)se::NativePtrToObjectMap::size());
- struct NamePtrStruct
- {
- const char* name;
- void* ptr;
- };
- std::vector<NamePtrStruct> namePtrArray;
- for (const auto& e : se::NativePtrToObjectMap::instance())
- {
- se::Object* jsobj = e.second;
- assert(jsobj->_getClass() != nullptr);
- NamePtrStruct tmp;
- tmp.name = jsobj->_getClass()->getName();
- tmp.ptr = e.first;
- namePtrArray.push_back(tmp);
- }
- std::sort(namePtrArray.begin(), namePtrArray.end(), [](const NamePtrStruct& a, const NamePtrStruct& b) -> bool {
- std::string left = a.name;
- std::string right = b.name;
- for( std::string::const_iterator lit = left.begin(), rit = right.begin(); lit != left.end() && rit != right.end(); ++lit, ++rit )
- if( ::tolower( *lit ) < ::tolower( *rit ) )
- return true;
- else if( ::tolower( *lit ) > ::tolower( *rit ) )
- return false;
- if( left.size() < right.size() )
- return true;
- return false;
- });
- for (const auto& e : namePtrArray)
- {
- cocos2d::log("%s: %p", e.name, e.ptr);
- }
- cocos2d::log(">>> total: %d, nonRefMap: %d, Dump (native -> jsobj) map end", (int)se::NativePtrToObjectMap::size(), (int)se::NonRefNativePtrCreatedByCtorMap::size());
- return true;
- }
- SE_BIND_FUNC(jsc_dumpNativePtrToSeObjectMap)
- static bool jsc_dumpRoot(se::State& s)
- {
- assert(false);
- return true;
- }
- SE_BIND_FUNC(jsc_dumpRoot)
- static bool JSBCore_platform(se::State& s)
- {
- Application::Platform platform = Application::getInstance()->getPlatform();
- s.rval().setInt32((int32_t)platform);
- return true;
- }
- SE_BIND_FUNC(JSBCore_platform)
- static bool JSBCore_version(se::State& s)
- {
- //cjh char version[256];
- // snprintf(version, sizeof(version)-1, "%s", cocos2dVersion());
- //
- // s.rval().setString(version);
- return true;
- }
- SE_BIND_FUNC(JSBCore_version)
- static bool JSBCore_os(se::State& s)
- {
- se::Value os;
- // osx, ios, android, windows, linux, etc..
- #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
- os.setString("iOS");
- #elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
- os.setString("Android");
- #elif (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
- os.setString("Windows");
- #elif (CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE)
- os.setString("Marmalade");
- #elif (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
- os.setString("Linux");
- #elif (CC_TARGET_PLATFORM == CC_PLATFORM_BADA)
- os.setString("Bada");
- #elif (CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY)
- os.setString("Blackberry");
- #elif (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
- os.setString("OS X");
- #elif (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
- os.setString("WINRT");
- #else
- os.setString("Unknown");
- #endif
- s.rval() = os;
- return true;
- }
- SE_BIND_FUNC(JSBCore_os)
- static bool JSBCore_getCurrentLanguage(se::State& s)
- {
- std::string languageStr;
- Application::LanguageType language = Application::getInstance()->getCurrentLanguage();
- switch (language)
- {
- case Application::LanguageType::ENGLISH:
- languageStr = "en";
- break;
- case Application::LanguageType::CHINESE:
- languageStr = "zh";
- break;
- case Application::LanguageType::FRENCH:
- languageStr = "fr";
- break;
- case Application::LanguageType::ITALIAN:
- languageStr = "it";
- break;
- case Application::LanguageType::GERMAN:
- languageStr = "de";
- break;
- case Application::LanguageType::SPANISH:
- languageStr = "es";
- break;
- case Application::LanguageType::DUTCH:
- languageStr = "du";
- break;
- case Application::LanguageType::RUSSIAN:
- languageStr = "ru";
- break;
- case Application::LanguageType::KOREAN:
- languageStr = "ko";
- break;
- case Application::LanguageType::JAPANESE:
- languageStr = "ja";
- break;
- case Application::LanguageType::HUNGARIAN:
- languageStr = "hu";
- break;
- case Application::LanguageType::PORTUGUESE:
- languageStr = "pt";
- break;
- case Application::LanguageType::ARABIC:
- languageStr = "ar";
- break;
- case Application::LanguageType::NORWEGIAN:
- languageStr = "no";
- break;
- case Application::LanguageType::POLISH:
- languageStr = "pl";
- break;
- case Application::LanguageType::TURKISH:
- languageStr = "tr";
- break;
- case Application::LanguageType::UKRAINIAN:
- languageStr = "uk";
- break;
- case Application::LanguageType::ROMANIAN:
- languageStr = "ro";
- break;
- case Application::LanguageType::BULGARIAN:
- languageStr = "bg";
- break;
- default:
- languageStr = "unknown";
- break;
- }
- s.rval().setString(languageStr);
- return true;
- }
- SE_BIND_FUNC(JSBCore_getCurrentLanguage)
- static bool JSBCore_getCurrentLanguageCode(se::State& s)
- {
- std::string language = Application::getInstance()->getCurrentLanguageCode();
- s.rval().setString(language);
- return true;
- }
- SE_BIND_FUNC(JSBCore_getCurrentLanguageCode)
- static bool JSB_getOSVersion(se::State& s)
- {
- std::string systemVersion = Application::getInstance()->getSystemVersion();
- s.rval().setString(systemVersion);
- return true;
- }
- SE_BIND_FUNC(JSB_getOSVersion)
- static bool JSB_cleanScript(se::State& s)
- {
- assert(false); //IDEA:
- return true;
- }
- SE_BIND_FUNC(JSB_cleanScript)
- static bool JSB_core_restartVM(se::State& s)
- {
- //REFINE: release AudioEngine, waiting HttpClient & WebSocket threads to exit.
- Application::getInstance()->restart();
- return true;
- }
- SE_BIND_FUNC(JSB_core_restartVM)
- static bool JSB_closeWindow(se::State& s)
- {
- Application::getInstance()->end();
- return true;
- }
- SE_BIND_FUNC(JSB_closeWindow)
- static bool JSB_isObjectValid(se::State& s)
- {
- const auto& args = s.args();
- int argc = (int)args.size();
- if (argc == 1)
- {
- void* nativePtr = nullptr;
- seval_to_native_ptr(args[0], &nativePtr);
- s.rval().setBoolean(nativePtr != nullptr);
- return true;
- }
- SE_REPORT_ERROR("Invalid number of arguments: %d. Expecting: 1", argc);
- return false;
- }
- SE_BIND_FUNC(JSB_isObjectValid)
- static bool getOrCreatePlainObject_r(const char* name, se::Object* parent, se::Object** outObj)
- {
- assert(parent != nullptr);
- assert(outObj != nullptr);
- se::Value tmp;
- if (parent->getProperty(name, &tmp) && tmp.isObject())
- {
- *outObj = tmp.toObject();
- (*outObj)->incRef();
- }
- else
- {
- *outObj = se::Object::createPlainObject();
- parent->setProperty(name, se::Value(*outObj));
- }
- return true;
- }
- static bool js_performance_now(se::State& s)
- {
- auto now = std::chrono::steady_clock::now();
- auto micro = std::chrono::duration_cast<std::chrono::microseconds>(now - se::ScriptEngine::getInstance()->getStartTime()).count();
- s.rval().setNumber((double)micro * 0.001);
- return true;
- }
- SE_BIND_FUNC(js_performance_now)
- namespace
- {
- struct ImageInfo
- {
- ~ImageInfo()
- {
- if (freeData)
- delete [] data;
- }
- uint32_t length = 0;
- uint32_t width = 0;
- uint32_t height = 0;
- uint8_t* data = nullptr;
- GLenum glFormat = GL_RGBA;
- GLenum glInternalFormat = GL_RGBA;
- GLenum type = GL_UNSIGNED_BYTE;
- uint8_t bpp = 0;
- uint8_t numberOfMipmaps = 0;
- bool hasAlpha = false;
- bool hasPremultipliedAlpha = false;
- bool compressed = false;
- bool freeData = false;
- };
- uint8_t* convertRGB2RGBA (uint32_t length, uint8_t* src) {
- uint8_t* dst = new uint8_t[length];
- for (uint32_t i = 0; i < length; i += 4) {
- dst[i] = *src++;
- dst[i + 1] = *src++;
- dst[i + 2] = *src++;
- dst[i + 3] = 255;
- }
- return dst;
- }
- uint8_t* convertIA2RGBA (uint32_t length, uint8_t* src) {
- uint8_t* dst = new uint8_t[length];
- for (uint32_t i = 0; i < length; i += 4) {
- dst[i] = *src;
- dst[i + 1] = *src;
- dst[i + 2] = *src++;
- dst[i + 3] = *src++;
- }
- return dst;
- }
- uint8_t* convertI2RGBA (uint32_t length, uint8_t* src) {
- uint8_t* dst = new uint8_t[length];
- for (uint32_t i = 0; i < length; i += 4) {
- dst[i] = *src;
- dst[i + 1] = *src;
- dst[i + 2] = *src++;
- dst[i + 3] = 255;
- }
- return dst;
- }
- struct ImageInfo* createImageInfo(const Image* img)
- {
- struct ImageInfo* imgInfo = new struct ImageInfo();
- imgInfo->length = (uint32_t)img->getDataLen();
- imgInfo->width = img->getWidth();
- imgInfo->height = img->getHeight();
- imgInfo->data = img->getData();
- const auto& pixelFormatInfo = img->getPixelFormatInfo();
- imgInfo->glFormat = pixelFormatInfo.format;
- imgInfo->glInternalFormat = pixelFormatInfo.internalFormat;
- imgInfo->type = pixelFormatInfo.type;
- imgInfo->bpp = img->getBitPerPixel();
- imgInfo->numberOfMipmaps = img->getNumberOfMipmaps();
- imgInfo->hasAlpha = img->hasAlpha();
- imgInfo->hasPremultipliedAlpha = img->hasPremultipliedAlpha();
- imgInfo->compressed = img->isCompressed();
- // Convert to RGBA888 because standard web api will return only RGBA888.
- // If not, then it may have issue in glTexSubImage. For example, engine
- // will create a big texture, and update its content with small pictures.
- // The big texture is RGBA888, then the small picture should be the same
- // format, or it will cause 0x502 error on OpenGL ES 2.
- if (!imgInfo->compressed && imgInfo->glFormat != GL_RGBA) {
- imgInfo->length = img->getWidth() * img->getHeight() * 4;
- uint8_t* dst = nullptr;
- uint32_t length = imgInfo->length;
- uint8_t* src = imgInfo->data;
- switch(imgInfo->glFormat) {
- case GL_LUMINANCE_ALPHA:
- dst = convertIA2RGBA(length, src);
- break;
- case GL_ALPHA:
- case GL_LUMINANCE:
- dst = convertI2RGBA(length, src);
- break;
- case GL_RGB:
- dst = convertRGB2RGBA(length, src);
- break;
- default:
- SE_LOGE("unknown image format");
- break;
- }
- imgInfo->data = dst;
- imgInfo->hasAlpha = true;
- imgInfo->bpp = 32;
- imgInfo->glFormat = GL_RGBA;
- imgInfo->glInternalFormat = GL_RGBA;
- imgInfo->freeData = true;
- }
- return imgInfo;
- }
- }
- bool jsb_global_load_image(const std::string& path, const se::Value& callbackVal) {
- if (path.empty())
- {
- se::ValueArray seArgs;
- callbackVal.toObject()->call(seArgs, nullptr);
- return true;
- }
-
- std::shared_ptr<se::Value> callbackPtr = std::make_shared<se::Value>(callbackVal);
- auto initImageFunc = [path, callbackPtr](const std::string& fullPath, unsigned char* imageData, int imageBytes, const std::string& errorMsg){
- std::shared_ptr<uint8_t> imageDataGuard(imageData, free);
- auto pool = g_threadPool;
- if (!pool)
- return;
- pool->pushTask([=](int tid) mutable {
- // NOTE: FileUtils::getInstance()->fullPathForFilename isn't a threadsafe method,
- // Image::initWithImageFile will call fullPathForFilename internally which may
- // cause thread race issues. Therefore, we get the full path of file before
- // going into task callback.
- // Be careful of invoking any Cocos2d-x interface in a sub-thread.
- bool loadSucceed = false;
- std::shared_ptr<Image> img(new Image(), [](Image *image) {
- image->release();
- });
- if (!errorMsg.empty()) {
- loadSucceed = false;
- }
- else if (fullPath.empty())
- {
- loadSucceed = img->initWithImageData(imageDataGuard.get(), imageBytes);
- imageDataGuard = nullptr;
- }
- else
- {
- loadSucceed = img->initWithImageFile(fullPath);
- }
- std::shared_ptr<ImageInfo> imgInfo;
- if(loadSucceed)
- {
- imgInfo.reset(createImageInfo(img.get()));
- }
- Application::getInstance()->getScheduler()->performFunctionInCocosThread([=]() mutable {
- se::AutoHandleScope hs;
- se::ValueArray seArgs;
- se::Value dataVal;
-
- if (loadSucceed)
- {
- se::HandleObject retObj(se::Object::createPlainObject());
- Data data;
- data.fastSet(imgInfo->data, imgInfo->length);
- Data_to_seval(data, &dataVal);
- data.takeBuffer();
- retObj->setProperty("data", dataVal);
- retObj->setProperty("width", se::Value(imgInfo->width));
- retObj->setProperty("height", se::Value(imgInfo->height));
- retObj->setProperty("premultiplyAlpha", se::Value(imgInfo->hasPremultipliedAlpha));
- retObj->setProperty("bpp", se::Value(imgInfo->bpp));
- retObj->setProperty("hasAlpha", se::Value(imgInfo->hasAlpha));
- retObj->setProperty("compressed", se::Value(imgInfo->compressed));
- retObj->setProperty("numberOfMipmaps", se::Value(imgInfo->numberOfMipmaps));
- if (imgInfo->numberOfMipmaps > 0)
- {
- se::HandleObject mipmapArray(se::Object::createArrayObject(imgInfo->numberOfMipmaps));
- retObj->setProperty("mipmaps", se::Value(mipmapArray));
- auto mipmapInfo = img->getMipmaps();
- for (int i = 0; i < imgInfo->numberOfMipmaps; ++i)
- {
- se::HandleObject info(se::Object::createPlainObject());
- info->setProperty("offset", se::Value(mipmapInfo[i].offset));
- info->setProperty("length", se::Value(mipmapInfo[i].len));
- mipmapArray->setArrayElement(i, se::Value(info));
- }
- }
- retObj->setProperty("glFormat", se::Value(imgInfo->glFormat));
- retObj->setProperty("glInternalFormat", se::Value(imgInfo->glInternalFormat));
- retObj->setProperty("glType", se::Value(imgInfo->type));
- seArgs.push_back(se::Value(retObj));
- imgInfo = nullptr;
- }
- else
- {
- SE_REPORT_ERROR("initWithImageFile: %s failed!", path.c_str());
- }
- if (!errorMsg.empty()) {
- se::HandleObject retObj(se::Object::createPlainObject());
- retObj->setProperty("errorMsg", se::Value(errorMsg));
- seArgs.push_back(se::Value(retObj));
- }
- callbackPtr->toObject()->call(seArgs, nullptr);
- img = nullptr;
- });
- });
- };
- size_t pos = std::string::npos;
- if (path.find("http://") == 0 || path.find("https://") == 0)
- {
- localDownloaderCreateTask(path, initImageFunc);
- }
- else if (path.find("data:") == 0 && (pos = path.find("base64,")) != std::string::npos)
- {
- int imageBytes = 0;
- unsigned char* imageData = nullptr;
- size_t dataStartPos = pos + strlen("base64,");
- const char* base64Data = path.data() + dataStartPos;
- size_t dataLen = path.length() - dataStartPos;
- imageBytes = base64Decode((const unsigned char *)base64Data, (unsigned int)dataLen, &imageData);
- if (imageBytes <= 0 || imageData == nullptr)
- {
- SE_REPORT_ERROR("Decode base64 image data failed!");
- return false;
- }
- initImageFunc("", imageData, imageBytes, "");
- }
- else
- {
- std::string fullPath(FileUtils::getInstance()->fullPathForFilename(path));
- if (0 == path.find("file://"))
- fullPath = FileUtils::getInstance()->fullPathForFilename(path.substr(strlen("file://")));
- if (fullPath.empty())
- {
- SE_REPORT_ERROR("File (%s) doesn't exist!", path.c_str());
- return false;
- }
- initImageFunc(fullPath, nullptr, 0, "");
- }
- return true;
- }
- static bool js_loadImage(se::State& s)
- {
- const auto& args = s.args();
- size_t argc = args.size();
- CC_UNUSED bool ok = true;
- if (argc == 2) {
- std::string path;
- ok &= seval_to_std_string(args[0], &path);
- SE_PRECONDITION2(ok, false, "js_loadImage : Error processing arguments");
- se::Value callbackVal = args[1];
- assert(callbackVal.isObject());
- assert(callbackVal.toObject()->isFunction());
- return jsb_global_load_image(path, callbackVal);
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
- return false;
- }
- SE_BIND_FUNC(js_loadImage)
- //pixels(RGBA), width, height, fullFilePath(*.png/*.jpg)
- static bool js_saveImageData(se::State& s)
- {
- const auto& args = s.args();
- size_t argc = args.size();
- CC_UNUSED bool ok = true;
- if (argc == 4) {
- cocos2d::Data data;
- ok &= seval_to_Data(args[0], &data);
- uint32_t width, height;
- ok &= seval_to_uint32(args[1], &width);
- ok &= seval_to_uint32(args[2], &height);
- std::string filePath;
- ok &= seval_to_std_string(args[3], &filePath);
- SE_PRECONDITION2(ok, false, "js_saveImageData : Error processing arguments");
- Image* img = new Image();
- img->initWithRawData(data.getBytes(), data.getSize(), width, height, 8);
- // isToRGB = false, to keep alpha channel
- bool ret = img->saveToFile(filePath, false);
- s.rval().setBoolean(ret);
- img->release();
- return ret;
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
- return false;
- }
- SE_BIND_FUNC(js_saveImageData)
- static bool js_setDebugViewText(se::State& s)
- {
- const auto& args = s.args();
- size_t argc = args.size();
- CC_UNUSED bool ok = true;
- if (argc == 2) {
- int32_t index;
- ok = seval_to_int32(args[0], &index);
- SE_PRECONDITION2(ok, false, "Convert arg0 index failed!");
- std::string text;
- ok = seval_to_std_string(args[1], &text);
- SE_PRECONDITION2(ok, false, "Convert arg1 text failed!");
- #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
- setGameInfoDebugViewTextJNI(index, text);
- #endif
- return true;
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
- return false;
- }
- SE_BIND_FUNC(js_setDebugViewText)
- static bool js_openDebugView(se::State& s)
- {
- #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
- openDebugViewJNI();
- #endif
- return true;
- }
- SE_BIND_FUNC(js_openDebugView)
- static bool js_disableBatchGLCommandsToNative(se::State& s)
- {
- #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
- disableBatchGLCommandsToNativeJNI();
- #endif
- return true;
- }
- SE_BIND_FUNC(js_disableBatchGLCommandsToNative)
- static bool JSB_openURL(se::State& s)
- {
- const auto& args = s.args();
- size_t argc = args.size();
- CC_UNUSED bool ok = true;
- if (argc > 0) {
- std::string url;
- ok = seval_to_std_string(args[0], &url);
- SE_PRECONDITION2(ok, false, "url is invalid!");
- Application::getInstance()->openURL(url);
- return true;
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
- return false;
- }
- SE_BIND_FUNC(JSB_openURL)
- static bool JSB_copyTextToClipboard(se::State& s)
- {
- const auto& args = s.args();
- size_t argc = args.size();
- CC_UNUSED bool ok = true;
- if (argc > 0) {
- std::string text;
- ok = seval_to_std_string(args[0], &text);
- SE_PRECONDITION2(ok, false, "text is invalid!");
- Application::getInstance()->copyTextToClipboard(text);
- return true;
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
- return false;
- }
- SE_BIND_FUNC(JSB_copyTextToClipboard)
- static bool JSB_setPreferredFramesPerSecond(se::State& s)
- {
- const auto& args = s.args();
- size_t argc = args.size();
- CC_UNUSED bool ok = true;
- if (argc > 0) {
- int32_t fps;
- ok = seval_to_int32(args[0], &fps);
- SE_PRECONDITION2(ok, false, "fps is invalid!");
- Application::getInstance()->setPreferredFramesPerSecond(fps);
- return true;
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
- return false;
- }
- SE_BIND_FUNC(JSB_setPreferredFramesPerSecond)
- static bool JSB_showInputBox(se::State& s)
- {
- const auto& args = s.args();
- size_t argc = args.size();
- CC_UNUSED bool ok = true;
- if (argc == 1)
- {
- bool ok;
- se::Value tmp;
- const auto& obj = args[0].toObject();
- cocos2d::EditBox::ShowInfo showInfo;
- ok = obj->getProperty("defaultValue", &tmp);
- SE_PRECONDITION2(ok && tmp.isString(), false, "defaultValue is invalid!");
- showInfo.defaultValue = tmp.toString();
- ok = obj->getProperty("maxLength", &tmp);
- SE_PRECONDITION2(ok && tmp.isNumber(), false, "maxLength is invalid!");
- showInfo.maxLength = tmp.toInt32();
- ok = obj->getProperty("multiple", &tmp);
- SE_PRECONDITION2(ok && tmp.isBoolean(), false, "multiple is invalid!");
- showInfo.isMultiline = tmp.toBoolean();
- if (obj->getProperty("confirmHold", &tmp))
- {
- SE_PRECONDITION2(tmp.isBoolean(), false, "confirmHold is invalid!");
- if (! tmp.isUndefined())
- showInfo.confirmHold = tmp.toBoolean();
- }
- if (obj->getProperty("confirmType", &tmp))
- {
- SE_PRECONDITION2(tmp.isString(), false, "confirmType is invalid!");
- if (!tmp.isUndefined())
- showInfo.confirmType = tmp.toString();
- }
- if (obj->getProperty("inputType", &tmp))
- {
- SE_PRECONDITION2(tmp.isString(), false, "inputType is invalid!");
- if (! tmp.isUndefined())
- showInfo.inputType = tmp.toString();
- }
- if (obj->getProperty("originX", &tmp))
- {
- SE_PRECONDITION2(tmp.isNumber(), false, "originX is invalid!");
- if (! tmp.isUndefined())
- showInfo.x = tmp.toInt32();
- }
- if (obj->getProperty("originY", &tmp))
- {
- SE_PRECONDITION2(tmp.isNumber(), false, "originY is invalid!");
- if (! tmp.isUndefined())
- showInfo.y = tmp.toInt32();
- }
- if (obj->getProperty("width", &tmp))
- {
- SE_PRECONDITION2(tmp.isNumber(), false, "width is invalid!");
- if (! tmp.isUndefined())
- showInfo.width = tmp.toInt32();
- }
- if (obj->getProperty("height", &tmp))
- {
- SE_PRECONDITION2(tmp.isNumber(), false, "height is invalid!");
- if (! tmp.isUndefined())
- showInfo.height = tmp.toInt32();
- }
- EditBox::show(showInfo);
- return true;
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
- return false;
- }
- SE_BIND_FUNC(JSB_showInputBox);
- static bool JSB_updateInputBoxRect(se::State& s)
- {
- const auto& args = s.args();
- size_t argc = args.size();
- if (argc == 4)
- {
- SE_PRECONDITION2(args[0].isNumber(), false, "x is invalid!");
- const auto& x = args[0].toInt32();
-
- SE_PRECONDITION2(args[1].isNumber(), false, "y is invalid!");
- const auto& y = args[1].toInt32();
-
- SE_PRECONDITION2(args[2].isNumber(), false, "width is invalid!");
- const auto& width = args[2].toInt32();
-
-
- SE_PRECONDITION2(args[3].isNumber(), false, "height is invalid!");
- const auto& height = args[3].toInt32();
-
- EditBox::updateRect(x, y, width, height);
- return true;
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 4);
- return false;
- }
- SE_BIND_FUNC(JSB_updateInputBoxRect);
- static bool JSB_hideInputBox(se::State& s)
- {
- EditBox::hide();
- return true;
- }
- SE_BIND_FUNC(JSB_hideInputBox)
- bool jsb_register_global_variables(se::Object* global)
- {
- g_threadPool.reset(ThreadPool::newFixedThreadPool(3));
- global->defineFunction("require", _SE(require));
- global->defineFunction("requireModule", _SE(moduleRequire));
- getOrCreatePlainObject_r("jsb", global, &__jsbObj);
- auto glContextCls = se::Class::create("WebGLRenderingContext", global, nullptr, nullptr);
- glContextCls->install();
- SAFE_DEC_REF(__glObj);
- __glObj = se::Object::createObjectWithClass(glContextCls);
- global->setProperty("__gl", se::Value(__glObj));
- __jsbObj->defineFunction("garbageCollect", _SE(jsc_garbageCollect));
- __jsbObj->defineFunction("dumpNativePtrToSeObjectMap", _SE(jsc_dumpNativePtrToSeObjectMap));
- __jsbObj->defineFunction("loadImage", _SE(js_loadImage));
- __jsbObj->defineFunction("saveImageData", _SE(js_saveImageData));
- __jsbObj->defineFunction("setDebugViewText", _SE(js_setDebugViewText));
- __jsbObj->defineFunction("openDebugView", _SE(js_openDebugView));
- __jsbObj->defineFunction("disableBatchGLCommandsToNative", _SE(js_disableBatchGLCommandsToNative));
- __jsbObj->defineFunction("openURL", _SE(JSB_openURL));
- __jsbObj->defineFunction("copyTextToClipboard", _SE(JSB_copyTextToClipboard));
- __jsbObj->defineFunction("setPreferredFramesPerSecond", _SE(JSB_setPreferredFramesPerSecond));
- __jsbObj->defineFunction("showInputBox", _SE(JSB_showInputBox));
- __jsbObj->defineFunction("hideInputBox", _SE(JSB_hideInputBox));
- __jsbObj->defineFunction("updateInputBoxRect", _SE(JSB_updateInputBoxRect));
- global->defineFunction("__getPlatform", _SE(JSBCore_platform));
- global->defineFunction("__getOS", _SE(JSBCore_os));
- global->defineFunction("__getOSVersion", _SE(JSB_getOSVersion));
- global->defineFunction("__getCurrentLanguage", _SE(JSBCore_getCurrentLanguage));
- global->defineFunction("__getCurrentLanguageCode", _SE(JSBCore_getCurrentLanguageCode));
- global->defineFunction("__getVersion", _SE(JSBCore_version));
- global->defineFunction("__restartVM", _SE(JSB_core_restartVM));
- global->defineFunction("__cleanScript", _SE(JSB_cleanScript));
- global->defineFunction("__isObjectValid", _SE(JSB_isObjectValid));
- global->defineFunction("close", _SE(JSB_closeWindow));
- se::HandleObject performanceObj(se::Object::createPlainObject());
- performanceObj->defineFunction("now", _SE(js_performance_now));
- global->setProperty("performance", se::Value(performanceObj));
- se::ScriptEngine::getInstance()->clearException();
- se::ScriptEngine::getInstance()->addBeforeCleanupHook([](){
- g_threadPool = nullptr;
- PoolManager::getInstance()->getCurrentPool()->clear();
- });
- se::ScriptEngine::getInstance()->addAfterCleanupHook([](){
- PoolManager::getInstance()->getCurrentPool()->clear();
- __moduleCache.clear();
- SAFE_DEC_REF(__jsbObj);
- SAFE_DEC_REF(__glObj);
- });
- return true;
- }
|