[engine] [cocos2d-x] [jsb-adapter] 适配引擎 v2.4.12 版本

This commit is contained in:
SmallMain
2023-10-30 22:32:32 +08:00
parent 2508616ad9
commit 0092eb9f05
787 changed files with 206249 additions and 422 deletions

View File

@@ -0,0 +1,86 @@
/****************************************************************************
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 "AppDelegate.h"
#include "cocos2d.h"
#include "cocos/scripting/js-bindings/manual/jsb_module_register.hpp"
#include "cocos/scripting/js-bindings/manual/jsb_global.h"
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
#include "cocos/scripting/js-bindings/event/EventDispatcher.h"
#include "cocos/scripting/js-bindings/manual/jsb_classtype.hpp"
USING_NS_CC;
AppDelegate::AppDelegate(int width, int height) : Application("Cocos Game", width, height)
{
}
AppDelegate::~AppDelegate()
{
}
bool AppDelegate::applicationDidFinishLaunching()
{
se::ScriptEngine *se = se::ScriptEngine::getInstance();
jsb_set_xxtea_key("");
jsb_init_file_operation_delegate();
#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
// Enable debugger here
jsb_enable_debugger("0.0.0.0", 6086, false);
#endif
se->setExceptionCallback([](const char *location, const char *message, const char *stack) {
// Send exception information to server like Tencent Bugly.
cocos2d::log("\nUncaught Exception:\n - location : %s\n - msg : %s\n - detail : \n %s\n", location, message, stack);
});
jsb_register_all_modules();
se->start();
se::AutoHandleScope hs;
// jsb_run_script("jsb-adapter/jsb-builtin.js");
// jsb_run_script("main.js");
se->addAfterCleanupHook([]() {
JSBClassType::destroy();
});
return true;
}
// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::onPause()
{
}
// this function will be called when the app is active again
void AppDelegate::onResume()
{
}

View File

@@ -0,0 +1,55 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "platform/CCApplication.h"
/**
@brief The cocos2d Application.
The reason for implement as private inheritance is to hide some interface call by Director.
*/
class AppDelegate : public cocos2d::Application
{
public:
AppDelegate(int width, int height);
virtual ~AppDelegate();
/**
@brief Implement Director and Scene init code here.
@return true Initialize success, app continue.
@return false Initialize failed, app terminate.
*/
virtual bool applicationDidFinishLaunching() override;
/**
@brief The function be called when the application is paused
*/
virtual void onPause() override;
/**
@brief The function be called when the application is resumed
*/
virtual void onResume() override;
};

View File

@@ -0,0 +1,143 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_OPENHARMONY
#include "platform/CCDevice.h"
#include "platform/openharmony/napi/NapiHelper.h"
NS_CC_BEGIN
int Device::getDPI() {
float value;
NapiHelper::napiCallFunction("getDPI", &value);
return value;
}
int Device::getDevicePixelRatio() {
// float value;
// NapiHelper::napiCallFunction("getPixelRation", &value);
// return value;
// TODO(qgh):openharmony does support this interface, but returning a value of 1.5 will cause the entire page to zoom in.
return 1;
}
void Device::setKeepScreenOn(bool value) {
CC_UNUSED_PARAM(value);
}
cocos2d::Vec4 Device::getSafeAreaEdge() {
return cocos2d::Vec4();
}
Device::Rotation Device::getDeviceRotation() {
int32_t value = 0;
NapiHelper::napiCallFunction("getDeviceOrientation", &value);
if(value == 0) {
return cocos2d::Device::Rotation::_0;
} else if(value == 1) {
// TODO(qgh): The openharmony platform is rotated clockwise.
return cocos2d::Device::Rotation::_270;
} else if(value == 2) {
return cocos2d::Device::Rotation::_180;
} else if(value == 3) {
// TODO(qgh): The openharmony platform is rotated clockwise.
return cocos2d::Device::Rotation::_90;
}
CC_ASSERT(false);
return cocos2d::Device::Rotation::_0;
}
Device::NetworkType Device::getNetworkType() {
int32_t value;
NapiHelper::napiCallFunction("getNetworkType", &value);
if(value == 0) {
return cocos2d::Device::NetworkType::WWAN;
} else if(value == 1 or value == 3) {
return cocos2d::Device::NetworkType::LAN;
} else {
return cocos2d::Device::NetworkType::NONE;
}
}
float Device::getBatteryLevel() {
int32_t value;
NapiHelper::napiCallFunction("getBatteryLevel", &value);
return value;
}
const Device::MotionValue& Device::getDeviceMotionValue() {
std::vector<float> v;
NapiHelper::napiCallFunction<std::vector<float> >("getDeviceMotionValue", &v);
static MotionValue motionValue;
if (!v.empty()) {
motionValue.accelerationIncludingGravityX = v[0];
motionValue.accelerationIncludingGravityY = v[1];
motionValue.accelerationIncludingGravityZ = v[2];
motionValue.accelerationX = v[3];
motionValue.accelerationY = v[4];
motionValue.accelerationZ = v[5];
motionValue.rotationRateAlpha = v[6];
motionValue.rotationRateBeta = v[7];
motionValue.rotationRateGamma = v[8];
} else {
memset(&motionValue, 0, sizeof(motionValue));
}
return motionValue;
}
std::string Device::getDeviceModel() {
std::string str;
NapiHelper::napiCallFunction<std::string>("getDeviceModel", &str);
return str;
}
void Device::setAccelerometerEnabled(bool isEnabled) {
// if (isEnabled)
// {
// JniHelper::callStaticVoidMethod(JCLS_HELPER, "enableAccelerometer");
// }
// else
// {
// JniHelper::callStaticVoidMethod(JCLS_HELPER, "disableAccelerometer");
// }
}
void Device::setAccelerometerInterval(float interval) {
// JniHelper::callStaticVoidMethod(JCLS_HELPER, "setAccelerometerInterval", interval);
}
void Device::vibrate(float duration) {
int32_t value = 0;
NapiHelper::napiCallFunctionByFloatArgs("vibrate", duration, &value);
}
NS_CC_END
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_OPENHARMONY

View File

@@ -0,0 +1,80 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __CCGL_H__
#define __CCGL_H__
#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_OPENHARMONY
#define glClearDepth glClearDepthf
#define glDeleteVertexArrays glDeleteVertexArraysOES
#define glGenVertexArrays glGenVertexArraysOES
#define glBindVertexArray glBindVertexArrayOES
#define glMapBuffer glMapBufferOES
#define glUnmapBuffer glUnmapBufferOES
#define glTexImage3D glTexImage3DOES
#define glCompressedTexImage3D glCompressedTexImage3DOES
#define glCompressedTexSubImage3D glCompressedTexSubImage3DOES
#define glTexSubImage3D glTexSubImage3DOES
#define glDepthRange glDepthRangef
#define glSubImage3D glSubImage3DOES
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
#define GL_WRITE_ONLY GL_WRITE_ONLY_OES
// GL_GLEXT_PROTOTYPES isn't defined in glplatform.h on android ndk r7
// we manually define it here
#include <GLES2/gl2platform.h>
#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES 1
#endif
// normal process
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
// gl2.h doesn't define GLchar on Android
typedef char GLchar;
// android defines GL_BGRA_EXT but not GL_BRGA
#ifndef GL_BGRA
#define GL_BGRA 0x80E1
#endif
//declare here while define in EGLView_android.cpp
extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOESEXT;
extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOESEXT;
extern PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOESEXT;
#define glGenVertexArraysOES glGenVertexArraysOESEXT
#define glBindVertexArrayOES glBindVertexArrayOESEXT
#define glDeleteVertexArraysOES glDeleteVertexArraysOESEXT
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_OPENHARMONY
#endif // __CCGL_H__

View File

@@ -0,0 +1,66 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __CCPLATFORMDEFINE_H__
#define __CCPLATFORMDEFINE_H__
#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_OPENHARMONY
#include <sys/types.h>
#include <hilog/log.h>
#define CC_DLL
#define CC_NO_MESSAGE_PSEUDOASSERT(cond) \
if (!(cond)) { \
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN, "HMG_LOG", \
"assert file:%{public}s function:%{public}s line:%{public}d", \
__FILE__, __FUNCTION__, __LINE__); \
}
#define CC_MESSAGE_PSEUDOASSERT(cond, msg) \
if (!(cond)) { \
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN, "HMG_LOG", \
"assert file:%{public}s function:%{public}s line:%{public}d, %{public}s", \
__FILE__, __FUNCTION__, __LINE__, msg); \
}
#define CC_ASSERT(cond) CC_NO_MESSAGE_PSEUDOASSERT(cond)
#define CC_UNUSED_PARAM(unusedparam) (void)unusedparam
/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
#endif /* __CCPLATFORMDEFINE_H__*/

View File

@@ -0,0 +1,233 @@
/****************************************************************************
Copyright (c) 2021-2023 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 "cocos/platform/openharmony/FileUtils-openharmony.h"
#include <hilog/log.h>
#include <sys/stat.h>
#include <cstdio>
#include <regex>
#include <string>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <assert.h>
#include "base/CCLog.h"
#include "scripting/js-bindings/jswrapper/napi/HelperMacros.h"
#define ASSETS_FOLDER_WRITEABLE_PATH "/data/accounts/account_0/applications/ohos.example.xcomponent1/ohos.example.xcomponent1/writeable_path"
#include "rawfile/raw_file_manager.h"
namespace cocos2d {
NativeResourceManager* FileUtilsOpenHarmony::_nativeResourceManager = nullptr;
FileUtils *createFileUtils() {
return new (std::nothrow) FileUtilsOpenHarmony();
}
FileUtilsOpenHarmony::FileUtilsOpenHarmony() {
// init();
}
std::string FileUtilsOpenHarmony::_ohWritablePath;
bool FileUtilsOpenHarmony::initResourceManager(napi_env env, napi_value param) {
_nativeResourceManager = OH_ResourceManager_InitNativeResourceManager(env, param);
return true;
}
FileUtils* FileUtils::getInstance()
{
if (s_sharedFileUtils == nullptr)
{
s_sharedFileUtils = new (std::nothrow) FileUtilsOpenHarmony();
if (!s_sharedFileUtils->init())
{
delete s_sharedFileUtils;
s_sharedFileUtils = nullptr;
cocos2d::log("ERROR: Could not init CCFileUtilsOpenHarmony");
}
}
return s_sharedFileUtils;
}
FileUtils::Status FileUtilsOpenHarmony::getContents(const std::string &filename, ResizableBuffer *buffer) {
if (filename.empty()) {
return FileUtils::Status::NotExists;
}
std::string fullPath = fullPathForFilename(filename);
if (fullPath.empty()) {
return FileUtils::Status::NotExists;
}
if (fullPath[0] == '/') {
return FileUtils::getContents(fullPath, buffer);
}
if (nullptr == _nativeResourceManager) {
cocos2d::log("[ERROR]ativeResourceManager is nullptr");
return FileUtils::Status::NotInitialized;
}
RawFile *rawFile = OH_ResourceManager_OpenRawFile(_nativeResourceManager, fullPath.c_str());
if (nullptr == rawFile) {
return FileUtils::Status::OpenFailed;
}
auto size = OH_ResourceManager_GetRawFileSize(rawFile);
buffer->resize(size);
assert(buffer->buffer());
int readsize = OH_ResourceManager_ReadRawFile(rawFile, buffer->buffer(), size);
// TODO(unknown): read error
if (readsize < size) {
if (readsize >= 0) {
buffer->resize(readsize);
}
OH_ResourceManager_CloseRawFile(rawFile);
return FileUtils::Status::ReadFailed;
}
OH_ResourceManager_CloseRawFile(rawFile);
return FileUtils::Status::OK;
}
FileUtilsOpenHarmony::~FileUtilsOpenHarmony() {
if(_nativeResourceManager)
OH_ResourceManager_ReleaseNativeResourceManager(_nativeResourceManager);
}
bool FileUtilsOpenHarmony::init() {
_defaultResRootPath = "";
return FileUtils::init();
}
bool FileUtilsOpenHarmony::isAbsolutePath(const std::string &strPath) const {
return !strPath.empty() && (strPath[0] == '/');
}
std::string FileUtilsOpenHarmony::getWritablePath() const {
std::string dir("");
if (_ohWritablePath.length() > 0)
{
dir.append(_ohWritablePath).append("/");
}
return dir;
}
bool FileUtilsOpenHarmony::isFileExistInternal(const std::string &strFilePath) const {
if (strFilePath.empty()) {
return false;
}
std::string strPath = strFilePath;
if (!isAbsolutePath(strPath)) { // Not absolute path, add the default root path at the beginning.
strPath.insert(0, _defaultResRootPath);
} else {
FILE *fp = fopen(strFilePath.c_str(), "r");
if (fp)
{
fclose(fp);
return true;
}
return false;
}
if (nullptr == _nativeResourceManager) {
cocos2d::log("[ERROR]ativeResourceManager is nullptr");
return false;
}
RawFile* rawFile = OH_ResourceManager_OpenRawFile(_nativeResourceManager, strPath.c_str());
if(rawFile) {
OH_ResourceManager_CloseRawFile(rawFile);
return true;
}
return false;
}
FileUtils::Status FileUtilsOpenHarmony::getRawFileDescriptor(const std::string &filename,RawFileDescriptor& descriptor) {
if (filename.empty()) {
return FileUtils::Status::NotExists;
}
std::string fullPath = fullPathForFilename(filename);
if (fullPath.empty()) {
return FileUtils::Status::NotExists;
}
if (nullptr == _nativeResourceManager) {
cocos2d::log("[ERROR]ativeResourceManager is nullptr");
return FileUtils::Status::NotInitialized;
}
RawFile *rawFile = OH_ResourceManager_OpenRawFile(_nativeResourceManager, fullPath.c_str());
if (nullptr == rawFile) {
return FileUtils::Status::OpenFailed;
}
bool result = OH_ResourceManager_GetRawFileDescriptor(rawFile, descriptor);
if (!result) {
OH_ResourceManager_CloseRawFile(rawFile);
return FileUtils::Status::OpenFailed;
}
OH_ResourceManager_CloseRawFile(rawFile);
return FileUtils::Status::OK;
}
bool FileUtilsOpenHarmony::isDirectoryExistInternal(const std::string &dirPath) const {
if (dirPath.empty()) return false;
std::string dirPathMf = dirPath[dirPath.length() - 1] == '/' ? dirPath.substr(0, dirPath.length() - 1) : dirPath;
if (dirPathMf[0] == '/') {
struct stat st;
return stat(dirPathMf.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
}
if (dirPathMf.find(_defaultResRootPath) == 0) {
dirPathMf = dirPathMf.substr(_defaultResRootPath.length(), dirPathMf.length());
}
if (nullptr == _nativeResourceManager) {
cocos2d::log("[ERROR]ativeResourceManager is nullptr");
return false;
}
RawDir* rawDir = OH_ResourceManager_OpenRawDir(_nativeResourceManager, dirPathMf.c_str());
if(rawDir) {
OH_ResourceManager_CloseRawDir(rawDir);
return true;
}
return false;
}
} // namespace cc

View File

@@ -0,0 +1,66 @@
/****************************************************************************
Copyright (c) 2021-2023 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.
****************************************************************************/
#pragma once
//clang-format off
#include <cstdint>
//clang-format on
#include <rawfile/raw_dir.h>
#include <rawfile/raw_file.h>
#include <rawfile/raw_file_manager.h>
#include "cocos/platform/CCFileUtils.h"
#include <napi/native_api.h>
class NativeResourceManager;
namespace cocos2d {
class CC_DLL FileUtilsOpenHarmony : public FileUtils {
public:
FileUtilsOpenHarmony();
virtual ~FileUtilsOpenHarmony() override;
static bool initResourceManager(napi_env env, napi_value info);
bool init() override;
bool isAbsolutePath(const std::string &strPath) const override;
FileUtils::Status getRawFileDescriptor(const std::string &filename,RawFileDescriptor& descriptor);
virtual std::string getWritablePath() const override;
virtual FileUtils::Status getContents(const std::string &filename, ResizableBuffer *buffer) override;
static std::string _ohWritablePath;
private:
virtual bool isFileExistInternal(const std::string &strFilePath) const override;
virtual bool isDirectoryExistInternal(const std::string &dirPath) const override;
friend class FileUtils;
static NativeResourceManager* _nativeResourceManager;
};
} // namespace cc

View File

@@ -0,0 +1,291 @@
/****************************************************************************
Copyright (c) 2021-2023 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 "platform/openharmony/OpenHarmonyPlatform.h"
#include "platform/CCPlatformDefine.h"
#include <ace/xcomponent/native_interface_xcomponent.h>
#include <napi/native_api.h>
#include "cocos2d.h"
#include "cocos/scripting/js-bindings/manual/jsb_module_register.hpp"
#include "cocos/scripting/js-bindings/manual/jsb_global.h"
#include "cocos/scripting/js-bindings/event/EventDispatcher.h"
#include "cocos/scripting/js-bindings/manual/jsb_classtype.hpp"
#include "base/CCScheduler.h"
#include "cocos/scripting/js-bindings/event/EventDispatcher.h"
#include <sstream>
#include <chrono>
namespace {
void sendMsgToWorker(const cocos2d::MessageType& type, void* component, void* window) {
cocos2d::OpenHarmonyPlatform* platform = cocos2d::OpenHarmonyPlatform::getInstance();
cocos2d::WorkerMessageData data{type, static_cast<void*>(component), window};
platform->enqueue(data);
}
void onSurfaceCreatedCB(OH_NativeXComponent* component, void* window) {
sendMsgToWorker(cocos2d::MessageType::WM_XCOMPONENT_SURFACE_CREATED, component, window);
}
void dispatchTouchEventCB(OH_NativeXComponent* component, void* window) {
OH_NativeXComponent_TouchEvent touchEvent;
int32_t ret = OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent);
if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
return;
}
cocos2d::TouchEvent* ev = new cocos2d::TouchEvent;
if (touchEvent.type == OH_NATIVEXCOMPONENT_DOWN) {
ev->type = cocos2d::TouchEvent::Type::BEGAN;
} else if (touchEvent.type == OH_NATIVEXCOMPONENT_MOVE) {
ev->type = cocos2d::TouchEvent::Type::MOVED;
} else if (touchEvent.type == OH_NATIVEXCOMPONENT_UP) {
ev->type = cocos2d::TouchEvent::Type::ENDED;
} else if (touchEvent.type == OH_NATIVEXCOMPONENT_CANCEL) {
ev->type = cocos2d::TouchEvent::Type::CANCELLED;
}
for(int i = 0; i < touchEvent.numPoints; ++i) {
cocos2d::TouchInfo touchInfo;
touchInfo.index = touchEvent.touchPoints[i].id;
touchInfo.x = touchEvent.touchPoints[i].x;
touchInfo.y = touchEvent.touchPoints[i].y;
if (touchEvent.id == touchInfo.index) {
ev->touches.push_back(touchInfo);
}
}
sendMsgToWorker(cocos2d::MessageType::WM_XCOMPONENT_TOUCH_EVENT, reinterpret_cast<void*>(ev), window);
}
void onSurfaceChangedCB(OH_NativeXComponent* component, void* window) {
sendMsgToWorker(cocos2d::MessageType::WM_XCOMPONENT_SURFACE_CHANGED, component, window);
}
void onSurfaceDestroyedCB(OH_NativeXComponent* component, void* window) {
sendMsgToWorker(cocos2d::MessageType::WM_XCOMPONENT_SURFACE_DESTROY, component, window);
}
bool setCanvasCallback(se::Object* global) {
cocos2d::OpenHarmonyPlatform* platform = cocos2d::OpenHarmonyPlatform::getInstance();
uint32_t innerWidth = (uint32_t)platform->width_;
uint32_t innerHeight = (uint32_t)platform->height_;
global->setProperty("innerWidth", se::Value(innerWidth));
global->setProperty("innerHeight", se::Value(innerHeight));
LOGD("exit setCanvasCallback setCanvasCallback");
return true;
}
} // namespace
namespace cocos2d {
OpenHarmonyPlatform::OpenHarmonyPlatform() {
_callback.OnSurfaceCreated = onSurfaceCreatedCB;
_callback.OnSurfaceChanged = onSurfaceChangedCB;
_callback.OnSurfaceDestroyed = onSurfaceDestroyedCB;
_callback.DispatchTouchEvent = dispatchTouchEventCB;
}
int32_t OpenHarmonyPlatform::init() {
return 0;
}
OpenHarmonyPlatform* OpenHarmonyPlatform::getInstance() {
static OpenHarmonyPlatform platform;
return &platform;
}
int32_t OpenHarmonyPlatform::run(int argc, const char** argv) {
LOGD("begin openharmonyplatform run");
int width = static_cast<int>(width_);
int height = static_cast<int>(height_);
g_app = new AppDelegate(width, height);
g_app->applicationDidFinishLaunching();
EventDispatcher::init();
g_started = true;
LOGD("end openharmonyplatform run");
return 0;
}
void OpenHarmonyPlatform::setNativeXComponent(OH_NativeXComponent* component) {
_component = component;
OH_NativeXComponent_RegisterCallback(_component, &_callback);
}
void OpenHarmonyPlatform::enqueue(const WorkerMessageData& msg) {
_messageQueue.enqueue(msg);
triggerMessageSignal();
}
void OpenHarmonyPlatform::triggerMessageSignal() {
if(_workerLoop != nullptr) {
// It is possible that when the message is sent, the worker thread has not yet started.
uv_async_send(&_messageSignal);
}
}
bool OpenHarmonyPlatform::dequeue(WorkerMessageData* msg) {
return _messageQueue.dequeue(msg);
}
// static
void OpenHarmonyPlatform::onMessageCallback(const uv_async_t* /* req */) {
void* window = nullptr;
WorkerMessageData msgData;
OpenHarmonyPlatform* platform = OpenHarmonyPlatform::getInstance();
while (true) {
//loop until all msg dispatch
if (!platform->dequeue(reinterpret_cast<WorkerMessageData*>(&msgData))) {
// Queue has no data
break;
}
if ((msgData.type >= MessageType::WM_XCOMPONENT_SURFACE_CREATED) && (msgData.type <= MessageType::WM_XCOMPONENT_SURFACE_DESTROY)) {
if (msgData.type == MessageType::WM_XCOMPONENT_TOUCH_EVENT) {
TouchEvent* ev = reinterpret_cast<TouchEvent*>(msgData.data);
EventDispatcher::dispatchTouchEvent(*ev);
delete ev;
ev = nullptr;
} else if (msgData.type == MessageType::WM_XCOMPONENT_SURFACE_CREATED) {
OH_NativeXComponent* nativexcomponet = reinterpret_cast<OH_NativeXComponent*>(msgData.data);
CC_ASSERT(nativexcomponet != nullptr);
platform->onSurfaceCreated(nativexcomponet, msgData.window);
} else if (msgData.type == MessageType::WM_XCOMPONENT_SURFACE_CHANGED) {
OH_NativeXComponent* nativexcomponet = reinterpret_cast<OH_NativeXComponent*>(msgData.data);
CC_ASSERT(nativexcomponet != nullptr);
platform->onSurfaceChanged(nativexcomponet, msgData.window);
} else if (msgData.type == MessageType::WM_XCOMPONENT_SURFACE_DESTROY) {
OH_NativeXComponent* nativexcomponet = reinterpret_cast<OH_NativeXComponent*>(msgData.data);
CC_ASSERT(nativexcomponet != nullptr);
platform->onSurfaceDestroyed(nativexcomponet, msgData.window);
} else {
CC_ASSERT(false);
}
continue;
}
if (msgData.type == MessageType::WM_APP_SHOW) {
platform->onShowNative();
} else if (msgData.type == MessageType::WM_APP_HIDE) {
platform->onHideNative();
} else if (msgData.type == MessageType::WM_APP_DESTROY) {
platform->onDestroyNative();
}
}
}
void OpenHarmonyPlatform::onCreateNative(napi_env env, uv_loop_t* loop) {
LOGD("OpenHarmonyPlatform::onCreateNative");
}
void OpenHarmonyPlatform::onShowNative() {
LOGD("OpenHarmonyPlatform::onShowNative");
EventDispatcher::dispatchOnResumeEvent();
}
void OpenHarmonyPlatform::onHideNative() {
LOGD("OpenHarmonyPlatform::onHideNative");
EventDispatcher::dispatchOnPauseEvent();
}
void OpenHarmonyPlatform::onDestroyNative() {
LOGD("OpenHarmonyPlatform::onDestroyNative");
}
void OpenHarmonyPlatform::timerCb(uv_timer_t* handle) {
if(OpenHarmonyPlatform::getInstance()->eglCore_ != nullptr){
OpenHarmonyPlatform::getInstance()->tick();
OpenHarmonyPlatform::getInstance()->eglCore_->Update();
}
}
void OpenHarmonyPlatform::workerInit(napi_env env, uv_loop_t* loop) {
_workerLoop = loop;
if (_workerLoop) {
uv_async_init(_workerLoop, &_messageSignal, reinterpret_cast<uv_async_cb>(OpenHarmonyPlatform::onMessageCallback));
if (!_messageQueue.empty()) {
triggerMessageSignal(); // trigger the signal to handle the pending message
}
}
}
void OpenHarmonyPlatform::requestVSync() {
// OH_NativeVSync_RequestFrame(OpenHarmonyPlatform::getInstance()->_nativeVSync, OnVSync, nullptr);
if (_workerLoop) {
// Todo: Starting the timer in this way is inaccurate and will be fixed later.
uv_timer_init(_workerLoop, &_timerHandle);
// The tick function needs to be called as quickly as possible because it is controlling the frame rate inside the engine.
uv_timer_start(&_timerHandle, &OpenHarmonyPlatform::timerCb, 0, 1);
}
}
int32_t OpenHarmonyPlatform::loop() {
return 0;
}
void OpenHarmonyPlatform::onSurfaceCreated(OH_NativeXComponent* component, void* window) {
eglCore_ = new EGLCore();
int32_t ret=OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
eglCore_->GLContextInit(window, width_, height_);
se::ScriptEngine *scriptEngine = se::ScriptEngine::getInstance();
scriptEngine->addRegisterCallback(setCanvasCallback);
if(g_app!=nullptr){
OpenHarmonyPlatform* platform = OpenHarmonyPlatform::getInstance();
g_app->updateViewSize(static_cast<float>(platform->width_), static_cast<float>(platform->height_));
}
LOGD("egl init finished.");
}
}
void OpenHarmonyPlatform::onSurfaceChanged(OH_NativeXComponent* component, void* window) {
int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
// nativeOnSizeChanged is firstly called before Application initiating.
if (g_app != nullptr) {
g_app->updateViewSize(width_, height_);
}
}
void OpenHarmonyPlatform::onSurfaceDestroyed(OH_NativeXComponent* component, void* window) {
}
void OpenHarmonyPlatform::tick() {
static std::chrono::steady_clock::time_point prevTime;
static std::chrono::steady_clock::time_point now;
static float dt = 0.f;
static float dtSum = 0.f;
static uint32_t jsbInvocationTotalCount = 0;
static uint32_t jsbInvocationTotalFrames = 0;
std::shared_ptr<Scheduler> scheduler = g_app->getScheduler();
scheduler->update(dt);
EventDispatcher::dispatchTickEvent(dt);
PoolManager::getInstance()->getCurrentPool()->clear();
now = std::chrono::steady_clock::now();
dt = std::chrono::duration_cast<std::chrono::microseconds>(now - prevTime).count() / 1000000.f;
prevTime = std::chrono::steady_clock::now();
}
}; // namespace cc

View File

@@ -0,0 +1,96 @@
/****************************************************************************
Copyright (c) 2021-2023 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.
****************************************************************************/
#pragma once
// #include "platform/UniversalPlatform.h"
#include <ace/xcomponent/native_interface_xcomponent.h>
#include <uv.h>
#include <string>
#include <unordered_map>
#include <napi/native_api.h>
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
#include "platform/openharmony/WorkerMessageQueue.h"
#include "scripting/js-bindings/event/EventDispatcher.h"
#include "platform/openharmony/render/egl_core.h"
#include "platform/openharmony/AppDelegate.h"
namespace cocos2d {
#define NANOSECONDS_PER_SECOND 1000000000
#define NANOSECONDS_60FPS 16666667L
class OpenHarmonyPlatform {
public:
OpenHarmonyPlatform();
int32_t init();
static OpenHarmonyPlatform* getInstance();
void onCreateNative(napi_env env, uv_loop_t* loop);
void onShowNative();
void onHideNative();
void onDestroyNative();
void workerInit(napi_env env, uv_loop_t* loop);
void setNativeXComponent(OH_NativeXComponent* component);
int32_t run(int argc, const char** argv);
void resume();
void pause();
int32_t loop();
void requestVSync();
void enqueue(const WorkerMessageData& data);
bool dequeue(WorkerMessageData* data);
void triggerMessageSignal();
public:
// Callback, called by ACE XComponent
void onSurfaceCreated(OH_NativeXComponent* component, void* window);
void onSurfaceChanged(OH_NativeXComponent* component, void* window);
void onSurfaceDestroyed(OH_NativeXComponent* component, void* window);
void dispatchTouchEvent(OH_NativeXComponent* component, void* window);
static void onMessageCallback(const uv_async_t* req);
static void timerCb(uv_timer_t* handle);
void tick();
OH_NativeXComponent* _component{nullptr};
OH_NativeXComponent_Callback _callback;
uv_timer_t _timerHandle;
uv_loop_t* _workerLoop{nullptr};
uv_async_t _messageSignal{};
WorkerMessageQueue _messageQueue;
EGLCore* eglCore_{nullptr};
uint64_t width_;
uint64_t height_;
Application* g_app = nullptr;
//game started
bool g_started = false;
};
} // namespace cc

View File

@@ -0,0 +1,49 @@
/****************************************************************************
Copyright (c) 2021-2023 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 "platform/openharmony/WorkerMessageQueue.h"
namespace cocos2d {
void WorkerMessageQueue::enqueue(const WorkerMessageData& data) {
std::lock_guard<std::mutex> lck(_mutex);
_queue.push(data);
}
bool WorkerMessageQueue::dequeue(WorkerMessageData *data) {
std::lock_guard<std::mutex> lck(_mutex);
if (empty()) {
return false;
}
*data = _queue.front();
_queue.pop();
return true;
}
bool WorkerMessageQueue::empty() const {
return _queue.empty();
}
} // namespace cocos2d

View File

@@ -0,0 +1,67 @@
/****************************************************************************
Copyright (c) 2021-2023 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.
****************************************************************************/
#pragma once
#include <queue>
#include <thread>
#include <mutex>
namespace cocos2d {
enum class MessageType {
WM_XCOMPONENT_SURFACE_CREATED = 0,
WM_XCOMPONENT_TOUCH_EVENT,
WM_XCOMPONENT_SURFACE_CHANGED,
WM_XCOMPONENT_SURFACE_DESTROY,
WM_APP_SHOW,
WM_APP_HIDE,
WM_APP_DESTROY,
WM_VSYNC,
};
struct WorkerMessageData {
MessageType type;
void* data;
void* window;
};
class WorkerMessageQueue final {
public:
void enqueue(const WorkerMessageData& data);
bool dequeue(WorkerMessageData *data);
bool empty() const;
size_t size() const {
return _queue.size();
}
private:
std::mutex _mutex;
std::queue<WorkerMessageData> _queue;
};
} // namespace cc

View File

@@ -0,0 +1,280 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "platform/CCApplication.h"
#include "platform/openharmony/napi/NapiHelper.h"
#include "base/CCScheduler.h"
#include "base/CCConfiguration.h"
#include "audio/include/AudioEngine.h"
#include "scripting/js-bindings/event/EventDispatcher.h"
#include "platform/openharmony/OpenHarmonyPlatform.h"
PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOESEXT = 0;
PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOESEXT = 0;
PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOESEXT = 0;
NS_CC_BEGIN
void Application::updateViewSize(int width, int height)
{
if(width <= 0 || height <= 0)
{
return;
}
_viewSize.x = width;
_viewSize.y = height;
// handle resize event
Application::getInstance()->getScheduler()->performFunctionInCocosThread([=]() {
EventDispatcher::dispatchResizeEvent(width, height);
});
}
Application* Application::_instance = nullptr;
std::shared_ptr<Scheduler> Application::_scheduler = nullptr;
Application::Application(const std::string& name, int width, int height)
{
Application::_instance = this;
Configuration::getInstance();
_scheduler = std::make_shared<Scheduler>();
_renderTexture = new RenderTexture(width, height);
updateViewSize(width, height);
}
Application::~Application()
{
#if USE_AUDIO
AudioEngine::end();
#endif
EventDispatcher::destroy();
se::ScriptEngine::destroyInstance();
delete _renderTexture;
_renderTexture = nullptr;
Application::_instance = nullptr;
}
void Application::start()
{
if(!applicationDidFinishLaunching())
return;
}
void Application::restart()
{
// restartJSVM();
}
void Application::end()
{
int32_t value;
NapiHelper::napiCallFunction("terminateProcess", &value);
}
void Application::setMultitouch(bool /*value*/)
{
}
bool Application::applicationDidFinishLaunching()
{
return true;
}
void Application::onPause()
{
}
void Application::onResume()
{
}
void Application::setPreferredFramesPerSecond(int fps)
{
_fps = fps;
// setPreferredFramesPerSecondJNI(_fps);
}
bool Application::isDisplayStats() {
se::AutoHandleScope hs;
se::Value ret;
char commandBuf[100] = "cc.debug.isDisplayStats();";
se::ScriptEngine::getInstance()->evalString(commandBuf, 100, &ret);
return ret.toBoolean();
}
void Application::setDisplayStats(bool isShow) {
se::AutoHandleScope hs;
char commandBuf[100] = {0};
sprintf(commandBuf, "cc.debug.setDisplayStats(%s);", isShow ? "true" : "false");
se::ScriptEngine::getInstance()->evalString(commandBuf);
}
std::string Application::getCurrentLanguageCode() const {
std::string str;
NapiHelper::napiCallFunction<std::string>("getSystemLanguage", &str);
std::string::size_type pos = str.find('-');
if(pos != std::string::npos) {
str = str.substr(0, pos);
}
return str;
}
Application::LanguageType Application::getCurrentLanguage() const
{
std::string languageName = getCurrentLanguageCode(); // NOLINT
const char* pLanguageName = languageName.c_str();
LanguageType ret = LanguageType::ENGLISH;
if (0 == strcmp("zh", pLanguageName))
{
ret = LanguageType::CHINESE;
}
else if (0 == strcmp("en", pLanguageName))
{
ret = LanguageType::ENGLISH;
}
else if (0 == strcmp("fr", pLanguageName))
{
ret = LanguageType::FRENCH;
}
else if (0 == strcmp("it", pLanguageName))
{
ret = LanguageType::ITALIAN;
}
else if (0 == strcmp("de", pLanguageName))
{
ret = LanguageType::GERMAN;
}
else if (0 == strcmp("es", pLanguageName))
{
ret = LanguageType::SPANISH;
}
else if (0 == strcmp("ru", pLanguageName))
{
ret = LanguageType::RUSSIAN;
}
else if (0 == strcmp("nl", pLanguageName))
{
ret = LanguageType::DUTCH;
}
else if (0 == strcmp("ko", pLanguageName))
{
ret = LanguageType::KOREAN;
}
else if (0 == strcmp("ja", pLanguageName))
{
ret = LanguageType::JAPANESE;
}
else if (0 == strcmp("hu", pLanguageName))
{
ret = LanguageType::HUNGARIAN;
}
else if (0 == strcmp("pt", pLanguageName))
{
ret = LanguageType::PORTUGUESE;
}
else if (0 == strcmp("ar", pLanguageName))
{
ret = LanguageType::ARABIC;
}
else if (0 == strcmp("nb", pLanguageName))
{
ret = LanguageType::NORWEGIAN;
}
else if (0 == strcmp("pl", pLanguageName))
{
ret = LanguageType::POLISH;
}
else if (0 == strcmp("tr", pLanguageName))
{
ret = LanguageType::TURKISH;
}
else if (0 == strcmp("uk", pLanguageName))
{
ret = LanguageType::UKRAINIAN;
}
else if (0 == strcmp("ro", pLanguageName))
{
ret = LanguageType::ROMANIAN;
}
else if (0 == strcmp("bg", pLanguageName))
{
ret = LanguageType::BULGARIAN;
}
return ret;
}
Application::Platform Application::getPlatform() const
{
return Platform::OpenHarmony;
}
float Application::getScreenScale() const
{
return 1.f;
}
GLint Application::getMainFBO() const
{
return _mainFBO;
}
void Application::onCreateView(PixelFormat& /*pixelformat*/, DepthFormat& /*depthFormat*/, int& /*multisamplingCount*/)
{
}
bool Application::openURL(const std::string &url)
{
return false;
}
void Application::copyTextToClipboard(const std::string &text)
{
// copyTextToClipboardJNI(text);
}
std::string Application::getSystemVersion()
{
std::string str;
NapiHelper::napiCallFunction<std::string>("getOSFullName", &str);
return str;
}
const cocos2d::Vec2& Application::getViewSize() const
{
return _viewSize;
}
NS_CC_END

View File

@@ -0,0 +1,718 @@
/****************************************************************************
Copyright (c) 2022-2023 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 <array>
#include <regex>
#include <memory>
#include "base/csscolorparser.hpp"
#include "cocos/scripting/js-bindings/manual/jsb_platform.h"
#include "math/CCMath.h"
#include "base/CCData.h"
#include "platform/CCCanvasRenderingContext2D.h"
//#include "platform/openharmony/OpenHarmonyPlatform.h"
#include <native_drawing/drawing_text_typography.h>
#include <native_drawing/drawing_canvas.h>
#include <native_drawing/drawing_font_collection.h>
#include <native_drawing/drawing_types.h>
#include <native_drawing/drawing_path.h>
#include <native_drawing/drawing_bitmap.h>
#include <native_drawing/drawing_text_declaration.h>
#include <native_drawing/drawing_brush.h>
using namespace cocos2d;
enum class TextAlign {
LEFT,
CENTER,
RIGHT
};
enum class TextBaseline {
TOP,
MIDDLE,
BOTTOM,
ALPHABETIC
};
class ScopedTypography {
public:
ScopedTypography(OH_Drawing_Typography* typography) :_typegraphy(typography) {}
~ScopedTypography() {
if(_typegraphy) {
OH_Drawing_DestroyTypography(_typegraphy);
}
}
OH_Drawing_Typography* get() {
return _typegraphy;
}
private:
OH_Drawing_Typography* _typegraphy{nullptr};
};
class CanvasRenderingContext2DImpl {
public:
using Point = std::array<float, 2>;
using Vec2 = std::array<float, 2>;
using Size = std::array<float, 2>;
using Color4F = std::array<float, 4>;
CanvasRenderingContext2DImpl() {
_typographyStyle = OH_Drawing_CreateTypographyStyle();
OH_Drawing_SetTypographyTextDirection(_typographyStyle, TEXT_DIRECTION_LTR);
OH_Drawing_SetTypographyTextAlign(_typographyStyle, TEXT_ALIGN_LEFT);
_fontCollection = OH_Drawing_CreateFontCollection();
_typographyCreate = OH_Drawing_CreateTypographyHandler(_typographyStyle, _fontCollection);
_textStyle = OH_Drawing_CreateTextStyle();
}
~CanvasRenderingContext2DImpl() {
if(_typographyStyle) {
OH_Drawing_DestroyTypographyStyle(_typographyStyle);
_typographyStyle = nullptr;
}
if(_fontCollection) {
OH_Drawing_DestroyFontCollection(_fontCollection);
}
if(_typographyCreate) {
OH_Drawing_DestroyTypographyHandler(_typographyCreate);
_typographyCreate = nullptr;
}
if(_textStyle) {
OH_Drawing_DestroyTextStyle(_textStyle);
_textStyle = nullptr;
}
if(_canvas) {
OH_Drawing_CanvasDestroy(_canvas);
_canvas = nullptr;
}
if(_bitmap) {
OH_Drawing_BitmapDestroy(_bitmap);
_bitmap = nullptr;
}
}
void recreateBuffer(float w, float h) {
_bufferWidth = w;
_bufferHeight = h;
if (_bufferWidth < 1.0F || _bufferHeight < 1.0F) {
return;
}
if (_canvas) {
OH_Drawing_CanvasDestroy(_canvas);
_canvas = nullptr;
}
if (_bitmap) {
OH_Drawing_BitmapDestroy(_bitmap);
_bitmap = nullptr;
}
_bufferSize = static_cast<int>(_bufferWidth * _bufferHeight * 4);
auto *data = static_cast<uint8_t *>(malloc(sizeof(uint8_t) * _bufferSize));
memset(data, 0x00, _bufferSize);
_imageData.fastSet(data, _bufferSize);
_bitmap = OH_Drawing_BitmapCreate();
OH_Drawing_BitmapBuild(_bitmap, _bufferWidth, _bufferHeight, &_format);
_canvas = OH_Drawing_CanvasCreate();
OH_Drawing_CanvasBind(_canvas, _bitmap);
}
void beginPath() {
}
void closePath() {
}
void moveTo(float x, float y) {
// MoveToEx(_DC, static_cast<int>(x), static_cast<int>(-(y - _bufferHeight - _fontSize)), nullptr);
_x = x;
_y = y;
}
void lineTo(float x, float y) {
}
void stroke() {
}
void saveContext() {
}
void restoreContext() {
}
void clearRect(float x, float y, float w, float h) {
if (_bufferWidth < 1.0F || _bufferHeight < 1.0F) {
return;
}
if (_imageData.isNull()) {
return;
}
recreateBuffer(w, h);
}
void fillRect(float x, float y, float w, float h) {
if (_bufferWidth < 1.0F || _bufferHeight < 1.0F) {
return;
}
uint8_t r = static_cast<uint8_t>(_fillStyle[0]);
uint8_t g = static_cast<uint8_t>(_fillStyle[1]);
uint8_t b = static_cast<uint8_t>(_fillStyle[2]);
uint8_t a = static_cast<uint8_t>(_fillStyle[3]);
OH_Drawing_Path* path = OH_Drawing_PathCreate();
OH_Drawing_PathMoveTo(path, x, y);
OH_Drawing_PathLineTo(path, x + w, y);
OH_Drawing_PathLineTo(path, x + w, y + h);
OH_Drawing_PathLineTo(path, x, y + h);
OH_Drawing_PathLineTo(path, x, y);
OH_Drawing_PathClose(path);
OH_Drawing_Brush* brush = OH_Drawing_BrushCreate();
OH_Drawing_BrushSetColor(brush, OH_Drawing_ColorSetArgb(a, r, g, b));
OH_Drawing_CanvasAttachBrush(_canvas, brush);
OH_Drawing_CanvasDrawPath(_canvas, path);
}
void fillText(const std::string &text, float x, float y, float /*maxWidth*/) {
if (text.empty() || _bufferWidth < 1.0F || _bufferHeight < 1.0F) {
return;
}
Size textSize = {0, 0};
Point offsetPoint = convertDrawPoint(Point{x, y}, text);
drawText(text, offsetPoint[0], offsetPoint[1]);
}
void strokeText(const std::string &text, float /*x*/, float /*y*/, float /*maxWidth*/) const {
}
Size measureText(const std::string &text) {
auto typography = createTypography(text);
return std::array<float, 2>{static_cast<float>(OH_Drawing_TypographyGetMaxIntrinsicWidth(typography->get())),
static_cast<float>(OH_Drawing_TypographyGetHeight(typography->get()))};
}
void updateFont(const std::string &fontName,
float fontSize,
bool bold,
bool italic,
bool oblique,
bool /* smallCaps */) {
_fontName = fontName;
_fontSize = static_cast<int>(fontSize);
std::string fontPath;
if (!_fontName.empty()) {
const char* fontFamilies[1];
fontFamilies[0] = fontName.c_str();
OH_Drawing_SetTextStyleFontFamilies(_textStyle, 1, fontFamilies);
OH_Drawing_SetTextStyleLocale(_textStyle, "en");
}
if (_fontSize)
OH_Drawing_SetTextStyleFontSize(_textStyle, _fontSize);
if (bold)
OH_Drawing_SetTextStyleFontWeight(_textStyle, FONT_WEIGHT_700);
else
OH_Drawing_SetTextStyleFontWeight(_textStyle, FONT_WEIGHT_400);
if(italic)
OH_Drawing_SetTextStyleFontStyle(_textStyle, FONT_STYLE_ITALIC);
else
OH_Drawing_SetTextStyleFontStyle(_textStyle, FONT_STYLE_NORMAL);
}
void setTextAlign(TextAlign align) {
_textAlign = align;
}
void setTextBaseline(TextBaseline baseline) {
_textBaseLine = baseline;
}
void setFillStyle(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
_fillStyle = {static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a)};
OH_Drawing_SetTextStyleColor(_textStyle, OH_Drawing_ColorSetArgb(a, r, g, b));
}
void setStrokeStyle(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
_strokeStyle = {static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a)};
}
void setLineWidth(float lineWidth) {
_lineWidth = lineWidth;
}
const Data &getDataRef() const {
return _imageData;
}
void removeCustomFont() {
}
// x, y offset value
int drawText(const std::string &text, float x, float y) {
auto typography = createTypography(text);
OH_Drawing_TypographyPaint(typography->get(), _canvas, (double)x, (double)y);
void* bitmapAddr = OH_Drawing_BitmapGetPixels(_bitmap);
memcpy(_imageData.getBytes(), bitmapAddr, _bufferSize);
return 0;
}
Size sizeWithText(const wchar_t *pszText, int nLen) {
return std::array<float, 2>{0.0F, 0.0F};
}
void prepareBitmap(int nWidth, int nHeight) {
}
void deleteBitmap() {
}
void fillTextureData() {
}
std::array<float, 2> convertDrawPoint(Point point, const std::string &text) {
auto typography = createTypography(text);
Size textSize {static_cast<float>(OH_Drawing_TypographyGetMaxIntrinsicWidth(typography->get())),
static_cast<float>(OH_Drawing_TypographyGetHeight(typography->get()))};
if (_textAlign == TextAlign::CENTER) {
point[0] -= textSize[0] / 2.0f;
} else if (_textAlign == TextAlign::RIGHT) {
point[0] -= textSize[0];
}
double alphabeticBaseLine = OH_Drawing_TypographyGetAlphabeticBaseline(typography->get());
if (_textBaseLine == TextBaseline::TOP) {
//point[1] += -alphabeticBaseLine;
} else if (_textBaseLine == TextBaseline::MIDDLE) {
point[1] += -textSize[1] / 2.0f;
} else if (_textBaseLine == TextBaseline::BOTTOM) {
point[1] += -textSize[1];
} else if (_textBaseLine == TextBaseline::ALPHABETIC) {
//GetTextMetrics(_DC, &_tm);
//point[1] -= _tm.tmAscent;
point[1] -= alphabeticBaseLine;
}
return point;
}
std::unique_ptr<ScopedTypography> createTypography(const std::string &text) {
OH_Drawing_TypographyHandlerPushTextStyle(_typographyCreate, _textStyle);
OH_Drawing_TypographyHandlerAddText(_typographyCreate, text.c_str());
OH_Drawing_TypographyHandlerPopTextStyle(_typographyCreate);
OH_Drawing_Typography* typography = OH_Drawing_CreateTypography(_typographyCreate);
OH_Drawing_TypographyLayout(typography, _bufferWidth);
return std::make_unique<ScopedTypography>(typography);
}
void fill() {
}
void setLineCap(const std::string &lineCap) {
}
void setLineJoin(const std::string &lineJoin) {
}
void fillImageData(const Data & /* imageData */,
float /* imageWidth */,
float /* imageHeight */,
float /* offsetX */,
float /* offsetY */) {
}
void strokeText(const std::string & /* text */,
float /* x */,
float /* y */,
float /* maxWidth */) {
}
void rect(float /* x */,
float /* y */,
float /* w */,
float /* h */) {
}
void updateData() {
}
private:
int32_t _x{0};
int32_t _y{0};
int32_t _lineCap{0};
int32_t _lineJoin{0};
OH_Drawing_Bitmap* _bitmap{nullptr};
OH_Drawing_BitmapFormat _format {COLOR_FORMAT_RGBA_8888, ALPHA_FORMAT_OPAQUE};
OH_Drawing_Canvas* _canvas{nullptr};
OH_Drawing_TypographyStyle* _typographyStyle{nullptr};
OH_Drawing_TypographyCreate* _typographyCreate{nullptr};
OH_Drawing_FontCollection* _fontCollection{nullptr};
OH_Drawing_TextStyle* _textStyle{nullptr};
Data _imageData;
std::string _curFontPath;
int _savedDC{0};
float _lineWidth{0.0F};
float _bufferWidth{0.0F};
float _bufferHeight{0.0F};
int32_t _bufferSize{0};
std::string _fontName;
int _fontSize{0};
Size _textSize;
TextAlign _textAlign{TextAlign::CENTER};
TextBaseline _textBaseLine{TextBaseline::TOP};
Color4F _fillStyle{0};
Color4F _strokeStyle{0};
};
NS_CC_BEGIN
CanvasGradient::CanvasGradient()
{
// SE_LOGD("CanvasGradient constructor: %p\n", this);
}
CanvasGradient::~CanvasGradient()
{
// SE_LOGD("CanvasGradient destructor: %p\n", this);
}
void CanvasGradient::addColorStop(float offset, const std::string& color)
{
// SE_LOGD("CanvasGradient::addColorStop: %p\n", this);
}
// CanvasRenderingContext2D
CanvasRenderingContext2D::CanvasRenderingContext2D(float width, float height)
: __width(width)
, __height(height)
{
// SE_LOGD("CanvasRenderingContext2D constructor: %p, width: %f, height: %f\n", this, width, height);
_impl = new CanvasRenderingContext2DImpl();
recreateBufferIfNeeded();
}
CanvasRenderingContext2D::~CanvasRenderingContext2D()
{
// SE_LOGD("CanvasRenderingContext2D destructor: %p\n", this);
delete _impl;
}
void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height)
{
// SE_LOGD("CanvasRenderingContext2D::clearRect: %p, %f, %f, %f, %f\n", this, x, y, width, height);
recreateBufferIfNeeded();
_impl->clearRect(x, y, width, height);
}
void CanvasRenderingContext2D::fillRect(float x, float y, float width, float height)
{
recreateBufferIfNeeded();
_impl->fillRect(x, y, width, height);
if (_canvasBufferUpdatedCB != nullptr)
_canvasBufferUpdatedCB(_impl->getDataRef());
}
void CanvasRenderingContext2D::fillText(const std::string& text, float x, float y, float maxWidth)
{
// SE_LOGD("CanvasRenderingContext2D::fillText: %s, %f, %f, %f\n", text.c_str(), x, y, maxWidth);
if (text.empty())
return;
recreateBufferIfNeeded();
_impl->fillText(text, x, y, maxWidth);
if (_canvasBufferUpdatedCB != nullptr)
_canvasBufferUpdatedCB(_impl->getDataRef());
}
void CanvasRenderingContext2D::strokeText(const std::string& text, float x, float y, float maxWidth)
{
// SE_LOGD("CanvasRenderingContext2D::strokeText: %s, %f, %f, %f\n", text.c_str(), x, y, maxWidth);
if (text.empty())
return;
recreateBufferIfNeeded();
_impl->strokeText(text, x, y, maxWidth);
if (_canvasBufferUpdatedCB != nullptr)
_canvasBufferUpdatedCB(_impl->getDataRef());
}
cocos2d::Size CanvasRenderingContext2D::measureText(const std::string& text)
{
// SE_LOGD("CanvasRenderingContext2D::measureText: %s\n", text.c_str());
auto s = _impl->measureText(text);
s[0] = ceil(s[0] * 100) / 100;
s[1] = ceil(s[1] * 100) / 100;
return cocos2d::Size(s[0], s[1]);
}
CanvasGradient* CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1)
{
return nullptr;
}
void CanvasRenderingContext2D::save()
{
_impl->saveContext();
}
void CanvasRenderingContext2D::beginPath()
{
_impl->beginPath();
}
void CanvasRenderingContext2D::closePath()
{
_impl->closePath();
}
void CanvasRenderingContext2D::moveTo(float x, float y)
{
_impl->moveTo(x, y);
}
void CanvasRenderingContext2D::lineTo(float x, float y)
{
_impl->lineTo(x, y);
}
void CanvasRenderingContext2D::stroke()
{
_impl->stroke();
if (_canvasBufferUpdatedCB != nullptr)
_canvasBufferUpdatedCB(_impl->getDataRef());
}
void CanvasRenderingContext2D::restore()
{
_impl->restoreContext();
}
void CanvasRenderingContext2D::setCanvasBufferUpdatedCallback(const CanvasBufferUpdatedCallback& cb)
{
_canvasBufferUpdatedCB = cb;
}
void CanvasRenderingContext2D::setPremultiply(bool multiply)
{
_premultiply = multiply;
}
void CanvasRenderingContext2D::set__width(float width)
{
// SE_LOGD("CanvasRenderingContext2D::set__width: %f\n", width);
__width = width;
_isBufferSizeDirty = true;
recreateBufferIfNeeded();
}
void CanvasRenderingContext2D::set__height(float height)
{
// SE_LOGD("CanvasRenderingContext2D::set__height: %f\n", height);
__height = height;
_isBufferSizeDirty = true;
recreateBufferIfNeeded();
}
void CanvasRenderingContext2D::set_lineWidth(float lineWidth)
{
_lineWidth = lineWidth;
_impl->setLineWidth(lineWidth);
}
void CanvasRenderingContext2D::set_lineCap(const std::string& lineCap)
{
if(lineCap.empty()) return ;
_impl->setLineCap(lineCap);
}
void CanvasRenderingContext2D::set_lineJoin(const std::string& lineJoin)
{
if(lineJoin.empty()) return ;
_impl->setLineJoin(lineJoin);
}
void CanvasRenderingContext2D::fill()
{
_impl->fill();
if (_canvasBufferUpdatedCB != nullptr)
_canvasBufferUpdatedCB(_impl->getDataRef());
}
void CanvasRenderingContext2D::rect(float x, float y, float width, float height)
{
// SE_LOGD("CanvasRenderingContext2D::rect: %p, %f, %f, %f, %f\n", this, x, y, width, height);
recreateBufferIfNeeded();
_impl->rect(x, y, width, height);
}
/*
* support format e.g.: "oblique bold small-caps 18px Arial"
* "italic bold small-caps 25px Arial"
* "italic 25px Arial"
* */
void CanvasRenderingContext2D::set_font(const std::string& font)
{
if (_font != font) {
_font = font;
std::string fontName = "sans-serif";
std::string fontSizeStr = "30";
std::regex re(R"(\s*((\d+)([\.]\d+)?)px\s+([^\r\n]*))");
std::match_results<std::string::const_iterator> results;
if (std::regex_search(_font.cbegin(), _font.cend(), results, re)) {
fontSizeStr = results[2].str();
// support get font name from `60px American` or `60px "American abc-abc_abc"`
// support get font name contain space,example `times new roman`
// if regex rule that does not conform to the rules,such as Chinese,it defaults to sans-serif
std::match_results<std::string::const_iterator> fontResults;
std::regex fontRe(R"(([\w\s-]+|"[\w\s-]+"$))");
std::string tmp(results[4].str());
if (std::regex_match(tmp, fontResults, fontRe)) {
fontName = results[4].str();
}
}
double fontSize = atof(fontSizeStr.c_str());
bool isBold = font.find("bold", 0) != std::string::npos || font.find("Bold", 0) != std::string::npos;
bool isItalic = font.find("italic", 0) != std::string::npos || font.find("Italic", 0) != std::string::npos;
bool isSmallCaps = font.find("small-caps", 0) != std::string::npos || font.find("Small-Caps") != std::string::npos;
bool isOblique = font.find("oblique", 0) != std::string::npos || font.find("Oblique", 0) != std::string::npos;
//font-style: italic, oblique, normal
//font-weight: normal, bold
//font-variant: normal, small-caps
_impl->updateFont(fontName, fontSize, isBold, isItalic, isOblique, isSmallCaps);
}
}
void CanvasRenderingContext2D::set_textAlign(const std::string& textAlign)
{
// SE_LOGD("CanvasRenderingContext2D::set_textAlign: %s\n", textAlign.c_str());
if (textAlign == "left") {
_impl->setTextAlign(TextAlign::LEFT);
} else if (textAlign == "center" || textAlign == "middle") {
_impl->setTextAlign(TextAlign::CENTER);
} else if (textAlign == "right") {
_impl->setTextAlign(TextAlign::RIGHT);
} else {
CC_ASSERT(false);
}
}
void CanvasRenderingContext2D::set_textBaseline(const std::string& textBaseline)
{
// SE_LOGD("CanvasRenderingContext2D::set_textBaseline: %s\n", textBaseline.c_str());
if (textBaseline == "top") {
_impl->setTextBaseline(TextBaseline::TOP);
} else if (textBaseline == "middle") {
_impl->setTextBaseline(TextBaseline::MIDDLE);
} else if (textBaseline == "bottom") //REFINE:, how to deal with alphabetic, currently we handle it as bottom mode.
{
_impl->setTextBaseline(TextBaseline::BOTTOM);
} else if (textBaseline == "alphabetic") {
_impl->setTextBaseline(TextBaseline::ALPHABETIC);
} else {
CC_ASSERT(false);
}
}
void CanvasRenderingContext2D::set_fillStyle(const std::string& fillStyle)
{
CSSColorParser::Color color = CSSColorParser::parse(fillStyle);
_impl->setFillStyle(color.r, color.g, color.b, static_cast<uint8_t>(color.a * 255));
// SE_LOGD("CanvasRenderingContext2D::set_fillStyle: %s, (%d, %d, %d, %f)\n", fillStyle.c_str(), color.r, color.g, color.b, color.a);
}
void CanvasRenderingContext2D::set_strokeStyle(const std::string& strokeStyle)
{
CSSColorParser::Color color = CSSColorParser::parse(strokeStyle);
_impl->setStrokeStyle(color.r, color.g, color.b, static_cast<uint8_t>(color.a * 255));
}
void CanvasRenderingContext2D::set_globalCompositeOperation(const std::string& globalCompositeOperation)
{
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
}
void CanvasRenderingContext2D::_fillImageData(const Data& imageData, float imageWidth, float imageHeight, float offsetX, float offsetY)
{
_impl->fillImageData(imageData, imageWidth, imageHeight, offsetX, offsetY);
if (_canvasBufferUpdatedCB != nullptr)
_canvasBufferUpdatedCB(_impl->getDataRef());
}
// transform
//REFINE:
void CanvasRenderingContext2D::translate(float x, float y)
{
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
}
void CanvasRenderingContext2D::scale(float x, float y)
{
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
}
void CanvasRenderingContext2D::rotate(float angle)
{
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
}
void CanvasRenderingContext2D::transform(float a, float b, float c, float d, float e, float f)
{
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
}
void CanvasRenderingContext2D::setTransform(float a, float b, float c, float d, float e, float f)
{
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
}
void CanvasRenderingContext2D::recreateBufferIfNeeded()
{
if (_isBufferSizeDirty) {
_isBufferSizeDirty = false;
// SE_LOGD("Recreate buffer %p, w: %f, h:%f\n", this, __width, __height);
_impl->recreateBuffer(__width, __height);
if (_canvasBufferUpdatedCB != nullptr)
_canvasBufferUpdatedCB(_impl->getDataRef());
}
}
NS_CC_END

View File

@@ -0,0 +1,389 @@
/****************************************************************************
Copyright (c) 2022-2023 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 "platform/openharmony/napi/NapiHelper.h"
#include "platform/openharmony/OpenHarmonyPlatform.h"
#include "scripting/js-bindings/jswrapper/napi/HelperMacros.h"
#include "cocos/platform/openharmony/FileUtils-openharmony.h"
#include "scripting/js-bindings/jswrapper/SeApi.h"
#include "ui/edit-box/EditBox-openharmony.h"
#include "ui/webview/WebViewImpl-openharmony.h"
#include "platform/openharmony/WorkerMessageQueue.h"
#define KEYCODE_BACK_OH 6
namespace cocos2d {
const int32_t kMaxStringLen = 512;
// Must be the same as the value called by js
enum ContextType {
APP_LIFECYCLE = 0,
JS_PAGE_LIFECYCLE,
XCOMPONENT_CONTEXT,
XCOMPONENT_REGISTER_LIFECYCLE_CALLBACK,
NATIVE_RENDER_API,
WORKER_INIT,
ENGINE_UTILS,
EDITBOX_UTILS,
WEBVIEW_UTILS,
DISPLAY_UTILS,
UV_ASYNC_SEND,
};
NapiHelper::PostMessage2UIThreadCb NapiHelper::_postMsg2UIThreadCb;
NapiHelper::PostSyncMessage2UIThreadCb NapiHelper::_postSyncMsg2UIThreadCb;
static bool js_set_PostMessage2UIThreadCallback(se::State& s) {
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
do {
if (args[0].isObject() && args[0].toObject()->isFunction()) {
//se::Value jsThis(s.thisObject());
se::Value jsFunc(args[0]);
//jsThis.toObject()->attachObject(jsFunc.toObject());
auto * thisObj = s.thisObject();
NapiHelper::_postMsg2UIThreadCb = [=](const std::string larg0, const se::Value& larg1) -> void {
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
CC_UNUSED bool ok = true;
se::ValueArray args;
args.resize(2);
ok &= std_string_to_seval(larg0, &args[0]);
CC_ASSERT(ok);
args[1] = larg1;
//ok &= nativevalue_to_se(larg1, args[1], nullptr /*ctx*/);
se::Value rval;
se::Object* funcObj = jsFunc.toObject();
bool succeed = funcObj->call(args, thisObj, &rval);
if (!succeed) {
se::ScriptEngine::getInstance()->clearException();
}
};
}
} while(false);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_set_PostMessage2UIThreadCallback);
static bool js_set_PostSyncMessage2UIThreadCallback(se::State& s) {
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
do {
if (args[0].isObject() && args[0].toObject()->isFunction()) {
//se::Value jsThis(s.thisObject());
se::Value jsFunc(args[0]);
//jsThis.toObject()->attachObject(jsFunc.toObject());
auto * thisObj = s.thisObject();
NapiHelper::_postSyncMsg2UIThreadCb = [=](const std::string larg0, const se::Value& larg1, se::Value* res) -> void {
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
CC_UNUSED bool ok = true;
se::ValueArray args;
args.resize(2);
ok &= std_string_to_seval(larg0, &args[0]);
CC_ASSERT(ok);
args[1] = larg1;
//ok &= nativevalue_to_se(larg1, args[1], nullptr /*ctx*/);
//se::Value rval;
se::Object* funcObj = jsFunc.toObject();
bool succeed = funcObj->call(args, thisObj, res);
if (!succeed) {
se::ScriptEngine::getInstance()->clearException();
}
};
}
} while(false);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_set_PostSyncMessage2UIThreadCallback);
// NAPI Interface
napi_value NapiHelper::getContext(napi_env env, napi_callback_info info) {
napi_status status;
napi_value exports;
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
if (argc != 1) {
napi_throw_type_error(env, NULL, "Wrong number of arguments");
return nullptr;
}
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) {
return nullptr;
}
if (valuetype != napi_number) {
napi_throw_type_error(env, NULL, "Wrong arguments");
return nullptr;
}
int64_t value;
NAPI_CALL(env, napi_get_value_int64(env, args[0], &value));
NAPI_CALL(env, napi_create_object(env, &exports));
switch (value) {
case APP_LIFECYCLE: {
// Register app lifecycle
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("onCreate", NapiHelper::napiOnCreate),
DECLARE_NAPI_FUNCTION("onShow", NapiHelper::napiOnShow),
DECLARE_NAPI_FUNCTION("onHide", NapiHelper::napiOnHide),
DECLARE_NAPI_FUNCTION("onDestroy", NapiHelper::napiOnDestroy),
DECLARE_NAPI_FUNCTION("onBackPress", NapiHelper::napiOnBackPress),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
}
break;
case JS_PAGE_LIFECYCLE: {
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("onPageShow", NapiHelper::napiOnPageShow),
DECLARE_NAPI_FUNCTION("onPageHide", NapiHelper::napiOnPageHide),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
} break;
case XCOMPONENT_REGISTER_LIFECYCLE_CALLBACK: {
} break;
case NATIVE_RENDER_API: {
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("nativeEngineInit", NapiHelper::napiNativeEngineInit),
DECLARE_NAPI_FUNCTION("nativeEngineStart", NapiHelper::napiNativeEngineStart),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
} break;
case WORKER_INIT: {
se::ScriptEngine::setEnv(env);
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("workerInit", NapiHelper::napiWorkerInit),
DECLARE_NAPI_FUNCTION("setPostMessageFunction", _SE(js_set_PostMessage2UIThreadCallback)),
DECLARE_NAPI_FUNCTION("setPostSyncMessageFunction", _SE(js_set_PostSyncMessage2UIThreadCallback)),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
} break;
case ENGINE_UTILS: {
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("resourceManagerInit", NapiHelper::napiResourceManagerInit),
DECLARE_NAPI_FUNCTION("writablePathInit", NapiHelper::napiWritablePathInit),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
}break;
case EDITBOX_UTILS: {
std::vector<napi_property_descriptor> desc;
OpenHarmonyEditBox::GetInterfaces(desc);
NAPI_CALL(env, napi_define_properties(env, exports, desc.size(), desc.data()));
}break;
case WEBVIEW_UTILS: {
std::vector<napi_property_descriptor> desc;
OpenHarmonyWebView::GetInterfaces(desc);
NAPI_CALL(env, napi_define_properties(env, exports, desc.size(), desc.data()));
} break;
case DISPLAY_UTILS: {
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("onDisplayChange", NapiHelper::napiOnDisplayChange),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
}
case UV_ASYNC_SEND: {
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("send", NapiHelper::napiASend),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
} break;
default:
LOGE("unknown type");
}
return exports;
}
// NAPI Interface
bool NapiHelper::exportFunctions(napi_env env, napi_value exports) {
napi_status status;
// Application/SDK etc. Init
// XComponent Init:
napi_value exportInstance = nullptr;
OH_NativeXComponent* nativeXComponent = nullptr;
int32_t ret;
char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
status = napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);
if (status != napi_ok) {
return false;
}
status = napi_unwrap(env, exportInstance, reinterpret_cast<void**>(&nativeXComponent));
if (status != napi_ok) {
LOGE("napi_unwrap error %{public}d", status);
return false;
}
ret = OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize);
if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
return false;
}
OpenHarmonyPlatform::getInstance()->setNativeXComponent(nativeXComponent);
return true;
}
napi_value NapiHelper::napiOnCreate(napi_env env, napi_callback_info info) {
// uv_loop_t* loop = nullptr;
// NAPI_CALL(env, napi_get_uv_event_loop(env, &loop));
// OpenHarmonyPlatform::getInstance()->onCreateNative(env, loop);
LOGD("NapiHelper::napiOnCreate");
return nullptr;
}
napi_value NapiHelper::napiOnShow(napi_env env, napi_callback_info info) {
cocos2d::WorkerMessageData data{cocos2d::MessageType::WM_APP_SHOW, nullptr, nullptr};
OpenHarmonyPlatform::getInstance()->enqueue(data);
Application* app = OpenHarmonyPlatform::getInstance()->g_app;
if (app) {
app->onResume();
}
LOGD("NapiHelper::napiOnShow");
return nullptr;
}
napi_value NapiHelper::napiOnHide(napi_env env, napi_callback_info info) {
cocos2d::WorkerMessageData data{cocos2d::MessageType::WM_APP_HIDE, nullptr, nullptr};
OpenHarmonyPlatform::getInstance()->enqueue(data);
Application* app = OpenHarmonyPlatform::getInstance()->g_app;
if (app) {
app->onPause();
}
LOGD("NapiHelper::napiOnHide");
return nullptr;
}
napi_value NapiHelper::napiOnBackPress(napi_env env, napi_callback_info info) {
KeyboardEvent event;
event.key = KEYCODE_BACK_OH;
event.action = KeyboardEvent::Action::RELEASE;
EventDispatcher::dispatchKeyboardEvent(event);
return nullptr;
}
napi_value NapiHelper::napiOnDestroy(napi_env env, napi_callback_info info) {
cocos2d::WorkerMessageData data{cocos2d::MessageType::WM_APP_DESTROY, nullptr, nullptr};
OpenHarmonyPlatform::getInstance()->enqueue(data);
LOGD("NapiHelper::napiOnDestroy");
return nullptr;
}
napi_value NapiHelper::napiOnPageShow(napi_env env, napi_callback_info info) {
LOGD("NapiHelper::napiOnPageShow");
return nullptr;
}
napi_value NapiHelper::napiOnPageHide(napi_env env, napi_callback_info info) {
LOGD("NapiHelper::napiOnPageHide");
return nullptr;
}
napi_value NapiHelper::napiNativeEngineInit(napi_env env, napi_callback_info info) {
LOGD("NapiHelper::napiNativeEngineInit");
se::ScriptEngine::setEnv(env);
OpenHarmonyPlatform::getInstance()->run(0, nullptr);
return nullptr;
}
napi_value NapiHelper::napiNativeEngineStart(napi_env env, napi_callback_info info) {
LOGD("NapiHelper::napiNativeEngineStart");
OpenHarmonyPlatform::getInstance()->requestVSync();
return nullptr;
}
napi_value NapiHelper::napiWorkerInit(napi_env env, napi_callback_info info) {
uv_loop_t* loop = nullptr;
NAPI_CALL(env, napi_get_uv_event_loop(env, &loop));
OpenHarmonyPlatform::getInstance()->workerInit(env, loop);
return nullptr;
}
napi_value NapiHelper::napiOnDisplayChange(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
CC_ASSERT(argc > 0);
int32_t value;
NAPI_CALL(env, napi_get_value_int32(env, args[0], &value));
cocos2d::Device::Rotation rotation = cocos2d::Device::Rotation::_0;
if(value == 0) {
rotation = cocos2d::Device::Rotation::_0;
} else if(value == 1) {
// TODO(qgh): The openharmony platform is rotated clockwise.
rotation = cocos2d::Device::Rotation::_270;
} else if(value == 2) {
rotation = cocos2d::Device::Rotation::_180;
} else if(value == 3) {
// TODO(qgh): The openharmony platform is rotated clockwise.
rotation = cocos2d::Device::Rotation::_90;
}
EventDispatcher::dispatchOrientationChangeEvent((int)rotation);
return nullptr;
}
napi_value NapiHelper::napiResourceManagerInit(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
FileUtilsOpenHarmony::initResourceManager(env, args[0]);
return nullptr;
}
napi_value NapiHelper::napiWritablePathInit(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
napi_status status;
char buffer[kMaxStringLen];
size_t result = 0;
NODE_API_CALL(status, env, napi_get_value_string_utf8(env, args[0], buffer, kMaxStringLen, &result));
FileUtilsOpenHarmony::_ohWritablePath = std::string(buffer);
return nullptr;
}
napi_value NapiHelper::napiASend(napi_env env, napi_callback_info info) {
OpenHarmonyPlatform::getInstance()->triggerMessageSignal();
return nullptr;
}
}

View File

@@ -0,0 +1,174 @@
/****************************************************************************
Copyright (c) 2022-2023 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.
****************************************************************************/
#pragma once
#include <napi/native_api.h>
#include <uv.h>
#include "scripting/js-bindings/jswrapper/SeApi.h"
#include "scripting/js-bindings/manual/jsb_conversions.hpp"
namespace cocos2d {
class NapiHelper {
public:
static napi_value getContext(napi_env env, napi_callback_info info);
// APP Lifecycle
static napi_value napiOnCreate(napi_env env, napi_callback_info info);
static napi_value napiOnShow(napi_env env, napi_callback_info info);
static napi_value napiOnHide(napi_env env, napi_callback_info info);
static napi_value napiOnDestroy(napi_env env, napi_callback_info info);
static napi_value napiOnBackPress(napi_env env, napi_callback_info info);
// JS Page : Lifecycle
static napi_value napiOnPageShow(napi_env env, napi_callback_info info);
static napi_value napiOnPageHide(napi_env env, napi_callback_info info);
// Worker Func
static napi_value napiWorkerInit(napi_env env, napi_callback_info info);
static napi_value napiASend(napi_env env, napi_callback_info info);
static napi_value napiNativeEngineInit(napi_env env, napi_callback_info info);
static napi_value napiNativeEngineStart(napi_env env, napi_callback_info info);
static napi_value napiWritablePathInit(napi_env env, napi_callback_info info);
static napi_value napiResourceManagerInit(napi_env env, napi_callback_info info);
static napi_value napiOnDisplayChange(napi_env env, napi_callback_info info);
template <class ReturnType>
static napi_value napiCallFunction(const std::string& functionName, ReturnType* value) {
if (!se::ScriptEngine::getInstance()->isValid()) {
return nullptr;
}
se::Value tickVal;
se::AutoHandleScope scope;
if (tickVal.isUndefined()) {
se::ScriptEngine::getInstance()->getGlobalObject()->getProperty(functionName, &tickVal);
}
se::Value rval;
se::ValueArray tickArgsValArr(1);
if (!tickVal.isUndefined()) {
tickVal.toObject()->call(tickArgsValArr, nullptr, &rval);
}
if(rval.isNullOrUndefined()) {
return nullptr;
}
bool ok = true;
ok &= seval_to_native_base_type(rval, value);
SE_PRECONDITION2(ok, nullptr, "Error processing arguments");
return nullptr;
}
static napi_value napiCallFunctionByStrArgs(const std::string& functionName, const std::string& args1, int32_t* value) {
if (!se::ScriptEngine::getInstance()->isValid()) {
return nullptr;
}
se::Value tickVal;
se::AutoHandleScope scope;
if (tickVal.isUndefined()) {
se::ScriptEngine::getInstance()->getGlobalObject()->getProperty(functionName, &tickVal);
}
se::Value rval;
se::ValueArray tickArgsValArr;
tickArgsValArr.push_back(se::Value(args1));
if (!tickVal.isUndefined()) {
tickVal.toObject()->call(tickArgsValArr, nullptr, &rval);
}
if(rval.isNullOrUndefined()) {
return nullptr;
}
bool ok = true;
ok &= seval_to_native_base_type(rval, value);
SE_PRECONDITION2(ok, nullptr, "Error processing arguments");
return nullptr;
}
static napi_value napiCallFunctionByFloatArgs(const std::string& functionName, float& sec, int32_t* value) {
if (!se::ScriptEngine::getInstance()->isValid()) {
return nullptr;
}
se::Value tickVal;
se::AutoHandleScope scope;
if (tickVal.isUndefined()) {
se::ScriptEngine::getInstance()->getGlobalObject()->getProperty(functionName, &tickVal);
}
se::Value rval;
se::ValueArray tickArgsValArr;
tickArgsValArr.push_back(se::Value(sec));
if (!tickVal.isUndefined()) {
tickVal.toObject()->call(tickArgsValArr, nullptr, &rval);
}
if(rval.isNullOrUndefined()) {
return nullptr;
}
bool ok = true;
ok &= seval_to_native_base_type(rval, value);
SE_PRECONDITION2(ok, nullptr, "Error processing arguments");
return nullptr;
}
static napi_value napiSetPostMessageFunction(napi_env env, napi_callback_info info);
// Napi export
static bool exportFunctions(napi_env env, napi_value exports);
static void postStringMessageToUIThread(const std::string& type, std::string param) {
if (!_postMsg2UIThreadCb) {
return;
}
CC_UNUSED bool ok = true;
se::Value value;
ok &= std_string_to_seval(param, &value);
_postMsg2UIThreadCb(type, value);
}
static void postIntMessageToUIThread(const std::string& type, int param) {
if (!_postMsg2UIThreadCb) {
return;
}
CC_UNUSED bool ok = true;
se::Value value;
ok &= native_int_to_se(param, value, nullptr /*ctx*/);
_postMsg2UIThreadCb(type, value);
}
static void postUnorderedMapMessageToUIThread(const std::string& type, std::unordered_map<std::string, cocos2d::Value> param) {
if (!_postMsg2UIThreadCb) {
return;
}
CC_UNUSED bool ok = true;
se::Value value;
ok &= native_unorderedmap_to_se(param, value, nullptr /*ctx*/);
_postMsg2UIThreadCb(type, value);
}
public:
using PostMessage2UIThreadCb = std::function<void(const std::string&, const se::Value&)>;
static PostMessage2UIThreadCb _postMsg2UIThreadCb;
using PostSyncMessage2UIThreadCb = std::function<void(const std::string&, const se::Value&, se::Value*)>;
static PostSyncMessage2UIThreadCb _postSyncMsg2UIThreadCb;
};
}

View File

@@ -0,0 +1,63 @@
/****************************************************************************
Copyright (c) 2022-2023 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 <ace/xcomponent/native_interface_xcomponent.h>
#include "scripting/js-bindings/jswrapper/SeApi.h"
#include "platform/openharmony/napi/NapiHelper.h"
const char kLibname[] = "cocos";
/*
* function for module exports
*/
static napi_value init(napi_env env, napi_value exports) {
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("getContext", cocos2d::NapiHelper::getContext),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
bool ret = cocos2d::NapiHelper::exportFunctions(env, exports);
if (!ret) {
LOGE("Init failed");
}
return exports;
}
/*
* Napi Module define
*/
static napi_module cocos2dModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = init, // called by ACE XComponent
.nm_modname = kLibname,
.nm_priv = ((void*)0),
.reserved = {0},
};
/*
* Module register function
*/
extern "C" __attribute__((constructor)) void RegisterModule(void) {
napi_module_register(&cocos2dModule);
}

View File

@@ -0,0 +1,113 @@
/****************************************************************************
Copyright (c) 2021-2023 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 "egl_core.h"
#include "platform/openharmony/napi/NapiHelper.h"
EGLConfig getConfig(int version, EGLDisplay eglDisplay) {
int attribList[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_STENCIL_SIZE, 8,
EGL_DEPTH_SIZE, 24,
EGL_NONE
};
EGLConfig configs = NULL;
int configsNum;
if (!eglChooseConfig(eglDisplay, attribList, &configs, 1, &configsNum)) {
LOGE("eglChooseConfig ERROR");
return NULL;
}
return configs;
}
void EGLCore::GLContextInit(void* window, int w, int h)
{
LOGD("EGLCore::GLContextInit window = %{public}p, w = %{public}d, h = %{public}d.", window, w, h);
width_ = w;
height_ = h;
mEglWindow = (EGLNativeWindowType)(window);
// 1. create sharedcontext
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (mEGLDisplay == EGL_NO_DISPLAY) {
LOGE("EGLCore::unable to get EGL display.");
return;
}
EGLint eglMajVers, eglMinVers;
if (!eglInitialize(mEGLDisplay, &eglMajVers, &eglMinVers)) {
mEGLDisplay = EGL_NO_DISPLAY;
LOGE("EGLCore::unable to initialize display");
return;
}
mEGLConfig = getConfig(3, mEGLDisplay);
if (mEGLConfig == nullptr) {
LOGE("EGLCore::GLContextInit config ERROR");
return;
}
// 2. Create EGL Surface from Native Window
if (mEglWindow) {
mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mEglWindow, nullptr);
if (mEGLSurface == nullptr) {
LOGE("EGLCore::eglCreateContext eglSurface is null");
return;
}
}
// 3. Create EGLContext from
int attrib3_list[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
mEGLContext = eglCreateContext(mEGLDisplay, mEGLConfig, mSharedEGLContext, attrib3_list);
if (!eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
LOGE("EGLCore::eglMakeCurrent error = %{public}d", eglGetError());
}
}
void EGLCore::Update()
{
eglSwapBuffers(mEGLDisplay, mEGLSurface);
}
bool EGLCore::checkGlError(const char* op)
{
LOGE("EGL ERROR CODE = %{public}x", eglGetError());
GLint error;
for (error = glGetError(); error; error = glGetError()) {
LOGE("ERROR: %{public}s, ERROR CODE = %{public}x", op, error);
return true;
}
return false;
}

View File

@@ -0,0 +1,53 @@
/****************************************************************************
Copyright (c) 2021-2023 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.
****************************************************************************/
#ifndef _GL_CORE_
#define _GL_CORE_
#include "platform/openharmony/CCGL-openharmony.h"
#include <string>
class EGLCore {
public:
EGLCore() {};
void GLContextInit(void* window, int w, int h);
void Update();
public:
int width_;
int height_;
private:
bool checkGlError(const char* op);
EGLNativeWindowType mEglWindow;
EGLDisplay mEGLDisplay = EGL_NO_DISPLAY;
EGLConfig mEGLConfig = nullptr;
EGLContext mEGLContext = EGL_NO_CONTEXT;
EGLContext mSharedEGLContext = EGL_NO_CONTEXT;
EGLSurface mEGLSurface = nullptr;
};
#endif // _GL_CORE_