no message

This commit is contained in:
gem
2025-02-18 15:21:31 +08:00
commit 2d133e56d7
1980 changed files with 465595 additions and 0 deletions

View File

@@ -0,0 +1,719 @@
/****************************************************************************
Copyright (c) 2018-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 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 "cocos/bindings/manual/JavaScriptJavaBridge.h"
#include "cocos/application/ApplicationManager.h"
#include "cocos/base/UTF8.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#if CC_PLATFORM == CC_PLATFORM_ANDROID
#include <android/log.h>
#elif CC_PLATFORM == CC_PLATFORM_OHOS
#include <hilog/log.h>
#endif
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "JavaScriptJavaBridge"
#ifndef ORG_JAVABRIDGE_CLASS_NAME
#define ORG_JAVABRIDGE_CLASS_NAME com_cocos_lib_CocosJavascriptJavaBridge
#endif
#define JNI_JSJAVABRIDGE(FUNC) JNI_METHOD1(ORG_JAVABRIDGE_CLASS_NAME, FUNC)
#define JSJ_ERR_OK (0)
#define JSJ_ERR_TYPE_NOT_SUPPORT (-1)
#define JSJ_ERR_INVALID_SIGNATURES (-2)
#define JSJ_ERR_METHOD_NOT_FOUND (-3)
#define JSJ_ERR_EXCEPTION_OCCURRED (-4)
#define JSJ_ERR_VM_THREAD_DETACHED (-5)
#define JSJ_ERR_VM_FAILURE (-6)
#define JSJ_ERR_CLASS_NOT_FOUND (-7)
class JavaScriptJavaBridge {
public:
enum class ValueType : char {
INVALID,
VOID,
INTEGER,
LONG,
FLOAT,
BOOLEAN,
STRING,
VECTOR,
FUNCTION
};
using ValueTypes = ccstd::vector<ValueType>;
using ReturnValue = union {
int intValue;
int64_t longValue;
float floatValue;
int boolValue;
ccstd::string *stringValue;
};
class CallInfo {
public:
CallInfo(const char *className, const char *methodName, const char *methodSig)
: _mClassName(className),
_mMethodName(methodName),
_mMethodSig(methodSig) {
memset(&_mRet, 0, sizeof(_mRet));
_mValid = validateMethodSig() && getMethodInfo();
}
~CallInfo();
bool isValid() const {
return _mValid;
}
int getErrorCode() const {
return _mError;
}
void tryThrowJSException() const {
if (_mError != JSJ_ERR_OK) {
se::ScriptEngine::getInstance()->throwException(getErrorMessage());
}
}
const char *getErrorMessage() const {
switch (_mError) {
case JSJ_ERR_TYPE_NOT_SUPPORT:
return "argument type is not supported";
case JSJ_ERR_INVALID_SIGNATURES:
return "invalid signature";
case JSJ_ERR_METHOD_NOT_FOUND:
return "method not found";
case JSJ_ERR_EXCEPTION_OCCURRED:
return "excpected occurred";
case JSJ_ERR_VM_THREAD_DETACHED:
return "vm thread detached";
case JSJ_ERR_VM_FAILURE:
return "vm failure";
case JSJ_ERR_CLASS_NOT_FOUND:
return "class not found";
case JSJ_ERR_OK:
default:
return "NOERROR";
}
}
JNIEnv *getEnv() const {
return _mEnv;
}
ValueType argumentTypeAtIndex(size_t index) {
return _mArgumentsType.at(index);
}
int getArgumentsCount() const {
return _mArgumentsCount;
}
ValueType getReturnValueType() {
return _mReturnType;
}
ReturnValue getReturnValue() {
return _mRet;
}
bool execute();
bool executeWithArgs(jvalue *args);
private:
bool _mValid{false};
int _mError{JSJ_ERR_OK};
ccstd::string _mClassName;
ccstd::string _mMethodName;
ccstd::string _mMethodSig;
int _mArgumentsCount{0};
ValueTypes _mArgumentsType;
ValueType _mReturnType{ValueType::VOID};
ReturnValue _mRet;
jstring _mRetjstring{nullptr};
JNIEnv *_mEnv{nullptr};
jclass _mClassID{nullptr};
jmethodID _mMethodID{nullptr};
bool validateMethodSig();
bool getMethodInfo();
ValueType checkType(const ccstd::string &sig, size_t *pos);
};
static bool convertReturnValue(ReturnValue retValue, ValueType type, se::Value *ret);
};
using JsCallback = std::function<void(const ccstd::string &, const ccstd::string &)>;
class ScriptNativeBridge {
public:
void callByNative(const ccstd::string &arg0, const ccstd::string &arg1);
inline void setCallback(const JsCallback &cb) {
_callback = cb;
}
static ScriptNativeBridge *bridgeCxxInstance;
se::Value jsCb;
private:
JsCallback _callback{nullptr}; // NOLINT(readability-identifier-naming)
};
extern "C" {
JNIEXPORT jint JNICALL JNI_JSJAVABRIDGE(evalString)(JNIEnv *env, jclass /*cls*/, jstring value) {
if (!se::ScriptEngine::getInstance()->isValid()) {
CC_LOG_DEBUG("ScriptEngine has not been initialized");
return 0;
}
se::AutoHandleScope hs;
bool strFlag = false;
ccstd::string strValue = cc::StringUtils::getStringUTFCharsJNI(env, value, &strFlag);
if (!strFlag) {
CC_LOG_DEBUG("JavaScriptJavaBridge_evalString error, invalid string code");
return 0;
}
se::ScriptEngine::getInstance()->evalString(strValue.c_str());
return 1;
}
JNIEXPORT void JNICALL
Java_com_cocos_lib_JsbBridge_nativeSendToScript(JNIEnv *env, jclass clazz, jstring arg0, jstring arg1) { // NOLINT
ccstd::string cArg0{cc::JniHelper::jstring2string(arg0)};
ccstd::string cArg1{cc::JniHelper::jstring2string(arg1)};
CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread([=]() {
ScriptNativeBridge::bridgeCxxInstance->callByNative(cArg0, cArg1);
});
}
} // extern "C"
ScriptNativeBridge *ScriptNativeBridge::bridgeCxxInstance{nullptr};
JavaScriptJavaBridge::CallInfo::~CallInfo() {
_mEnv->DeleteLocalRef(_mClassID);
if (_mReturnType == ValueType::STRING && _mRet.stringValue) {
_mEnv->DeleteLocalRef(_mRetjstring);
delete _mRet.stringValue;
}
}
bool JavaScriptJavaBridge::CallInfo::execute() {
switch (_mReturnType) {
case JavaScriptJavaBridge::ValueType::VOID:
_mEnv->CallStaticVoidMethod(_mClassID, _mMethodID);
break;
case JavaScriptJavaBridge::ValueType::INTEGER:
_mRet.intValue = _mEnv->CallStaticIntMethod(_mClassID, _mMethodID);
break;
case JavaScriptJavaBridge::ValueType::LONG:
_mRet.longValue = _mEnv->CallStaticLongMethod(_mClassID, _mMethodID);
break;
case JavaScriptJavaBridge::ValueType::FLOAT:
_mRet.floatValue = _mEnv->CallStaticFloatMethod(_mClassID, _mMethodID);
break;
case JavaScriptJavaBridge::ValueType::BOOLEAN:
_mRet.boolValue = _mEnv->CallStaticBooleanMethod(_mClassID, _mMethodID);
break;
case JavaScriptJavaBridge::ValueType::STRING: {
_mRetjstring = static_cast<jstring>(_mEnv->CallStaticObjectMethod(_mClassID, _mMethodID));
if (_mRetjstring) {
ccstd::string strValue = cc::StringUtils::getStringUTFCharsJNI(_mEnv, _mRetjstring);
_mRet.stringValue = ccnew ccstd::string(strValue);
} else {
_mRet.stringValue = nullptr;
}
break;
}
default:
_mError = JSJ_ERR_TYPE_NOT_SUPPORT;
SE_LOGD("Return type '%d' is not supported", static_cast<int>(_mReturnType));
return false;
}
if (_mEnv->ExceptionCheck() == JNI_TRUE) {
_mEnv->ExceptionDescribe();
_mEnv->ExceptionClear();
_mError = JSJ_ERR_EXCEPTION_OCCURRED;
return false;
}
return true;
}
bool JavaScriptJavaBridge::CallInfo::executeWithArgs(jvalue *args) {
switch (_mReturnType) {
case JavaScriptJavaBridge::ValueType::VOID:
_mEnv->CallStaticVoidMethodA(_mClassID, _mMethodID, args);
break;
case JavaScriptJavaBridge::ValueType::INTEGER:
_mRet.intValue = _mEnv->CallStaticIntMethodA(_mClassID, _mMethodID, args);
break;
case JavaScriptJavaBridge::ValueType::LONG:
_mRet.longValue = _mEnv->CallStaticLongMethodA(_mClassID, _mMethodID, args);
break;
case JavaScriptJavaBridge::ValueType::FLOAT:
_mRet.floatValue = _mEnv->CallStaticFloatMethodA(_mClassID, _mMethodID, args);
break;
case JavaScriptJavaBridge::ValueType::BOOLEAN:
_mRet.boolValue = _mEnv->CallStaticBooleanMethodA(_mClassID, _mMethodID, args);
break;
case JavaScriptJavaBridge::ValueType::STRING: {
_mRetjstring = static_cast<jstring>(_mEnv->CallStaticObjectMethodA(_mClassID, _mMethodID, args));
if (_mRetjstring) {
ccstd::string strValue = cc::StringUtils::getStringUTFCharsJNI(_mEnv, _mRetjstring);
_mRet.stringValue = ccnew ccstd::string(strValue);
} else {
_mRet.stringValue = nullptr;
}
break;
}
default:
_mError = JSJ_ERR_TYPE_NOT_SUPPORT;
SE_LOGD("Return type '%d' is not supported", static_cast<int>(_mReturnType));
return false;
}
if (_mEnv->ExceptionCheck() == JNI_TRUE) {
_mEnv->ExceptionDescribe();
_mEnv->ExceptionClear();
_mError = JSJ_ERR_EXCEPTION_OCCURRED;
return false;
}
return true;
}
bool JavaScriptJavaBridge::CallInfo::validateMethodSig() {
size_t len = _mMethodSig.length();
if (len < 3 || _mMethodSig[0] != '(') // min sig is "()V"
{
_mError = JSJ_ERR_INVALID_SIGNATURES;
return false;
}
size_t pos = 1;
while (pos < len && _mMethodSig[pos] != ')') {
JavaScriptJavaBridge::ValueType type = checkType(_mMethodSig, &pos);
if (type == ValueType::INVALID) return false;
_mArgumentsCount++;
_mArgumentsType.push_back(type);
pos++;
}
if (pos >= len || _mMethodSig[pos] != ')') {
_mError = JSJ_ERR_INVALID_SIGNATURES;
return false;
}
pos++;
_mReturnType = checkType(_mMethodSig, &pos);
return true;
}
JavaScriptJavaBridge::ValueType JavaScriptJavaBridge::CallInfo::checkType(const ccstd::string &sig, size_t *pos) {
switch (sig[*pos]) {
case 'I':
return JavaScriptJavaBridge::ValueType::INTEGER;
case 'J':
return JavaScriptJavaBridge::ValueType::LONG;
case 'F':
return JavaScriptJavaBridge::ValueType::FLOAT;
case 'Z':
return JavaScriptJavaBridge::ValueType::BOOLEAN;
case 'V':
return JavaScriptJavaBridge::ValueType::VOID;
case 'L':
size_t pos2 = sig.find_first_of(';', *pos + 1);
if (pos2 == ccstd::string::npos) {
_mError = JSJ_ERR_INVALID_SIGNATURES;
return ValueType::INVALID;
}
const ccstd::string t = sig.substr(*pos, pos2 - *pos + 1);
if (t == "Ljava/lang/String;") {
*pos = pos2;
return ValueType::STRING;
}
if (t == "Ljava/util/Vector;") {
*pos = pos2;
return ValueType::VECTOR;
}
_mError = JSJ_ERR_TYPE_NOT_SUPPORT;
return ValueType::INVALID;
}
_mError = JSJ_ERR_TYPE_NOT_SUPPORT;
return ValueType::INVALID;
}
bool JavaScriptJavaBridge::CallInfo::getMethodInfo() {
_mMethodID = nullptr;
_mEnv = nullptr;
JavaVM *jvm = cc::JniHelper::getJavaVM();
jint ret = jvm->GetEnv(reinterpret_cast<void **>(&_mEnv), JNI_VERSION_1_4);
switch (ret) {
case JNI_OK:
break;
case JNI_EDETACHED:
#if CC_PLATFORM == CC_PLATFORM_ANDROID
if (jvm->AttachCurrentThread(&_mEnv, nullptr) < 0) {
#else
if (jvm->AttachCurrentThread(reinterpret_cast<void **>(&_mEnv), nullptr) < 0) {
#endif
SE_LOGD("%s", "Failed to get the environment using AttachCurrentThread()");
_mError = JSJ_ERR_VM_THREAD_DETACHED;
return false;
}
break;
case JNI_EVERSION:
default:
SE_LOGD("%s", "Failed to get the environment using GetEnv()");
_mError = JSJ_ERR_VM_FAILURE;
return false;
}
jstring jstrClassName = _mEnv->NewStringUTF(_mClassName.c_str());
_mClassID = static_cast<jclass>(_mEnv->CallObjectMethod(cc::JniHelper::classloader,
cc::JniHelper::loadclassMethodMethodId,
jstrClassName));
if (nullptr == _mClassID) {
SE_LOGD("Classloader failed to find class of %s", _mClassName.c_str());
ccDeleteLocalRef(_mEnv, jstrClassName);
_mEnv->ExceptionClear();
_mError = JSJ_ERR_CLASS_NOT_FOUND;
return false;
}
ccDeleteLocalRef(_mEnv, jstrClassName);
_mMethodID = _mEnv->GetStaticMethodID(_mClassID, _mMethodName.c_str(), _mMethodSig.c_str());
if (!_mMethodID) {
_mEnv->ExceptionClear();
SE_LOGD("Failed to find method id of %s.%s %s",
_mClassName.c_str(),
_mMethodName.c_str(),
_mMethodSig.c_str());
_mError = JSJ_ERR_METHOD_NOT_FOUND;
return false;
}
return true;
}
bool JavaScriptJavaBridge::convertReturnValue(ReturnValue retValue, ValueType type, se::Value *ret) {
CC_ASSERT_NOT_NULL(ret);
switch (type) {
case JavaScriptJavaBridge::ValueType::INTEGER:
ret->setInt32(retValue.intValue);
break;
case JavaScriptJavaBridge::ValueType::LONG:
ret->setDouble(static_cast<double>(retValue.longValue));
break;
case JavaScriptJavaBridge::ValueType::FLOAT:
ret->setFloat(retValue.floatValue);
break;
case JavaScriptJavaBridge::ValueType::BOOLEAN:
ret->setBoolean(retValue.boolValue);
break;
case JavaScriptJavaBridge::ValueType::STRING:
if (retValue.stringValue) {
ret->setString(*retValue.stringValue);
} else {
ret->setNull();
}
break;
default:
ret->setUndefined();
break;
}
return true;
}
se::Class *__jsb_JavaScriptJavaBridge_class = nullptr; // NOLINT
static bool JavaScriptJavaBridge_finalize(se::State &s) { //NOLINT(readability-identifier-naming, misc-unused-parameters)
return true;
}
SE_BIND_FINALIZE_FUNC(JavaScriptJavaBridge_finalize)
static bool JavaScriptJavaBridge_constructor(se::State &s) { //NOLINT(readability-identifier-naming)
auto *cobj = ccnew JavaScriptJavaBridge();
s.thisObject()->setPrivateData(cobj);
return true;
}
SE_BIND_CTOR(JavaScriptJavaBridge_constructor, __jsb_JavaScriptJavaBridge_class, JavaScriptJavaBridge_finalize)
static bool JavaScriptJavaBridge_callStaticMethod(se::State &s) { //NOLINT(readability-identifier-naming)
const auto &args = s.args();
auto argc = static_cast<int>(args.size());
if (argc == 3) {
bool ok = false;
ccstd::string clsName;
ccstd::string methodName;
ccstd::string methodSig;
ok = sevalue_to_native(args[0], &clsName);
SE_PRECONDITION2(ok, false, "Converting class name failed!");
ok = sevalue_to_native(args[1], &methodName);
SE_PRECONDITION2(ok, false, "Converting method name failed!");
ok = sevalue_to_native(args[2], &methodSig);
SE_PRECONDITION2(ok, false, "Converting method signature failed!");
JavaScriptJavaBridge::CallInfo call(clsName.c_str(), methodName.c_str(), methodSig.c_str());
if (call.isValid()) {
ok = call.execute();
int errorCode = call.getErrorCode();
if (!ok || errorCode < 0) {
call.tryThrowJSException();
SE_REPORT_ERROR("call result code: %d", call.getErrorCode());
return false;
}
JavaScriptJavaBridge::convertReturnValue(call.getReturnValue(), call.getReturnValueType(), &s.rval());
return true;
}
call.tryThrowJSException();
SE_REPORT_ERROR("JavaScriptJavaBridge::CallInfo isn't valid!");
return false;
}
if (argc > 3) {
bool ok = false;
ccstd::string clsName;
ccstd::string methodName;
ccstd::string methodSig;
ok = sevalue_to_native(args[0], &clsName);
SE_PRECONDITION2(ok, false, "Converting class name failed!");
ok = sevalue_to_native(args[1], &methodName);
SE_PRECONDITION2(ok, false, "Converting method name failed!");
ok = sevalue_to_native(args[2], &methodSig);
SE_PRECONDITION2(ok, false, "Converting method signature failed!");
JavaScriptJavaBridge::CallInfo call(clsName.c_str(), methodName.c_str(), methodSig.c_str());
if (call.isValid() && call.getArgumentsCount() == (argc - 3)) {
int count = argc - 3;
auto *jargs = ccnew jvalue[count];
ccstd::vector<jobject> toReleaseObjects;
for (int i = 0; i < count; ++i) {
int index = i + 3;
switch (call.argumentTypeAtIndex(i)) {
case JavaScriptJavaBridge::ValueType::INTEGER: {
int integer = 0;
sevalue_to_native(args[index], &integer);
jargs[i].i = integer;
break;
}
case JavaScriptJavaBridge::ValueType::LONG: {
int64_t longVal = 0L;
sevalue_to_native(args[index], &longVal, nullptr);
jargs[i].j = longVal;
break;
}
case JavaScriptJavaBridge::ValueType::FLOAT: {
float floatNumber = 0.0F;
sevalue_to_native(args[index], &floatNumber);
jargs[i].f = floatNumber;
break;
}
case JavaScriptJavaBridge::ValueType::BOOLEAN: {
jargs[i].z = args[index].isBoolean() && args[index].toBoolean() ? JNI_TRUE : JNI_FALSE;
break;
}
case JavaScriptJavaBridge::ValueType::STRING: {
const auto &arg = args[index];
if (arg.isNull() || arg.isUndefined()) {
jargs[i].l = nullptr;
} else {
ccstd::string str;
seval_to_std_string(args[index], &str);
jargs[i].l = call.getEnv()->NewStringUTF(str.c_str());
toReleaseObjects.push_back(jargs[i].l);
}
break;
}
default:
SE_REPORT_ERROR("Unsupport type of parameter %d", i);
break;
}
}
ok = call.executeWithArgs(jargs);
for (const auto &obj : toReleaseObjects) {
ccDeleteLocalRef(call.getEnv(), obj);
}
delete[] jargs;
int errorCode = call.getErrorCode();
if (!ok || errorCode < 0) {
call.tryThrowJSException();
SE_REPORT_ERROR("js_JSJavaBridge : call result code: %d", errorCode);
return false;
}
JavaScriptJavaBridge::convertReturnValue(call.getReturnValue(), call.getReturnValueType(), &s.rval());
return true;
}
call.tryThrowJSException();
SE_REPORT_ERROR("call valid: %d, call.getArgumentsCount()= %d", call.isValid(), call.getArgumentsCount());
return false;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting >=3", argc);
return false;
}
SE_BIND_FUNC(JavaScriptJavaBridge_callStaticMethod)
static bool ScriptNativeBridge_getCallback(se::State &s) { //NOLINT(readability-identifier-naming)
auto *cobj = static_cast<ScriptNativeBridge *>(s.nativeThisObject());
CC_ASSERT_EQ(cobj, ScriptNativeBridge::bridgeCxxInstance);
s.rval() = cobj->jsCb;
SE_HOLD_RETURN_VALUE(cobj->jsCb, s.thisObject(), s.rval());
return true;
}
SE_BIND_PROP_GET(ScriptNativeBridge_getCallback)
static bool ScriptNativeBridge_setCallback(se::State &s) { //NOLINT(readability-identifier-naming)
auto *cobj = static_cast<ScriptNativeBridge *>(s.nativeThisObject());
CC_ASSERT_EQ(cobj, ScriptNativeBridge::bridgeCxxInstance);
const auto &args = s.args();
se::Value jsFunc = args[0];
cobj->jsCb = jsFunc;
if (jsFunc.isNullOrUndefined()) {
cobj->setCallback(nullptr);
} else {
CC_ASSERT(jsFunc.isObject() && jsFunc.toObject()->isFunction());
s.thisObject()->attachObject(jsFunc.toObject());
cobj->setCallback([jsFunc](const ccstd::string &arg0, const ccstd::string &arg1) {
se::AutoHandleScope hs;
se::ValueArray args;
args.push_back(se::Value(arg0));
if (!arg1.empty()) {
args.push_back(se::Value(arg1));
}
jsFunc.toObject()->call(args, nullptr);
});
}
return true;
}
SE_BIND_PROP_SET(ScriptNativeBridge_setCallback)
static bool ScriptNativeBridge_sendToNative(se::State &s) { //NOLINT(readability-identifier-naming)
const auto &args = s.args();
size_t argc = args.size();
if (argc >= 1 && argc < 3) {
bool ok = false;
ccstd::string arg0;
ok = sevalue_to_native(args[0], &arg0);
SE_PRECONDITION2(ok, false, "Converting arg0 failed!");
ccstd::string arg1;
if (argc == 2) {
ok = sevalue_to_native(args[1], &arg1);
SE_PRECONDITION2(ok, false, "Converting arg1 failed!");
}
callPlatformStringMethod(arg0, arg1);
SE_PRECONDITION2(ok, false, "call java method failed!");
return ok;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting at least %d and less than %d", static_cast<uint32_t>(argc), 1, 3);
return false;
}
SE_BIND_FUNC(ScriptNativeBridge_sendToNative)
bool register_javascript_java_bridge(se::Object *obj) { //NOLINT(readability-identifier-naming)
se::Class *cls = se::Class::create("JavascriptJavaBridge", obj, nullptr, _SE(JavaScriptJavaBridge_constructor));
cls->defineFinalizeFunction(_SE(JavaScriptJavaBridge_finalize));
cls->defineFunction("callStaticMethod", _SE(JavaScriptJavaBridge_callStaticMethod));
cls->install();
__jsb_JavaScriptJavaBridge_class = cls;
se::ScriptEngine::getInstance()->clearException();
return true;
}
se::Class *__jsb_ScriptNativeBridge_class = nullptr; // NOLINT
static bool ScriptNativeBridge_finalize(se::State &s) { //NOLINT
//bridgeCxxInstance is an se object which will be deleted in se holder.
ScriptNativeBridge::bridgeCxxInstance = nullptr;
return true;
}
SE_BIND_FINALIZE_FUNC(ScriptNativeBridge_finalize)
static bool ScriptNativeBridge_constructor(se::State &s) { //NOLINT(readability-identifier-naming)
auto *cobj = ccnew ScriptNativeBridge();
s.thisObject()->setPrivateData(cobj);
ScriptNativeBridge::bridgeCxxInstance = cobj;
return true;
}
SE_BIND_CTOR(ScriptNativeBridge_constructor, __jsb_ScriptNativeBridge_class, ScriptNativeBridge_finalize)
bool register_script_native_bridge(se::Object *obj) { //NOLINT(readability-identifier-naming)
se::Class *cls = se::Class::create("ScriptNativeBridge", obj, nullptr, _SE(ScriptNativeBridge_constructor));
cls->defineFinalizeFunction(_SE(ScriptNativeBridge_finalize));
cls->defineFunction("sendToNative", _SE(ScriptNativeBridge_sendToNative));
cls->defineProperty("onNative", _SE(ScriptNativeBridge_getCallback), _SE(ScriptNativeBridge_setCallback));
cls->install();
__jsb_ScriptNativeBridge_class = cls;
se::ScriptEngine::getInstance()->clearException();
return true;
}
void callPlatformStringMethod(const ccstd::string &arg0, const ccstd::string &arg1) {
cc::JniHelper::callStaticVoidMethod(
"com/cocos/lib/JsbBridge", "callByScript", arg0, arg1);
}
void ScriptNativeBridge::callByNative(const ccstd::string &arg0, const ccstd::string &arg1) {
_callback(arg0, arg1);
}

View File

@@ -0,0 +1,35 @@
/****************************************************************************
Copyright (c) 2018-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 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.
****************************************************************************/
#pragma once
#include "base/std/container/string.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "platform/java/jni/JniHelper.h"
namespace se {
class Object;
}
bool register_javascript_java_bridge(se::Object *obj); // NOLINT(readability-identifier-naming)
bool register_script_native_bridge(se::Object *obj); // NOLINT(readability-identifier-naming)
void callPlatformStringMethod(const ccstd::string &arg0, const ccstd::string &arg1); // NOLINT(readability-identifier-naming)

View File

@@ -0,0 +1,35 @@
/****************************************************************************
Copyright (c) 2018-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 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.
****************************************************************************/
#pragma once
#include "base/std/container/string.h"
#include "cocos/bindings/jswrapper/SeApi.h"
namespace se {
class Object;
}
bool register_javascript_objc_bridge(se::Object *obj);
bool register_script_native_bridge(se::Object *obj); // NOLINT(readability-identifier-naming)
bool callPlatformStringMethod(const ccstd::string &arg0, const ccstd::string &arg1);
void callScript(const ccstd::string &arg0, const ccstd::string &arg1);

View File

@@ -0,0 +1,437 @@
/****************************************************************************
Copyright (c) 2018-2022 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 "JavaScriptObjCBridge.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "base/std/container/string.h"
#include <iostream>
#import <Foundation/Foundation.h>
se::Value static objc_to_seval(id objcVal) {
se::Value ret;
if (objcVal == nil)
return ret;
if ([objcVal isKindOfClass:[NSNumber class]]) {
NSNumber *number = (NSNumber *)objcVal;
ccstd::string numberType = [number objCType];
if (numberType == @encode(BOOL) || numberType == @encode(bool)) {
ret.setBoolean([number boolValue]);
} else if (numberType == @encode(int) || numberType == @encode(long) || numberType == @encode(short) || numberType == @encode(unsigned int) || numberType == @encode(unsigned long) || numberType == @encode(unsigned short) || numberType == @encode(float) || numberType == @encode(double) || numberType == @encode(char) || numberType == @encode(unsigned char)) {
ret.setDouble([number doubleValue]);
} else {
CC_LOG_ERROR("Unknown number type: %s", numberType.c_str());
}
} else if ([objcVal isKindOfClass:[NSString class]]) {
const char *content = [objcVal cStringUsingEncoding:NSUTF8StringEncoding];
ret.setString(content);
} else if ([objcVal isKindOfClass:[NSDictionary class]]) {
CC_LOG_ERROR("JavaScriptObjCBridge doesn't support to bind NSDictionary!");
} else {
const char *content = [[NSString stringWithFormat:@"%@", objcVal] cStringUsingEncoding:NSUTF8StringEncoding];
ret.setString(content);
}
return ret;
}
#define JSO_ERR_OK (0)
#define JSO_ERR_TYPE_NOT_SUPPORT (-1)
#define JSO_ERR_INVALID_ARGUMENTS (-2)
#define JSO_ERR_METHOD_NOT_FOUND (-3)
#define JSO_ERR_EXCEPTION_OCCURRED (-4)
#define JSO_ERR_CLASS_NOT_FOUND (-5)
#define JSO_ERR_VM_FAILURE (-6)
class JavaScriptObjCBridge {
public:
class CallInfo {
public:
CallInfo(const char *className, const char *methodName)
: _className(className),
_methodName(methodName) {}
~CallInfo() {}
int getErrorCode() const {
return _error;
}
bool execute(const se::ValueArray &argv, se::Value &rval);
private:
int _error{JSO_ERR_OK};
ccstd::string _className;
ccstd::string _methodName;
};
};
using JsCallback = std::function<void(const ccstd::string &, const ccstd::string &)>;
class ScriptNativeBridge {
public:
void callByNative(const ccstd::string &arg0, const ccstd::string &arg1);
inline void setCallback(const JsCallback &cb) {
_callback = cb;
}
static ScriptNativeBridge *bridgeCxxInstance;
se::Value jsCb;
private:
JsCallback _callback{nullptr}; // NOLINT(readability-identifier-naming)
};
ScriptNativeBridge *ScriptNativeBridge::bridgeCxxInstance{nullptr};
bool JavaScriptObjCBridge::CallInfo::execute(const se::ValueArray &argv, se::Value &rval) {
NSString *className = [NSString stringWithCString:_className.c_str() encoding:NSUTF8StringEncoding];
NSString *methodName = [NSString stringWithCString:_methodName.c_str() encoding:NSUTF8StringEncoding];
if (!className || !methodName) {
_error = JSO_ERR_INVALID_ARGUMENTS;
return false;
}
Class targetClass = NSClassFromString(className);
if (!targetClass) {
_error = JSO_ERR_CLASS_NOT_FOUND;
return false;
}
SEL methodSel;
methodSel = NSSelectorFromString(methodName);
if (!methodSel) {
_error = JSO_ERR_METHOD_NOT_FOUND;
return false;
}
methodSel = NSSelectorFromString(methodName);
NSMethodSignature *methodSig = [targetClass methodSignatureForSelector:(SEL)methodSel];
if (methodSig == nil) {
_error = JSO_ERR_METHOD_NOT_FOUND;
NSLog(@"%@.%@ method isn't found!", className, methodName);
return false;
}
@try {
int argc = (int)argv.size();
NSUInteger argumentCount = [methodSig numberOfArguments];
if (argumentCount != argc) {
_error = JSO_ERR_INVALID_ARGUMENTS;
return false;
}
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setTarget:targetClass];
[invocation setSelector:methodSel];
for (int i = 2; i < argc; ++i) {
ccstd::string argumentType = [methodSig getArgumentTypeAtIndex:i];
const se::Value &arg = argv[i];
/* - (void)setArgument:(void *)argumentLocation atIndex:(NSInteger)idx;
*
* Refer to https://developer.apple.com/documentation/foundation/nsinvocation/1437834-setargument?language=objc
*
* This method copies the contents of buffer as the argument at index. The number of bytes copied is determined by the argument size.
* When the argument value is an object, pass a pointer to the variable (or memory) from which the object should be copied:
*/
if (arg.isString()) {
NSString *str = [NSString stringWithCString:arg.toString().c_str() encoding:NSUTF8StringEncoding];
[invocation setArgument:&str atIndex:i];
} else if (arg.isNumber()) {
if (argumentType == @encode(int)) {
int val = arg.toInt32();
[invocation setArgument:&val atIndex:i];
} else if (argumentType == @encode(long)) {
long val = static_cast<long>(arg.toDouble());
[invocation setArgument:&val atIndex:i];
} else if (argumentType == @encode(short)) {
short val = arg.toInt16();
[invocation setArgument:&val atIndex:i];
} else if (argumentType == @encode(unsigned int)) {
unsigned int val = arg.toUint32();
[invocation setArgument:&val atIndex:i];
} else if (argumentType == @encode(unsigned long)) {
unsigned long val = static_cast<unsigned long>(arg.toDouble());
[invocation setArgument:&val atIndex:i];
} else if (argumentType == @encode(unsigned short)) {
unsigned short val = arg.toUint16();
[invocation setArgument:&val atIndex:i];
} else if (argumentType == @encode(float)) {
float val = arg.toFloat();
[invocation setArgument:&val atIndex:i];
} else if (argumentType == @encode(double)) {
double val = arg.toDouble();
[invocation setArgument:&val atIndex:i];
} else if (argumentType == @encode(char)) {
char val = arg.toInt8();
[invocation setArgument:&val atIndex:i];
} else if (argumentType == @encode(unsigned char)) {
unsigned char val = arg.toUint8();
[invocation setArgument:&val atIndex:i];
} else if (argumentType == "@") { // NSNumber*
NSNumber *number = [NSNumber numberWithDouble:arg.toDouble()];
[invocation setArgument:&number atIndex:i];
} else {
NSLog(@"Unsupported argument type: %s", argumentType.c_str());
_error = JSO_ERR_TYPE_NOT_SUPPORT;
return false;
}
} else if (arg.isBoolean()) {
if (argumentType == @encode(BOOL)) {
BOOL val = arg.toBoolean() ? YES : NO;
[invocation setArgument:&val atIndex:i];
} else if (argumentType == @encode(bool)) {
bool val = arg.toBoolean();
[invocation setArgument:&val atIndex:i];
} else {
NSLog(@"Unsupported argument type: %s", argumentType.c_str());
_error = JSO_ERR_TYPE_NOT_SUPPORT;
return false;
}
} else if (arg.isNullOrUndefined()) {
// Don't call [invocation setArgument] will pass nil to relevant Objective-C argument.
} else {
NSLog(@"Unsupported argument type, se::Value::Type: %d", (int)arg.getType());
_error = JSO_ERR_TYPE_NOT_SUPPORT;
return false;
}
}
NSUInteger returnLength = [methodSig methodReturnLength];
ccstd::string returnType = [methodSig methodReturnType];
[invocation invoke];
if (returnLength > 0) {
if (returnType == "@") {
id ret;
[invocation getReturnValue:&ret];
rval = objc_to_seval(ret);
} else if (returnType == @encode(BOOL) || returnType == @encode(bool)) {
bool ret;
[invocation getReturnValue:&ret];
rval.setBoolean(ret);
} else if (returnType == @encode(int)) {
int ret;
[invocation getReturnValue:&ret];
rval.setInt32(ret);
} else if (returnType == @encode(long)) {
long ret;
[invocation getReturnValue:&ret];
rval.setDouble(static_cast<long>(ret));
} else if (returnType == @encode(short)) {
short ret;
[invocation getReturnValue:&ret];
rval.setInt16(ret);
} else if (returnType == @encode(unsigned int)) {
unsigned int ret;
[invocation getReturnValue:&ret];
rval.setUint32(ret);
} else if (returnType == @encode(unsigned long)) {
unsigned long ret;
[invocation getReturnValue:&ret];
rval.setDouble(static_cast<double>(ret));
} else if (returnType == @encode(unsigned short)) {
unsigned short ret;
[invocation getReturnValue:&ret];
rval.setUint16(ret);
} else if (returnType == @encode(float)) {
float ret;
[invocation getReturnValue:&ret];
rval.setFloat(ret);
} else if (returnType == @encode(double)) {
double ret;
[invocation getReturnValue:&ret];
rval.setDouble(ret);
} else if (returnType == @encode(char)) {
int8_t ret;
[invocation getReturnValue:&ret];
rval.setInt8(ret);
} else if (returnType == @encode(unsigned char)) {
uint8_t ret;
[invocation getReturnValue:&ret];
rval.setUint8(ret);
} else {
_error = JSO_ERR_TYPE_NOT_SUPPORT;
NSLog(@"not support return type = %s", returnType.c_str());
return false;
}
}
} @catch (NSException *exception) {
NSLog(@"EXCEPTION THROW: %@", exception);
_error = JSO_ERR_EXCEPTION_OCCURRED;
return false;
}
return true;
}
void ScriptNativeBridge::callByNative(const ccstd::string &arg0, const ccstd::string &arg1) {
_callback(arg0, arg1);
}
se::Class *__jsb_JavaScriptObjCBridge_class = nullptr;
static bool JavaScriptObjCBridge_finalize(se::State &s) {
return true;
}
SE_BIND_FINALIZE_FUNC(JavaScriptObjCBridge_finalize)
static bool JavaScriptObjCBridge_constructor(se::State &s) {
JavaScriptObjCBridge *cobj = ccnew JavaScriptObjCBridge();
s.thisObject()->setPrivateData(cobj);
return true;
}
SE_BIND_CTOR(JavaScriptObjCBridge_constructor, __jsb_JavaScriptObjCBridge_class, JavaScriptObjCBridge_finalize)
static bool JavaScriptObjCBridge_callStaticMethod(se::State &s) {
const auto &args = s.args();
int argc = (int)args.size();
if (argc >= 2) {
bool ok = false;
ccstd::string clsName, methodName;
ok = sevalue_to_native(args[0], &clsName);
SE_PRECONDITION2(ok, false, "Converting class name failed!");
ok = sevalue_to_native(args[1], &methodName);
SE_PRECONDITION2(ok, false, "Converting method name failed!");
JavaScriptObjCBridge::CallInfo call(clsName.c_str(), methodName.c_str());
ok = call.execute(args, s.rval());
if (!ok) {
s.rval().setUndefined();
SE_REPORT_ERROR("call (%s.%s) failed, result code: %d", clsName.c_str(), methodName.c_str(), call.getErrorCode());
return false;
}
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting >=2", argc);
return false;
}
SE_BIND_FUNC(JavaScriptObjCBridge_callStaticMethod)
static bool ScriptNativeBridge_getCallback(se::State &s) {
ScriptNativeBridge *cobj = (ScriptNativeBridge *)s.nativeThisObject();
CC_ASSERT_EQ(cobj, ScriptNativeBridge::bridgeCxxInstance);
s.rval() = cobj->jsCb;
SE_HOLD_RETURN_VALUE(cobj->jsCb, s.thisObject(), s.rval());
return true;
}
SE_BIND_PROP_GET(ScriptNativeBridge_getCallback)
static bool ScriptNativeBridge_setCallback(se::State &s) { //NOLINT(readability-identifier-naming)
auto *cobj = static_cast<ScriptNativeBridge *>(s.nativeThisObject());
CC_ASSERT_EQ(cobj, ScriptNativeBridge::bridgeCxxInstance);
const auto &args = s.args();
se::Value jsFunc = args[0];
cobj->jsCb = jsFunc;
if (jsFunc.isNullOrUndefined()) {
cobj->setCallback(nullptr);
} else {
CC_ASSERT(jsFunc.isObject() && jsFunc.toObject()->isFunction());
s.thisObject()->attachObject(jsFunc.toObject());
cobj->setCallback([jsFunc](const ccstd::string &arg0, const ccstd::string &arg1) {
se::AutoHandleScope hs;
se::ValueArray args;
args.push_back(se::Value(arg0));
if (!arg1.empty()) {
args.push_back(se::Value(arg1));
}
jsFunc.toObject()->call(args, nullptr);
});
}
return true;
}
SE_BIND_PROP_SET(ScriptNativeBridge_setCallback)
static bool ScriptNativeBridge_sendToNative(se::State &s) { //NOLINT
const auto &args = s.args();
int argc = (int)args.size();
if (argc >= 1 && argc < 3) {
bool ok = false;
ccstd::string arg0;
ok = sevalue_to_native(args[0], &arg0);
SE_PRECONDITION2(ok, false, "Converting first argument failed!");
ccstd::string arg1;
if (argc == 2) {
ok = sevalue_to_native(args[1], &arg1);
SE_PRECONDITION2(ok, false, "Converting second argument failed!");
}
ok = callPlatformStringMethod(arg0, arg1);
SE_PRECONDITION2(ok, false, "call platform event failed!");
return ok;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting at least %d and less than %d", argc, 1, 3);
return false;
}
SE_BIND_FUNC(ScriptNativeBridge_sendToNative)
bool register_javascript_objc_bridge(se::Object *obj) {
se::Class *cls = se::Class::create("JavaScriptObjCBridge", obj, nullptr, _SE(JavaScriptObjCBridge_constructor));
cls->defineFinalizeFunction(_SE(JavaScriptObjCBridge_finalize));
cls->defineFunction("callStaticMethod", _SE(JavaScriptObjCBridge_callStaticMethod));
cls->install();
__jsb_JavaScriptObjCBridge_class = cls;
se::ScriptEngine::getInstance()->clearException();
return true;
}
se::Class *__jsb_ScriptNativeBridge_class = nullptr; // NOLINT
static bool ScriptNativeBridge_finalize(se::State &s) { //NOLINT(readability-identifier-naming)
//bridgeCxxInstance is an se object which will be deleted in se holder.
ScriptNativeBridge::bridgeCxxInstance = nullptr;
return true;
}
SE_BIND_FINALIZE_FUNC(ScriptNativeBridge_finalize)
static bool ScriptNativeBridge_constructor(se::State &s) { //NOLINT(readability-identifier-naming)
auto *cobj = ccnew ScriptNativeBridge();
s.thisObject()->setPrivateData(cobj);
ScriptNativeBridge::bridgeCxxInstance = cobj;
return true;
}
SE_BIND_CTOR(ScriptNativeBridge_constructor, __jsb_ScriptNativeBridge_class, ScriptNativeBridge_finalize)
bool register_script_native_bridge(se::Object *obj) { //NOLINT(readability-identifier-naming)
se::Class *cls = se::Class::create("ScriptNativeBridge", obj, nullptr, _SE(ScriptNativeBridge_constructor));
cls->defineFinalizeFunction(_SE(ScriptNativeBridge_finalize));
cls->defineFunction("sendToNative", _SE(ScriptNativeBridge_sendToNative));
cls->defineProperty("onNative", _SE(ScriptNativeBridge_getCallback), _SE(ScriptNativeBridge_setCallback));
cls->install();
__jsb_ScriptNativeBridge_class = cls;
se::ScriptEngine::getInstance()->clearException();
return true;
}
void callScript(const ccstd::string &arg0, const ccstd::string &arg1) {
ScriptNativeBridge::bridgeCxxInstance->callByNative(arg0, arg1);
}

View File

@@ -0,0 +1,135 @@
/****************************************************************************
Copyright (c) 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 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 "application/ApplicationManager.h"
#include "bindings/jswrapper/SeApi.h"
#if CC_PLATFORM == CC_PLATFORM_ANDROID
#include "platform/android/adpf_manager.h"
#endif
#if CC_PLATFORM == CC_PLATFORM_ANDROID && CC_SUPPORT_ADPF
struct VmCallback {
uint32_t vmId{0xFEFEFEFE};
se::Value *cbFn{nullptr};
void reset() {
vmId = 0xFEFEFEFE;
delete cbFn;
cbFn = nullptr;
}
};
static VmCallback vmCallback;
static bool jsb_adpf_onThermalStatusChanged_set(se::State &state) { // NOLINT
auto fn = state.args()[0];
vmCallback.reset();
if (fn.isNullOrUndefined()) {
return true;
}
CC_ASSERT_TRUE(fn.toObject()->isFunction());
auto *scriptEngine = se::ScriptEngine::getInstance();
if (vmCallback.vmId != scriptEngine->getVMId()) {
vmCallback.vmId = scriptEngine->getVMId();
scriptEngine->addBeforeCleanupHook([]() {
vmCallback.reset();
});
}
vmCallback.cbFn = new se::Value(fn.toObject(), true);
// NOLINTNEXTLINE
ADPFManager::getInstance().SetThermalListener(+[](int prevStatus, int currentStatus) {
CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread([=]() {
se::AutoHandleScope scope;
se::ValueArray args;
args.push_back(se::Value(prevStatus));
args.push_back(se::Value(currentStatus));
args.push_back(se::Value(ATHERMAL_STATUS_NONE));
args.push_back(se::Value(ATHERMAL_STATUS_SHUTDOWN));
CC_ASSERT_EQ(vmCallback.vmId, se::ScriptEngine::getInstance()->getVMId());
if (vmCallback.cbFn && vmCallback.cbFn->isObject() && vmCallback.cbFn->toObject()->isFunction()) {
vmCallback.cbFn->toObject()->call(args, nullptr);
}
});
});
return true;
}
SE_BIND_PROP_SET(jsb_adpf_onThermalStatusChanged_set)
static bool jsb_adpf_onThermalStatusChanged_get(se::State &state) { // NOLINT
if (!vmCallback.cbFn) {
state.rval().setUndefined();
} else {
state.rval().setObject(vmCallback.cbFn->toObject());
}
return true;
}
SE_BIND_PROP_GET(jsb_adpf_onThermalStatusChanged_get)
static bool jsb_adpf_getThermalStatus(se::State &state) { // NOLINT
int statusInt = ADPFManager::getInstance().GetThermalStatus();
state.rval().setUint32(statusInt);
return true;
}
SE_BIND_PROP_GET(jsb_adpf_getThermalStatus)
static bool jsb_adpf_getThermalStatusMin(se::State &state) { // NOLINT
state.rval().setUint32(ATHERMAL_STATUS_NONE);
return true;
}
SE_BIND_PROP_GET(jsb_adpf_getThermalStatusMin)
static bool jsb_adpf_getThermalStatusMax(se::State &state) { // NOLINT
state.rval().setUint32(ATHERMAL_STATUS_SHUTDOWN);
return true;
}
SE_BIND_PROP_GET(jsb_adpf_getThermalStatusMax)
static bool jsb_adpf_getThermalStatusNormalized(se::State &state) { // NOLINT
float statusNormalized = ADPFManager::getInstance().GetThermalStatusNormalized();
state.rval().setFloat(statusNormalized);
return true;
}
SE_BIND_PROP_GET(jsb_adpf_getThermalStatusNormalized)
static bool jsb_adpf_getThermalHeadroom(se::State &state) { // NOLINT
float headroom = ADPFManager::getInstance().GetThermalHeadroom();
state.rval().setFloat(headroom);
return true;
}
SE_BIND_PROP_GET(jsb_adpf_getThermalHeadroom)
void jsb_register_ADPF(se::Object *ns) { // NOLINT
se::Value adpfObj{se::Object::createPlainObject()};
adpfObj.toObject()->defineProperty("thermalHeadroom", _SE(jsb_adpf_getThermalHeadroom), nullptr);
adpfObj.toObject()->defineProperty("thermalStatus", _SE(jsb_adpf_getThermalStatus), nullptr);
adpfObj.toObject()->defineProperty("thermalStatusMin", _SE(jsb_adpf_getThermalStatusMin), nullptr);
adpfObj.toObject()->defineProperty("thermalStatusMax", _SE(jsb_adpf_getThermalStatusMax), nullptr);
adpfObj.toObject()->defineProperty("thermalStatusNormalized", _SE(jsb_adpf_getThermalStatusNormalized), nullptr);
adpfObj.toObject()->defineProperty("thermalHeadroom", _SE(jsb_adpf_getThermalHeadroom), nullptr);
adpfObj.toObject()->defineProperty("onThermalStatusChanged", _SE(jsb_adpf_onThermalStatusChanged_get), _SE(jsb_adpf_onThermalStatusChanged_set));
ns->setProperty("adpf", adpfObj);
}
#else
void jsb_register_ADPF(se::Object *ns) {} // NOLINT
#endif // CC_PLATFORM_ANDROID

View File

@@ -0,0 +1,139 @@
/****************************************************************************
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 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 "bindings/auto/jsb_assets_auto.h"
#include "core/assets/Material.h"
#include "core/assets/SimpleTexture.h"
#include "core/assets/TextureBase.h"
#include "core/data/JSBNativeDataHolder.h"
#include "jsb_scene_manual.h"
#ifndef JSB_ALLOC
#define JSB_ALLOC(kls, ...) new (std::nothrow) kls(__VA_ARGS__)
#endif
#ifndef JSB_FREE
#define JSB_FREE(ptr) delete ptr
#endif
static bool js_assets_ImageAsset_setData(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::ImageAsset>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
if (argc == 1) {
uint8_t *data{nullptr};
if (args[0].isObject()) {
if (args[0].toObject()->isTypedArray()) {
args[0].toObject()->getTypedArrayData(&data, nullptr);
} else if (args[0].toObject()->isArrayBuffer()) {
args[0].toObject()->getArrayBufferData(&data, nullptr);
} else {
auto *dataHolder = static_cast<cc::JSBNativeDataHolder *>(args[0].toObject()->getPrivateData());
CC_ASSERT_NOT_NULL(dataHolder);
data = dataHolder->getData();
}
} else {
CC_ABORTF("setData with '%s'", args[0].toStringForce().c_str());
}
cobj->setData(data);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 0);
return false;
}
SE_BIND_FUNC(js_assets_ImageAsset_setData) // NOLINT(readability-identifier-naming)
static bool js_assets_SimpleTexture_registerListeners(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::SimpleTexture>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
auto *thisObj = s.thisObject();
cobj->on<cc::SimpleTexture::TextureUpdated>([thisObj](cc::SimpleTexture * /*emitter*/, cc::gfx::Texture *texture) {
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(texture, arg0, nullptr);
se::ScriptEngine::getInstance()->callFunction(thisObj, "_onGFXTextureUpdated", 1, &arg0);
});
cobj->on<cc::SimpleTexture::AfterAssignImage>([thisObj](cc::SimpleTexture * /*emitter*/, cc::ImageAsset *image) {
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(image, arg0, nullptr);
se::ScriptEngine::getInstance()->callFunction(thisObj, "_onAfterAssignImage", 1, &arg0);
});
return true;
}
SE_BIND_FUNC(js_assets_SimpleTexture_registerListeners) // NOLINT(readability-identifier-naming)
static bool js_assets_TextureBase_registerGFXSamplerUpdatedListener(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::TextureBase>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
auto *thisObj = s.thisObject();
cobj->on<cc::TextureBase::SamplerUpdated>([thisObj](cc::TextureBase * /*emitter*/, cc::gfx::Sampler *sampler) {
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(sampler, arg0, nullptr);
se::ScriptEngine::getInstance()->callFunction(thisObj, "_onGFXSamplerUpdated", 1, &arg0);
});
return true;
}
SE_BIND_FUNC(js_assets_TextureBase_registerGFXSamplerUpdatedListener) // NOLINT(readability-identifier-naming)
static bool js_assets_Material_registerPassesUpdatedListener(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::Material>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
auto *thisObj = s.thisObject();
cobj->on<cc::Material::PassesUpdated>([thisObj](cc::Material * /*emitter*/) {
se::AutoHandleScope hs;
se::ScriptEngine::getInstance()->callFunction(thisObj, "_onPassesUpdated", 0, nullptr);
});
return true;
}
SE_BIND_FUNC(js_assets_Material_registerPassesUpdatedListener) // NOLINT(readability-identifier-naming)
bool register_all_assets_manual(se::Object *obj) // NOLINT(readability-identifier-naming)
{
// Get the ns
se::Value nsVal;
if (!obj->getProperty("jsb", &nsVal)) {
se::HandleObject jsobj(se::Object::createPlainObject());
nsVal.setObject(jsobj);
obj->setProperty("jsb", nsVal);
}
__jsb_cc_ImageAsset_proto->defineFunction("setData", _SE(js_assets_ImageAsset_setData));
__jsb_cc_SimpleTexture_proto->defineFunction("_registerListeners", _SE(js_assets_SimpleTexture_registerListeners));
__jsb_cc_TextureBase_proto->defineFunction("_registerGFXSamplerUpdatedListener", _SE(js_assets_TextureBase_registerGFXSamplerUpdatedListener));
__jsb_cc_Material_proto->defineFunction("_registerPassesUpdatedListener", _SE(js_assets_Material_registerPassesUpdatedListener));
return true;
}

View File

@@ -0,0 +1,33 @@
/****************************************************************************
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 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.
****************************************************************************/
#pragma once
#include "cocos/bindings/jswrapper/SeApi.h"
namespace se {
class Object;
}
bool register_all_assets_manual(se::Object *obj); // NOLINT(readability-identifier-naming)

View File

@@ -0,0 +1,103 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
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 "jsb_audio_manual.h"
#include <cstdint>
#include "State.h"
#include "audio/include/AudioDef.h"
#include "audio/include/AudioEngine.h"
#include "bindings/auto/jsb_audio_auto.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global.h"
// NOLINTNEXTLINE(readability-identifier-naming)
static bool PCMHeader_to_seval(PCMHeader& header, se::Value* ret) {
CC_ASSERT_NOT_NULL(ret);
se::HandleObject obj(se::Object::createPlainObject());
obj->setProperty("totalFrames", se::Value(header.totalFrames));
obj->setProperty("sampleRate", se::Value(header.sampleRate));
obj->setProperty("bytesPerFrame", se::Value(header.bytesPerFrame));
obj->setProperty("channelCount", se::Value(header.channelCount));
obj->setProperty("audioFormat", se::Value(static_cast<int>(header.dataFormat)));
ret->setObject(obj);
return true;
}
static bool js_audio_AudioEngine_getPCMHeader(se::State& s) // NOLINT
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
ccstd::string arg0;
ok &= sevalue_to_native(args[0], &arg0, nullptr);
SE_PRECONDITION2(ok, false, "Error processing arguments");
PCMHeader header = cc::AudioEngine::getPCMHeader(arg0.c_str());
ok &= PCMHeader_to_seval(header, &s.rval());
SE_PRECONDITION2(ok, false, "Error processing arguments");
SE_HOLD_RETURN_VALUE(result, s.thisObject(), s.rval());
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_audio_AudioEngine_getPCMHeader)
static bool js_audio_AudioEngine_getOriginalPCMBuffer(se::State& s) // NOLINT
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 2) {
ccstd::string arg0; // url of audio
ok &= sevalue_to_native(args[0], &arg0, nullptr);
SE_PRECONDITION2(ok, false, "Error processing arguments");
uint32_t arg1{0};
ok &= sevalue_to_native(args[1], &arg1, nullptr);
SE_PRECONDITION2(ok, false, "Error processing arguments");
ccstd::vector<uint8_t> buffer = cc::AudioEngine::getOriginalPCMBuffer(arg0.c_str(), arg1);
se::HandleObject obj(se::Object::createArrayBufferObject(buffer.data(), buffer.size()));
s.rval().setObject(obj);
SE_PRECONDITION2(ok, false, "Error processing arguments");
SE_HOLD_RETURN_VALUE(result, s.thisObject(), s.rval());
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_audio_AudioEngine_getOriginalPCMBuffer)
bool register_all_audio_manual(se::Object* obj) // NOLINT
{
se::Value jsbVal;
obj->getProperty("jsb", &jsbVal);
se::Value audioEngineVal;
jsbVal.toObject()->getProperty("AudioEngine", &audioEngineVal);
audioEngineVal.toObject()->defineFunction("getPCMHeader", _SE(js_audio_AudioEngine_getPCMHeader));
audioEngineVal.toObject()->defineFunction("getOriginalPCMBuffer", _SE(js_audio_AudioEngine_getOriginalPCMBuffer));
return true;
}

View File

@@ -0,0 +1,35 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
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.
****************************************************************************/
// clang-format off
#pragma once
#include <type_traits>
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/audio/include/AudioEngine.h"
bool register_all_audio_manual(se::Object *obj); // NOLINT

View File

@@ -0,0 +1,27 @@
/****************************************************************************
Copyright (c) 2017-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 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 "jsb_classtype.h"
ccstd::unordered_map<const char *, se::Class *> JSBClassType::jsbClassTypeMap;

View File

@@ -0,0 +1,64 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
#pragma once
#include "bindings/jswrapper/SeApi.h"
#include <typeinfo>
class JSBClassType {
public:
template <typename T>
static void registerClass(se::Class *cls) {
const char *typeName = typeid(T).name();
CC_ASSERT(jsbClassTypeMap.find(typeName) == jsbClassTypeMap.end());
jsbClassTypeMap.emplace(typeName, cls);
}
template <typename T>
static se::Class *findClass(const T *nativeObj) {
bool found = false;
const char *typeNameFromValue = typeid(*nativeObj).name();
auto iter = jsbClassTypeMap.find(typeNameFromValue);
if (iter == jsbClassTypeMap.end()) {
const char *typeNameFromType = typeid(T).name();
iter = jsbClassTypeMap.find(typeNameFromType);
if (iter != jsbClassTypeMap.end()) {
found = true;
jsbClassTypeMap.emplace(typeNameFromValue, iter->second);
}
} else {
found = true;
}
return found ? iter->second : nullptr;
}
static void cleanup() {
jsbClassTypeMap.clear();
}
private:
static ccstd::unordered_map<const char *, se::Class *> jsbClassTypeMap;
};

View File

@@ -0,0 +1,813 @@
/****************************************************************************
Copyright (c) 2017-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 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 "jsb_cocos_manual.h"
#include "bindings/manual/jsb_global.h"
#include "cocos/bindings/auto/jsb_cocos_auto.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global_init.h"
#include "application/ApplicationManager.h"
#include "platform/interfaces/modules/ISystemWindowManager.h"
#include "storage/local-storage/LocalStorage.h"
extern se::Object *__jsb_cc_FileUtils_proto; // NOLINT(readability-redundant-declaration, readability-identifier-naming)
static bool jsb_ccx_empty_func(se::State & /*s*/) { // NOLINT(readability-identifier-naming)
return true;
}
SE_BIND_FUNC(jsb_ccx_empty_func) // NOLINT(readability-identifier-naming)
class JSPlistDelegator : public cc::SAXDelegator {
public:
static JSPlistDelegator *getInstance() {
static JSPlistDelegator *pInstance = nullptr;
if (pInstance == nullptr) {
pInstance = ccnew JSPlistDelegator();
}
return pInstance;
};
~JSPlistDelegator() override;
cc::SAXParser *getParser();
ccstd::string parse(const ccstd::string &path);
ccstd::string parseText(const ccstd::string &text);
// implement pure virtual methods of SAXDelegator
void startElement(void *ctx, const char *name, const char **atts) override;
void endElement(void *ctx, const char *name) override;
void textHandler(void *ctx, const char *ch, int len) override;
private:
cc::SAXParser _parser;
ccstd::string _result;
bool _isStoringCharacters;
ccstd::string _currentValue;
};
// cc.PlistParser.getInstance()
static bool js_PlistParser_getInstance(se::State &s) { // NOLINT(readability-identifier-naming)
JSPlistDelegator *delegator = JSPlistDelegator::getInstance();
cc::SAXParser *parser = delegator->getParser();
if (parser) {
native_ptr_to_seval<cc::SAXParser>(parser, __jsb_cc_SAXParser_class, &s.rval());
s.rval().toObject()->root();
return true;
}
return false;
}
SE_BIND_FUNC(js_PlistParser_getInstance) // NOLINT(readability-identifier-naming)
// cc.PlistParser.getInstance().parse(text)
static bool js_PlistParser_parse(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
size_t argc = args.size();
JSPlistDelegator *delegator = JSPlistDelegator::getInstance();
bool ok = true;
if (argc == 1) {
ccstd::string arg0;
ok &= sevalue_to_native(args[0], &arg0);
SE_PRECONDITION2(ok, false, "Error processing arguments");
ccstd::string parsedStr = delegator->parseText(arg0);
std::replace(parsedStr.begin(), parsedStr.end(), '\n', ' ');
se::Value strVal;
nativevalue_to_se(parsedStr, strVal);
se::HandleObject robj(se::Object::createJSONObject(strVal.toString()));
s.rval().setObject(robj);
return true;
}
SE_REPORT_ERROR("js_PlistParser_parse : wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_PlistParser_parse)
cc::SAXParser *JSPlistDelegator::getParser() {
return &_parser;
}
ccstd::string JSPlistDelegator::parse(const ccstd::string &path) {
_result.clear();
cc::SAXParser parser;
if (parser.init("UTF-8")) {
parser.setDelegator(this);
parser.parse(cc::FileUtils::getInstance()->fullPathForFilename(path));
}
return _result;
}
JSPlistDelegator::~JSPlistDelegator() {
CC_LOG_INFO("deallocing __JSSAXDelegator: %p", this);
}
ccstd::string JSPlistDelegator::parseText(const ccstd::string &text) {
_result.clear();
cc::SAXParser parser;
if (parser.init("UTF-8")) {
parser.setDelegator(this);
parser.parse(text.c_str(), text.size());
}
return _result;
}
void JSPlistDelegator::startElement(void * /*ctx*/, const char *name, const char ** /*atts*/) {
_isStoringCharacters = true;
_currentValue.clear();
ccstd::string elementName{name};
auto end = static_cast<int>(_result.size()) - 1;
if (end >= 0 && _result[end] != '{' && _result[end] != '[' && _result[end] != ':') {
_result += ",";
}
if (elementName == "dict") {
_result += "{";
} else if (elementName == "array") {
_result += "[";
}
}
void JSPlistDelegator::endElement(void * /*ctx*/, const char *name) {
_isStoringCharacters = false;
ccstd::string elementName{name};
if (elementName == "dict") {
_result += "}";
} else if (elementName == "array") {
_result += "]";
} else if (elementName == "key") {
_result += "\"" + _currentValue + "\":";
} else if (elementName == "string") {
_result += "\"" + _currentValue + "\"";
} else if (elementName == "false" || elementName == "true") {
_result += elementName;
} else if (elementName == "real" || elementName == "integer") {
_result += _currentValue;
}
}
void JSPlistDelegator::textHandler(void * /*unused*/, const char *ch, int len) {
ccstd::string text(ch, 0, len);
if (_isStoringCharacters) {
_currentValue += text;
}
}
static bool register_plist_parser(se::Object * /*obj*/) { // NOLINT(readability-identifier-naming)
se::Value v;
__jsbObj->getProperty("PlistParser", &v);
CC_ASSERT(v.isObject());
v.toObject()->defineFunction("getInstance", _SE(js_PlistParser_getInstance));
__jsb_cc_SAXParser_proto->defineFunction("parse", _SE(js_PlistParser_parse));
se::ScriptEngine::getInstance()->clearException();
return true;
}
// cc.sys.localStorage
static bool JSB_localStorageGetItem(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
size_t argc = args.size();
if (argc == 1) {
bool ok = true;
ccstd::string key;
ok = sevalue_to_native(args[0], &key);
SE_PRECONDITION2(ok, false, "Error processing arguments");
ccstd::string value;
ok = localStorageGetItem(key, &value);
if (ok) {
s.rval().setString(value);
} else {
s.rval().setNull(); // Should return null to make JSB behavior same as Browser since returning undefined will make JSON.parse(undefined) trigger exception.
}
return true;
}
SE_REPORT_ERROR("Invalid number of arguments");
return false;
}
SE_BIND_FUNC(JSB_localStorageGetItem) // NOLINT(readability-identifier-naming)
static bool JSB_localStorageRemoveItem(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
size_t argc = args.size();
if (argc == 1) {
bool ok = true;
ccstd::string key;
ok = sevalue_to_native(args[0], &key);
SE_PRECONDITION2(ok, false, "Error processing arguments");
localStorageRemoveItem(key);
return true;
}
SE_REPORT_ERROR("Invalid number of arguments");
return false;
}
SE_BIND_FUNC(JSB_localStorageRemoveItem) // NOLINT(readability-identifier-naming)
static bool JSB_localStorageSetItem(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
size_t argc = args.size();
if (argc == 2) {
bool ok = true;
ccstd::string key;
ok = sevalue_to_native(args[0], &key);
SE_PRECONDITION2(ok, false, "Error processing arguments");
ccstd::string value = args[1].toStringForce();
localStorageSetItem(key, value);
return true;
}
SE_REPORT_ERROR("Invalid number of arguments");
return false;
}
SE_BIND_FUNC(JSB_localStorageSetItem) // NOLINT(readability-identifier-naming)
static bool JSB_localStorageClear(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
size_t argc = args.size();
if (argc == 0) {
localStorageClear();
return true;
}
SE_REPORT_ERROR("Invalid number of arguments");
return false;
}
SE_BIND_FUNC(JSB_localStorageClear) // NOLINT(readability-identifier-naming)
static bool JSB_localStorageKey(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
size_t argc = args.size();
if (argc == 1) {
bool ok = true;
int nIndex = 0;
ok = sevalue_to_native(args[0], &nIndex);
SE_PRECONDITION2(ok, false, "Error processing arguments");
ccstd::string value;
localStorageGetKey(nIndex, &value);
s.rval().setString(value);
return true;
}
SE_REPORT_ERROR("Invalid number of arguments");
return false;
}
SE_BIND_FUNC(JSB_localStorageKey) // NOLINT(readability-identifier-naming)
static bool JSB_localStorage_getLength(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
size_t argc = args.size();
if (argc == 0) {
int nLength = 0;
localStorageGetLength(nLength);
s.rval().setInt32(nLength);
return true;
}
SE_REPORT_ERROR("Invalid number of arguments");
return false;
}
SE_BIND_PROP_GET(JSB_localStorage_getLength); // NOLINT(readability-identifier-naming)
static bool register_sys_localStorage(se::Object *obj) { // NOLINT(readability-identifier-naming)
se::Value sys;
if (!obj->getProperty("sys", &sys)) {
se::HandleObject sysObj(se::Object::createPlainObject());
obj->setProperty("sys", se::Value(sysObj));
sys.setObject(sysObj);
}
se::HandleObject localStorageObj(se::Object::createPlainObject());
sys.toObject()->setProperty("localStorage", se::Value(localStorageObj));
localStorageObj->defineFunction("getItem", _SE(JSB_localStorageGetItem));
localStorageObj->defineFunction("removeItem", _SE(JSB_localStorageRemoveItem));
localStorageObj->defineFunction("setItem", _SE(JSB_localStorageSetItem));
localStorageObj->defineFunction("clear", _SE(JSB_localStorageClear));
localStorageObj->defineFunction("key", _SE(JSB_localStorageKey));
localStorageObj->defineProperty("length", _SE(JSB_localStorage_getLength), nullptr);
ccstd::string strFilePath = cc::FileUtils::getInstance()->getWritablePath();
#if defined(__QNX__)
// In the QNX environment, the execution of this statement will not take effect.
// Not sure why
// strFilePath += "/jsb.sqlite";
// Use another way
char path[256] = {0};
sprintf(path, "%s/jsb.sqlite", strFilePath.c_str());
localStorageInit(path);
#else
strFilePath += "/jsb.sqlite";
localStorageInit(strFilePath);
#endif
se::ScriptEngine::getInstance()->addBeforeCleanupHook([]() {
localStorageFree();
});
se::ScriptEngine::getInstance()->clearException();
return true;
}
//IDEA: move to auto bindings.
static bool js_CanvasRenderingContext2D_setCanvasBufferUpdatedCallback(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::ICanvasRenderingContext2D *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
std::function<void(const cc::Data &)> arg0;
do {
if (args[0].isObject() && args[0].toObject()->isFunction()) {
se::Value jsThis(s.thisObject());
se::Value jsFunc(args[0]);
jsThis.toObject()->attachObject(jsFunc.toObject());
se::Object *thisObj = s.thisObject();
auto lambda = [=](const cc::Data &larg0) -> void {
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
CC_UNUSED bool ok = true;
se::ValueArray args;
args.resize(1);
ok &= Data_to_TypedArray(larg0, &args[0]);
se::Value rval;
se::Object *funcObj = jsFunc.toObject();
bool succeed = funcObj->call(args, thisObj, &rval);
if (!succeed) {
se::ScriptEngine::getInstance()->clearException();
}
};
// Add an unroot to avoid the root of the copy constructor caused by the internal reference of Lambda.
if (thisObj) {
thisObj->unroot();
}
jsFunc.toObject()->unroot();
arg0 = lambda;
} else {
arg0 = nullptr;
}
} while (false);
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->setCanvasBufferUpdatedCallback(arg0);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_CanvasRenderingContext2D_setCanvasBufferUpdatedCallback) // NOLINT(readability-identifier-naming)
static void setCanvasRenderingContext2DProps(cc::ICanvasRenderingContext2D *context, const se::Value &val) {
se::Object *props = val.toObject();
se::Value propVal;
props->getProperty("lineWidth", &propVal);
if (!propVal.isUndefined()) context->setLineWidth(propVal.toFloat());
props->getProperty("lineJoin", &propVal);
if (!propVal.isUndefined()) context->setLineJoin(propVal.toString());
props->getProperty("fillStyle", &propVal);
if (!propVal.isUndefined()) context->setFillStyle(propVal.toString());
props->getProperty("font", &propVal);
if (!propVal.isUndefined()) context->setFont(propVal.toString());
props->getProperty("lineCap", &propVal);
if (!propVal.isUndefined()) context->setLineCap(propVal.toString());
props->getProperty("textAlign", &propVal);
if (!propVal.isUndefined()) context->setTextAlign(propVal.toString());
props->getProperty("textBaseline", &propVal);
if (!propVal.isUndefined()) context->setTextBaseline(propVal.toString());
props->getProperty("strokeStyle", &propVal);
if (!propVal.isUndefined()) context->setStrokeStyle(propVal.toString());
props->getProperty("globalCompositeOperation", &propVal);
if (!propVal.isUndefined()) context->setGlobalCompositeOperation(propVal.toString());
props->getProperty("shadowBlur", &propVal);
if (!propVal.isUndefined()) context->setShadowBlur(propVal.toFloat());
props->getProperty("shadowColor", &propVal);
if (!propVal.isUndefined()) context->setShadowColor(propVal.toString());
props->getProperty("shadowOffsetX", &propVal);
if (!propVal.isUndefined()) context->setShadowOffsetX(propVal.toFloat());
props->getProperty("shadowOffsetY", &propVal);
if (!propVal.isUndefined()) context->setShadowOffsetY(propVal.toFloat());
}
static bool js_engine_CanvasRenderingContext2D_measureText(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::ICanvasRenderingContext2D *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 2) {
ccstd::string arg0;
ok &= sevalue_to_native(args[0], &arg0);
SE_PRECONDITION2(ok, false, "Error processing arguments");
SE_PRECONDITION2(args[1].isObject(), false, "no attributes set.");
setCanvasRenderingContext2DProps(cobj, args[1]);
cc::Size result = cobj->measureText(arg0);
ok &= nativevalue_to_se(result, s.rval());
SE_PRECONDITION2(ok, false, "Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_engine_CanvasRenderingContext2D_measureText) // NOLINT(readability-identifier-naming)
static bool js_engine_CanvasRenderingContext2D_fillRect(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::ICanvasRenderingContext2D *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 5) {
float arg0 = 0;
float arg1 = 0;
float arg2 = 0;
float arg3 = 0;
ok &= sevalue_to_native(args[0], &arg0);
ok &= sevalue_to_native(args[1], &arg1);
ok &= sevalue_to_native(args[2], &arg2);
ok &= sevalue_to_native(args[3], &arg3);
SE_PRECONDITION2(args[4].isObject(), false, "no attributes set.");
setCanvasRenderingContext2DProps(cobj, args[4]);
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->fillRect(arg0, arg1, arg2, arg3);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 4);
return false;
}
SE_BIND_FUNC(js_engine_CanvasRenderingContext2D_fillRect) // NOLINT(readability-identifier-naming)
static bool js_engine_CanvasRenderingContext2D_fillText(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::ICanvasRenderingContext2D *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 5) {
ccstd::string arg0;
float arg1 = 0;
float arg2 = 0;
float arg3 = 0;
ok &= sevalue_to_native(args[0], &arg0);
ok &= sevalue_to_native(args[1], &arg1);
ok &= sevalue_to_native(args[2], &arg2);
SE_PRECONDITION2(args[4].isObject(), false, "no attributes set.");
setCanvasRenderingContext2DProps(cobj, args[4]);
if (args[3].isUndefined()) {
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->fillText(arg0, arg1, arg2, -1.0F);
} else {
ok &= sevalue_to_native(args[3], &arg3);
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->fillText(arg0, arg1, arg2, arg3);
}
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 4);
return false;
}
SE_BIND_FUNC(js_engine_CanvasRenderingContext2D_fillText) // NOLINT(readability-identifier-naming)
static bool js_engine_CanvasRenderingContext2D_strokeText(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::ICanvasRenderingContext2D *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
bool ok = true;
if (argc == 5) {
ccstd::string arg0;
float arg1 = 0;
float arg2 = 0;
float arg3 = 0;
ok &= sevalue_to_native(args[0], &arg0);
ok &= sevalue_to_native(args[1], &arg1);
ok &= sevalue_to_native(args[2], &arg2);
SE_PRECONDITION2(args[4].isObject(), false, "no attributes set.");
setCanvasRenderingContext2DProps(cobj, args[4]);
if (!args[3].isUndefined()) {
ok &= sevalue_to_native(args[3], &arg3);
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->strokeText(arg0, arg1, arg2, arg3);
} else {
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->strokeText(arg0, arg1, arg2, -1.0F);
}
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 4);
return false;
}
SE_BIND_FUNC(js_engine_CanvasRenderingContext2D_strokeText) // NOLINT(readability-identifier-naming)
static se::Object *deviceMotionObject = nullptr;
static bool JSB_getDeviceMotionValue(se::State &s) { // NOLINT(readability-identifier-naming)
if (deviceMotionObject == nullptr) {
deviceMotionObject = se::Object::createArrayObject(9);
deviceMotionObject->root();
}
const auto &v = cc::Device::getDeviceMotionValue();
deviceMotionObject->setArrayElement(0, se::Value(v.accelerationX));
deviceMotionObject->setArrayElement(1, se::Value(v.accelerationY));
deviceMotionObject->setArrayElement(2, se::Value(v.accelerationZ));
deviceMotionObject->setArrayElement(3, se::Value(v.accelerationIncludingGravityX));
deviceMotionObject->setArrayElement(4, se::Value(v.accelerationIncludingGravityY));
deviceMotionObject->setArrayElement(5, se::Value(v.accelerationIncludingGravityZ));
deviceMotionObject->setArrayElement(6, se::Value(v.rotationRateAlpha));
deviceMotionObject->setArrayElement(7, se::Value(v.rotationRateBeta));
deviceMotionObject->setArrayElement(8, se::Value(v.rotationRateGamma));
s.rval().setObject(deviceMotionObject);
return true;
}
SE_BIND_FUNC(JSB_getDeviceMotionValue) // NOLINT(readability-identifier-naming)
static bool register_device(se::Object * /*obj*/) { // NOLINT(readability-identifier-naming)
se::Value device;
__jsbObj->getProperty("Device", &device);
device.toObject()->defineFunction("getDeviceMotionValue", _SE(JSB_getDeviceMotionValue));
se::ScriptEngine::getInstance()->addBeforeCleanupHook([]() {
if (deviceMotionObject != nullptr) {
deviceMotionObject->unroot();
deviceMotionObject->decRef();
deviceMotionObject = nullptr;
}
});
se::ScriptEngine::getInstance()->clearException();
return true;
}
static bool register_canvas_context2d(se::Object * /*obj*/) { // NOLINT(readability-identifier-naming)
__jsb_cc_ICanvasRenderingContext2D_proto->defineFunction("_setCanvasBufferUpdatedCallback", _SE(js_CanvasRenderingContext2D_setCanvasBufferUpdatedCallback));
__jsb_cc_ICanvasRenderingContext2D_proto->defineFunction("fillText", _SE(js_engine_CanvasRenderingContext2D_fillText));
__jsb_cc_ICanvasRenderingContext2D_proto->defineFunction("strokeText", _SE(js_engine_CanvasRenderingContext2D_strokeText));
__jsb_cc_ICanvasRenderingContext2D_proto->defineFunction("fillRect", _SE(js_engine_CanvasRenderingContext2D_fillRect));
__jsb_cc_ICanvasRenderingContext2D_proto->defineFunction("measureText", _SE(js_engine_CanvasRenderingContext2D_measureText));
se::ScriptEngine::getInstance()->clearException();
return true;
}
static bool js_engine_FileUtils_listFilesRecursively(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::FileUtils *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 2) {
ccstd::string arg0;
ccstd::vector<ccstd::string> arg1;
ok &= sevalue_to_native(args[0], &arg0);
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->listFilesRecursively(arg0, &arg1);
se::Object *list = args[1].toObject();
SE_PRECONDITION2(args[1].isObject() && list->isArray(), false, "2nd argument should be an Array");
for (uint32_t i = 0; i < static_cast<uint32_t>(arg1.size()); i++) {
list->setArrayElement(i, se::Value(arg1[i]));
}
list->setProperty("length", se::Value(static_cast<uint32_t>(arg1.size())));
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
return false;
}
SE_BIND_FUNC(js_engine_FileUtils_listFilesRecursively) // NOLINT(readability-identifier-naming)
static bool js_se_setExceptionCallback(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
if (args.size() != 1 || !args[0].isObject() || !args[0].toObject()->isFunction()) {
SE_REPORT_ERROR("expect 1 arguments of Function type, %d provided", (int)args.size());
return false;
}
se::Object *objFunc = args[0].toObject();
// se::Value::reset will invoke decRef() while destroying s.args()
// increase ref here
objFunc->incRef();
if (s.thisObject()) {
s.thisObject()->attachObject(objFunc); // prevent GC
} else {
//prevent GC in C++ & JS
objFunc->root();
}
se::ScriptEngine::getInstance()->setJSExceptionCallback([objFunc](const char *location, const char *message, const char *stack) {
se::AutoHandleScope scope;
se::ValueArray jsArgs;
jsArgs.resize(3);
jsArgs[0] = se::Value(location);
jsArgs[1] = se::Value(message);
jsArgs[2] = se::Value(stack);
objFunc->call(jsArgs, nullptr);
});
se::ScriptEngine::getInstance()->addBeforeCleanupHook([objFunc] {
objFunc->decRef();
});
return true;
}
SE_BIND_FUNC(js_se_setExceptionCallback) // NOLINT(readability-identifier-naming)
static bool register_filetuils_ext(se::Object * /*obj*/) { // NOLINT(readability-identifier-naming)
__jsb_cc_FileUtils_proto->defineFunction("listFilesRecursively", _SE(js_engine_FileUtils_listFilesRecursively));
return true;
}
static bool register_se_setExceptionCallback(se::Object *obj) { // NOLINT(readability-identifier-naming)
se::Value jsb;
if (!obj->getProperty("jsb", &jsb)) {
jsb.setObject(se::Object::createPlainObject());
obj->setProperty("jsb", jsb);
}
auto *jsbObj = jsb.toObject();
jsbObj->defineFunction("onError", _SE(js_se_setExceptionCallback));
return true;
}
static bool js_engine_Color_get_val(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::Color>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
CC_UNUSED bool ok = true;
se::Value jsret;
auto r = static_cast<uint32_t>(cobj->r);
auto g = static_cast<uint32_t>(cobj->g);
auto b = static_cast<uint32_t>(cobj->b);
auto a = static_cast<uint32_t>(cobj->a);
uint32_t val = (a << 24) + (b << 16) + (g << 8) + r;
ok &= nativevalue_to_se(val, jsret, s.thisObject() /*ctx*/);
s.rval() = jsret;
return true;
}
SE_BIND_PROP_GET(js_engine_Color_get_val)
static bool js_engine_Color_set_val(se::State &s) // NOLINT(readability-identifier-naming)
{
const auto &args = s.args();
auto *cobj = SE_THIS_OBJECT<cc::Color>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
CC_UNUSED bool ok = true;
uint32_t val{0};
ok &= sevalue_to_native(args[0], &val, s.thisObject());
cobj->r = val & 0x000000FF;
cobj->g = (val & 0x0000FF00) >> 8;
cobj->b = (val & 0x00FF0000) >> 16;
cobj->a = (val & 0xFF000000) >> 24;
SE_PRECONDITION2(ok, false, "Error processing new value");
return true;
}
SE_BIND_PROP_SET(js_engine_Color_set_val)
static bool register_engine_Color_manual(se::Object * /*obj*/) { // NOLINT(readability-identifier-naming)
__jsb_cc_Color_proto->defineProperty("_val", _SE(js_engine_Color_get_val), _SE(js_engine_Color_set_val));
se::ScriptEngine::getInstance()->clearException();
return true;
}
static bool js_cc_ISystemWindowManager_getInstance_static(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
CC_UNUSED bool ok = true;
auto *instance = CC_GET_PLATFORM_INTERFACE(cc::ISystemWindowManager);
ok &= nativevalue_to_se(instance, s.rval(), s.thisObject());
SE_PRECONDITION2(ok, false, "js_cc_ISystemWindowManager_getInstance Failed");
return true;
}
SE_BIND_FUNC(js_cc_ISystemWindowManager_getInstance_static)
static bool register_platform(se::Object * /*obj*/) { // NOLINT(readability-identifier-naming)
se::Value constructor;
bool result = __jsb_cc_ISystemWindowManager_proto->getProperty("constructor", &constructor);
result &= constructor.toObject()->defineFunction("getInstance", _SE(js_cc_ISystemWindowManager_getInstance_static));
return result;
}
template <typename T>
static bool bindAsExternalBuffer(se::State &s) { // NOLINT
auto *self = SE_THIS_OBJECT<T>(s);
if (!self) {
return false;
}
// NOLINTNEXTLINE
se::HandleObject buffer(se::Object::createExternalArrayBufferObject(self, sizeof(*self), [](void *, size_t, void *) {}));
s.rval().setObject(buffer);
return true;
}
static bool js_cc_Vec2_underlyingData(se::State &s) { // NOLINT
return bindAsExternalBuffer<cc::Vec2>(s);
}
SE_BIND_FUNC(js_cc_Vec2_underlyingData)
static bool js_cc_Vec3_underlyingData(se::State &s) { // NOLINT
return bindAsExternalBuffer<cc::Vec3>(s);
}
SE_BIND_FUNC(js_cc_Vec3_underlyingData)
static bool js_cc_Vec4_underlyingData(se::State &s) { // NOLINT
return bindAsExternalBuffer<cc::Vec4>(s);
}
SE_BIND_FUNC(js_cc_Vec4_underlyingData)
static bool js_cc_Mat3_underlyingData(se::State &s) { // NOLINT
return bindAsExternalBuffer<cc::Mat3>(s);
}
SE_BIND_FUNC(js_cc_Mat3_underlyingData)
static bool js_cc_Mat4_underlyingData(se::State &s) { // NOLINT
return bindAsExternalBuffer<cc::Mat4>(s);
}
SE_BIND_FUNC(js_cc_Mat4_underlyingData)
static bool js_cc_Quaternion_underlyingData(se::State &s) { // NOLINT
return bindAsExternalBuffer<cc::Quaternion>(s);
}
SE_BIND_FUNC(js_cc_Quaternion_underlyingData)
bool register_all_cocos_manual(se::Object *obj) { // NOLINT(readability-identifier-naming)
__jsb_cc_Vec2_proto->defineFunction("underlyingData", _SE(js_cc_Vec2_underlyingData));
__jsb_cc_Vec3_proto->defineFunction("underlyingData", _SE(js_cc_Vec3_underlyingData));
__jsb_cc_Vec4_proto->defineFunction("underlyingData", _SE(js_cc_Vec4_underlyingData));
__jsb_cc_Mat3_proto->defineFunction("underlyingData", _SE(js_cc_Mat3_underlyingData));
__jsb_cc_Mat4_proto->defineFunction("underlyingData", _SE(js_cc_Mat4_underlyingData));
__jsb_cc_Quaternion_proto->defineFunction("underlyingData", _SE(js_cc_Quaternion_underlyingData));
register_plist_parser(obj);
register_sys_localStorage(obj);
register_device(obj);
register_canvas_context2d(obj);
register_filetuils_ext(obj);
register_engine_Color_manual(obj);
register_se_setExceptionCallback(obj);
register_platform(obj);
return true;
}

View File

@@ -0,0 +1,31 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
#pragma once
namespace se {
class Object;
}
bool register_all_cocos_manual(se::Object *obj);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,106 @@
/****************************************************************************
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 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.
****************************************************************************/
// deprecated conversion functions
// native value -> se value
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool int8_to_seval(int8_t v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool uint8_to_seval(uint8_t v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool int32_to_seval(int32_t v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool uint32_to_seval(uint32_t v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool int16_to_seval(uint16_t v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool uint16_to_seval(uint16_t v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool boolean_to_seval(bool v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool float_to_seval(float v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool double_to_seval(double v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool long_to_seval(long v, se::Value *ret) { // NOLINT(readability-identifier-naming, google-runtime-int)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool ulong_to_seval(unsigned long v, se::Value *ret) { // NOLINT(readability-identifier-naming, google-runtime-int)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool longlong_to_seval(long long v, se::Value *ret) { // NOLINT(readability-identifier-naming, google-runtime-int)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool uintptr_t_to_seval(uintptr_t v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool size_to_seval(size_t v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool std_string_to_seval(const std::string &v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool std_vector_string_to_seval(const std::vector<std::string> &v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool std_vector_int_to_seval(const std::vector<int> &v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool std_vector_uint16_to_seval(const std::vector<uint16_t> &v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool std_vector_float_to_seval(const std::vector<float> &v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}
CC_DEPRECATED(3.6, "use nativevalue_to_se instead")
inline bool std_map_string_string_to_seval(const std::map<std::string, std::string> &v, se::Value *ret) { // NOLINT(readability-identifier-naming)
return nativevalue_to_se(v, *ret, nullptr);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,638 @@
/****************************************************************************
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 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.
****************************************************************************/
#pragma once
#include "base/Ptr.h"
#include "base/Value.h"
#include "base/std/any.h"
#include "base/std/container/unordered_map.h"
#include "base/std/optional.h"
#include "base/std/variant.h"
#include "bindings/jswrapper/SeApi.h"
#include "core/TypedArray.h"
#include "core/assets/AssetsModuleHeader.h"
#include "core/assets/RenderingSubMesh.h"
#if CC_USE_PHYSICS_PHYSX
#include "physics/spec/IShape.h"
#include "physics/spec/IWorld.h"
#endif
namespace cc {
class Data;
class Vec4;
class Vec2;
class Vec3;
class Size;
class Mat3;
class Mat4;
class Quaternion;
class Color;
class Rect;
template <typename K, typename V>
class RefMap;
struct NativeDep;
class ArrayBuffer;
// class TypedArray;
// class IBArray;
namespace network {
struct DownloaderHints;
class DownloadTask;
} // namespace network
namespace scene {
class FogInfo;
class ShadowsInfo;
class SkyboxInfo;
} // namespace scene
namespace geometry {
class AABB;
class Capsule;
class Line;
class Ray;
class Sphere;
class Triangle;
class Plane;
class Frustum;
class Spline;
} // namespace geometry
namespace extension {
struct ManifestAsset;
}
namespace middleware {
class Texture2D;
}
namespace gfx {
struct Viewport;
struct Offset;
struct Extent;
struct TextureSubres;
struct TextureCopy;
struct BufferTextureCopy;
struct BufferInfo;
struct BufferViewInfo;
struct TextureInfo;
struct DescriptorSetInfo;
struct BindingMappingInfo;
struct ShaderStage;
struct UniformSampler;
struct UniformBlock;
struct Uniform;
struct ShaderInfo;
struct DrawInfo;
struct IndirectBuffer;
struct SamplerInfo;
struct ColorAttachment;
struct DepthStencilAttachment;
struct SubPassInfo;
struct RenderPassInfo;
struct QueueInfo;
struct PipelineLayoutInfo;
struct DescriptorSetLayoutBinding;
struct DescriptorSetLayoutInfo;
struct FramebufferInfo;
struct CommandBufferInfo;
struct InputAssemblerInfo;
} // namespace gfx
} // namespace cc
#if CC_USE_SPINE
namespace spine {
class String;
template <typename T>
class Vector;
template <typename K, typename V>
class Map;
class Vector2;
} // namespace spine
#endif
////////////////////////////////////////////////////////////////////////////
/////////////////sevalue to native/////////////////////////////
////////////////////////////////////////////////////////////////////////////
// se value -> native value
CC_DEPRECATED(3.6, "use sevalue_to_native instead")
bool seval_to_ccvalue(const se::Value &v, cc::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use sevalue_to_native instead")
bool seval_to_ccvaluemap(const se::Value &v, cc::ValueMap *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use sevalue_to_native instead")
bool seval_to_ccvaluemapintkey(const se::Value &v, cc::ValueMapIntKey *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use sevalue_to_native instead")
bool seval_to_ccvaluevector(const se::Value &v, cc::ValueVector *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use sevalue_to_native instead")
bool sevals_variadic_to_ccvaluevector(const se::ValueArray &args, cc::ValueVector *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use sevalue_to_native instead")
bool seval_to_Data(const se::Value &v, cc::Data *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use sevalue_to_native instead")
bool seval_to_DownloaderHints(const se::Value &v, cc::network::DownloaderHints *ret); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::MacroValue *to, se::Object *ctx); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::IPreCompileInfoValueType *to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::IPropertyEditorValueType *to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
// ccstd::any
bool sevalue_to_native(const se::Value &from, ccstd::any *to, se::Object *ctx); // NOLINT(readability-identifier-naming)
////////////////// ArrayBuffer
bool sevalue_to_native(const se::Value &from, cc::ArrayBuffer *to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::ArrayBuffer **to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, ccstd::vector<cc::MacroRecord> *to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::MaterialProperty *to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
inline bool sevalue_to_native(const se::Value &from, ccstd::string *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
if (from.isString()) {
*to = from.toString();
return true;
}
if (from.isNumber()) {
*to = from.toStringForce();
return true;
}
if (from.isNullOrUndefined()) {
to->clear();
return true;
}
CC_ABORTF("parmater '%s' is not a string nor number", from.toStringForce().c_str());
to->clear();
return false;
}
inline bool seval_to_std_string(const se::Value &from, ccstd::string *ret) { // NOLINT(readability-identifier-naming)
assert(ret);
*ret = from.toStringForce();
return true;
}
inline bool sevalue_to_native(const se::Value &from, std::string_view *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
if (from.isString()) {
*to = from.toString();
}
return true;
}
///// integers
inline bool sevalue_to_native(const se::Value &from, bool *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
*to = from.isNullOrUndefined() ? false : (from.isNumber() ? from.toDouble() != 0 : from.toBoolean());
return true;
}
inline bool sevalue_to_native(const se::Value &from, int32_t *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
*to = from.toInt32();
return true;
}
inline bool sevalue_to_native(const se::Value &from, uint32_t *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
*to = from.toUint32();
return true;
}
inline bool sevalue_to_native(const se::Value &from, int16_t *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
*to = from.toInt16();
return true;
}
inline bool sevalue_to_native(const se::Value &from, uint16_t *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
*to = from.toUint16();
return true;
}
inline bool sevalue_to_native(const se::Value &from, int8_t *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
*to = from.toInt8();
return true;
}
inline bool sevalue_to_native(const se::Value &from, uint8_t *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
*to = from.toUint8();
return true;
}
inline bool sevalue_to_native(const se::Value &from, uint64_t *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
*to = from.toUint64();
return true;
}
inline bool sevalue_to_native(const se::Value &from, int64_t *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
*to = from.toInt64();
return true;
}
#if CC_PLATFORM == CC_PLATFORM_IOS || CC_PLATFORM == CC_PLATFORM_MACOS
inline bool sevalue_to_native(const se::Value &from, unsigned long *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
// on mac: unsiged long === uintptr_t
static_assert(sizeof(*to) == 8, "");
*to = static_cast<unsigned long>(from.toUint64());
return true;
}
inline bool sevalue_to_native(const se::Value &from, long *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
// on mac: unsiged long === uintptr_t
static_assert(sizeof(*to) == 8, "");
*to = static_cast<long>(from.toUint64());
return true;
}
#endif
inline bool sevalue_to_native(const se::Value &from, float *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
*to = from.toFloat();
return true;
}
inline bool sevalue_to_native(const se::Value &from, double *to, se::Object * /*unused*/) { // NOLINT(readability-identifier-naming)
*to = from.toDouble();
return true;
}
// inline bool sevalue_to_native(const se::Value & /*from*/, void * /*to*/, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
// CC_ABORT(); // void not supported
// return false;
// }
bool sevalue_to_native(const se::Value &from, cc::Data *to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::Value *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
inline bool sevalue_to_native(const se::Value &from, se::Value *to, se::Object * /*unused*/) { // NOLINT(readability-identifier-naming)
*to = from;
return true;
}
inline bool sevalue_to_native(const se::Value &from, se::Object **to, se::Object * /*unused*/) { // NOLINT(readability-identifier-naming)
*to = from.toObject();
return true;
}
inline bool sevalue_to_native(const se::Value &from, const se::Object **to, se::Object * /*unused*/) { // NOLINT(readability-identifier-naming)
*to = from.toObject();
return true;
}
bool sevalue_to_native(const se::Value &from, cc::Vec4 *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::Mat3 *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::Mat4 *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::Vec3 *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::Vec2 *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::Size *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::Quaternion *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::Color *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::Rect *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::gfx::Rect *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
inline bool sevalue_to_native(const se::Value &from, ccstd::vector<se::Value> *to, se::Object * /*unused*/) { // NOLINT(readability-identifier-naming)
if (from.isNullOrUndefined()) {
to->clear();
return true;
}
CC_ASSERT(from.isObject() && from.toObject()->isArray());
auto *array = from.toObject();
to->clear();
uint32_t size;
array->getArrayLength(&size);
for (uint32_t i = 0; i < size; i++) {
se::Value ele;
array->getArrayElement(i, &ele);
to->emplace_back(ele);
}
return true;
}
////////////////// ccstd::any
inline bool sevalue_to_native(const se::Value & /*from*/, ccstd::any * /*to*/, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
CC_ABORT();
SE_LOGE("Can not convert any to specific types");
return false;
}
bool sevalue_to_native(const se::Value &from, cc::TypedArray *to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::IBArray *to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
// bool sevalue_to_native(const se::Value &from, cc::gfx::Context **to, se::Object*) {// NOLINT(readability-identifier-naming)
// CC_ASSERT(from.isObject());
// *to = (cc::gfx::Context*)from.toObject()->getPrivateData();
// return true;
// }
inline bool sevalue_to_native(const se::Value &from, void **to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
CC_ASSERT_NOT_NULL(to);
if (from.isNumber() || from.isBigInt()) {
// NOLINTNEXTLINE(performance-no-int-to-ptr)
*to = reinterpret_cast<void *>(from.toUint64());
return true;
}
if (from.isObject()) {
*to = from.toObject()->getPrivateData();
return true;
}
SE_LOGE("[warn] failed to convert to void *\n");
return false;
}
inline bool sevalue_to_native(const se::Value &from, ccstd::string **to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
if (to != nullptr && *to != nullptr) {
**to = from.toString();
}
return true;
}
bool sevalue_to_native(const se::Value &from, cc::ValueMap *to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, ccstd::vector<bool> *to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, ccstd::variant<ccstd::string, bool> *to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, ccstd::vector<unsigned char> *to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::IPropertyValue *to, se::Object *ctx); // NOLINT(readability-identifier-naming)
inline bool sevalue_to_native(const se::Value & /*from*/, ccstd::monostate * /*to*/, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
// nothing todo
return false;
}
//////////////////////// scene info
bool sevalue_to_native(const se::Value &from, cc::scene::FogInfo *, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::scene::ShadowsInfo *, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::scene::SkyboxInfo *, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
/////////////////////// geometry
bool sevalue_to_native(const se::Value &from, cc::geometry::AABB *, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::geometry::Capsule *, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::geometry::Line *, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::geometry::Ray *, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::geometry::Sphere *, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::geometry::Triangle *, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::geometry::Plane *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::geometry::Plane **to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::geometry::Frustum *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, cc::geometry::Spline *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
////////////////////////////////////////////////////////////////////////////
////////////////////nativevalue to se /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// native value -> se value
CC_DEPRECATED(3.6, "use native_to_se instead")
bool ccvalue_to_seval(const cc::Value &v, se::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use native_to_se instead")
bool ccvaluemap_to_seval(const cc::ValueMap &v, se::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use native_to_se instead")
bool ccvaluemapintkey_to_seval(const cc::ValueMapIntKey &v, se::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use native_to_se instead")
bool ccvaluevector_to_seval(const cc::ValueVector &v, se::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use native_to_se instead")
bool ManifestAsset_to_seval(const cc::extension::ManifestAsset &v, se::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use native_to_se instead")
bool Data_to_seval(const cc::Data &v, se::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use native_to_se instead")
bool DownloadTask_to_seval(const cc::network::DownloadTask &v, se::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use native_to_se instead")
bool Vec2_to_seval(const cc::Vec2 &v, se::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use native_to_se instead")
bool Vec3_to_seval(const cc::Vec3 &v, se::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use native_to_se instead")
bool Vec4_to_seval(const cc::Vec4 &v, se::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use native_to_se instead")
bool Mat4_to_seval(const cc::Mat4 &v, se::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use native_to_se instead")
bool Size_to_seval(const cc::Size &v, se::Value *ret); // NOLINT(readability-identifier-naming)
CC_DEPRECATED(3.6, "use native_to_se instead")
bool Rect_to_seval(const cc::Rect &v, se::Value *ret); // NOLINT(readability-identifier-naming)
// bool nativevalue_to_se(const cc::TypedArray &typedArray, se::Value &to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming) // NOLINT
/**
* WARN: call nativevalue_to_se instead and it converts cc::Data to ArrayBuffer
*/
bool Data_to_TypedArray(const cc::Data &v, se::Value *ret); // NOLINT(readability-identifier-naming)
bool nativevalue_to_se(const cc::ArrayBuffer &arrayBuffer, se::Value &to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming) // NOLINT
inline bool nativevalue_to_se(cc::ArrayBuffer *arrayBuffer, se::Value &to, se::Object *ctx) { // NOLINT(readability-identifier-naming) // NOLINT
if (arrayBuffer == nullptr) {
return false;
}
return nativevalue_to_se(*arrayBuffer, to, ctx);
}
inline bool nativevalue_to_se(const ccstd::vector<int8_t> &from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
se::HandleObject array{se::Object::createTypedArray(se::Object::TypedArrayType::INT8, from.data(), from.size())};
to.setObject(array);
return true;
}
inline bool nativevalue_to_se(const ccstd::vector<uint8_t> &from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
se::HandleObject array{se::Object::createTypedArray(se::Object::TypedArrayType::UINT8, from.data(), from.size())};
to.setObject(array);
return true;
}
inline bool nativevalue_to_se(int64_t from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setInt64(from);
return true;
}
inline bool nativevalue_to_se(uint64_t from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setUint64(from);
return true;
}
inline bool nativevalue_to_se(int32_t from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setInt32(from);
return true;
}
inline bool nativevalue_to_se(uint32_t from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setUint32(from);
return true;
}
inline bool nativevalue_to_se(int16_t from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setInt16(from);
return true;
}
inline bool nativevalue_to_se(uint16_t from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setUint16(from);
return true;
}
inline bool nativevalue_to_se(int8_t from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setInt8(from);
return true;
}
inline bool nativevalue_to_se(uint8_t from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setUint8(from);
return true;
}
inline bool nativevalue_to_se(float from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setFloat(from);
return true;
}
inline bool nativevalue_to_se(double from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setDouble(from);
return true;
}
inline bool nativevalue_to_se(bool from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setBoolean(from);
return true;
}
#if CC_PLATFORM == CC_PLATFORM_IOS || CC_PLATFORM == CC_PLATFORM_MACOS
inline bool nativevalue_to_se(unsigned long from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
static_assert(sizeof(from) == 8, "");
to.setDouble(static_cast<double>(from));
return true;
}
inline bool nativevalue_to_se(long from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
static_assert(sizeof(from) == 8, "");
to.setDouble(static_cast<double>(from));
return true;
}
#endif
inline bool nativevalue_to_se(const ccstd::string &from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setString(from);
return true;
}
inline bool nativevalue_to_se(const std::string_view &from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setString(from);
return true;
}
inline bool nativevalue_to_se(const char *from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setString(from);
return true;
}
inline bool nativevalue_to_se(char *from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setString(from);
return true;
}
bool nativevalue_to_se(const cc::NativeDep &from, se::Value &to, se::Object *ctx); // NOLINT(readability-identifier-naming)
// JSB_REGISTER_OBJECT_TYPE(cc::network::DownloaderHints);
bool nativevalue_to_se(const cc::Data &from, se::Value &to, se::Object *ctx); // NOLINT(readability-identifier-naming)
bool nativevalue_to_se(const cc::Value &from, se::Value &to, se::Object *ctx); // NOLINT(readability-identifier-naming)
bool nativevalue_to_se(const ccstd::unordered_map<ccstd::string, cc::Value> &from, se::Value &to, se::Object *ctx); // NOLINT(readability-identifier-naming)
bool nativevalue_to_se(const cc::Size &from, se::Value &to, se::Object *ctx); // NOLINT(readability-identifier-naming)
bool nativevalue_to_se(const cc::extension::ManifestAsset &from, se::Value &to, se::Object *ctx); // NOLINT(readability-identifier-naming)
bool nativevalue_to_se(const cc::Rect &from, se::Value &to, se::Object *ctx); // NOLINT(readability-identifier-naming)
bool nativevalue_to_se(const cc::gfx::Rect &from, se::Value &to, se::Object *ctx); // NOLINT(readability-identifier-naming)
bool nativevalue_to_se(const cc::gfx::FormatInfo *from, se::Value &to, se::Object *ctx); // NOLINT(readability-identifier-naming
bool nativevalue_to_se(const cc::network::DownloadTask &from, se::Value &to, se::Object * /*ctx*/); // NOLINT(readability-identifier-naming)
inline bool nativevalue_to_se(const ccstd::monostate & /*from*/, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setUndefined();
return true;
}
inline bool nativevalue_to_se(const ccstd::any &from, se::Value &to, se::Object *ctx) { // NOLINT
CC_ABORT();
SE_LOGE("should not convert ccstd::any");
return true;
}
using void_p = void *;
inline bool nativevalue_to_se(const void_p &from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
if (!from) {
to.setUndefined();
} else {
auto ptr = reinterpret_cast<uintptr_t>(from);
sizeof(from) == 8 ? to.setUint64(static_cast<uint64_t>(ptr)) : to.setUint32(static_cast<uint32_t>(ptr));
}
return true;
}
// Spine conversions
#if CC_USE_SPINE
bool sevalue_to_native(const se::Value &, spine::String *, se::Object *); // NOLINT(readability-identifier-naming)
bool nativevalue_to_se(const spine::Vector<spine::String> &v, se::Value &ret, se::Object *ctx); // NOLINT(readability-identifier-naming)
bool nativevalue_to_se(const spine::String &obj, se::Value &val, se::Object *ctx); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &v, spine::Vector<spine::String> *ret, se::Object *ctx); // NOLINT(readability-identifier-naming)
bool sevalue_to_native(const se::Value &from, spine::Vector2 *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
bool nativevalue_to_se(const spine::Vector2 &from, se::Value &to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming)
#endif
inline bool nativevalue_to_se(const se::Object *from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setObject(const_cast<se::Object *>(from));
return true;
}
inline bool nativevalue_to_se(se::Object *from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
to.setObject(from);
return true;
}
#if CC_USE_MIDDLEWARE
bool seval_to_Map_string_key(const se::Value &v, cc::RefMap<ccstd::string, cc::middleware::Texture2D *> *ret); // NOLINT(readability-identifier-naming)
#endif // CC_USE_MIDDLEWARE
#if CC_USE_PHYSICS_PHYSX
bool nativevalue_to_se(const ccstd::vector<std::shared_ptr<cc::physics::TriggerEventPair>> &from, se::Value &to, se::Object * /*ctx*/);
bool nativevalue_to_se(const ccstd::vector<cc::physics::ContactPoint> &from, se::Value &to, se::Object * /*ctx*/);
bool nativevalue_to_se(const ccstd::vector<std::shared_ptr<cc::physics::ContactEventPair>> &from, se::Value &to, se::Object *ctx);
bool nativevalue_to_se(const cc::physics::RaycastResult &from, se::Value &to, se::Object *ctx);
bool nativevalue_to_se(const ccstd::vector<std::shared_ptr<cc::physics::CCTShapeEventPair>> &from, se::Value &to, se::Object *ctx);
bool nativevalue_to_se(const ccstd::vector<std::shared_ptr<cc::physics::CCTTriggerEventPair>> &from, se::Value &to, se::Object * /*ctx*/);
bool sevalue_to_native(const se::Value &from, cc::physics::ConvexDesc *to, se::Object *ctx);
bool sevalue_to_native(const se::Value &from, cc::physics::TrimeshDesc *to, se::Object *ctx);
bool sevalue_to_native(const se::Value &from, cc::physics::HeightFieldDesc *to, se::Object *ctx);
bool sevalue_to_native(const se::Value &from, cc::physics::RaycastOptions *to, se::Object *ctx);
#endif // USE_PHYSICS_PHYSX

View File

@@ -0,0 +1,486 @@
/****************************************************************************
Copyright (c) 2017-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 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 "jsb_dragonbones_manual.h"
#include "cocos/bindings/auto/jsb_dragonbones_auto.h"
#include "cocos/bindings/auto/jsb_editor_support_auto.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "cocos/bindings/manual/jsb_helper.h"
#include "cocos/editor-support/dragonbones-creator-support/CCDragonBonesHeaders.h"
using namespace cc;
// add by fins
static bool js_cocos2dx_dragonbones_Slot_get_globalTransformMatrix(se::State &s) {
dragonBones::Slot *cobj = (dragonBones::Slot *)s.nativeThisObject();
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 0) {
dragonBones::Matrix *result = cobj->getGlobalTransformMatrix();
ok &= native_ptr_to_seval<dragonBones::Matrix>((dragonBones::Matrix *)result, &s.rval());
SE_PRECONDITION2(ok, false, "Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 0);
return false;
}
SE_BIND_PROP_GET(js_cocos2dx_dragonbones_Slot_get_globalTransformMatrix)
// add by fins
static bool js_cocos2dx_dragonbones_Animation_get_animations(se::State &s) {
dragonBones::Animation *cobj = (dragonBones::Animation *)s.nativeThisObject();
se::HandleObject retObj(se::Object::createPlainObject());
bool ok = false;
se::Value tmp;
for (const auto &e : cobj->getAnimations()) {
if (!e.first.empty()) {
ok = native_ptr_to_seval<dragonBones::AnimationData>(e.second, __jsb_dragonBones_AnimationData_class, &tmp);
SE_PRECONDITION2(ok, false, "Convert dragonBones::AnimationData to se::Value failed!");
retObj->setProperty(e.first.c_str(), tmp);
}
}
s.rval().setObject(retObj);
return true;
}
SE_BIND_PROP_GET(js_cocos2dx_dragonbones_Animation_get_animations)
static bool js_cocos2dx_dragonbones_Armature_getDisplay(se::State &s) {
if (s.args().size() == 0) {
dragonBones::Armature *cobj = (dragonBones::Armature *)s.nativeThisObject();
dragonBones::CCArmatureDisplay *ret = (dragonBones::CCArmatureDisplay *)(cobj->getDisplay());
if (ret != nullptr) {
bool ok = native_ptr_to_seval<dragonBones::CCArmatureDisplay>(ret, __jsb_dragonBones_CCArmatureDisplay_class, &s.rval());
SE_PRECONDITION2(ok, false, "Convert dragonBones::Animation to se::Value failed!");
} else {
s.rval().setNull();
}
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)s.args().size(), 0);
return false;
}
SE_BIND_FUNC(js_cocos2dx_dragonbones_Armature_getDisplay)
static bool js_cocos2dx_dragonbones_Armature_getSlots(se::State &s) {
dragonBones::Armature *cobj = (dragonBones::Armature *)s.nativeThisObject();
const auto &result = cobj->getSlots();
se::HandleObject arr(se::Object::createArrayObject(result.size()));
uint32_t i = 0;
se::Value tmp;
bool ok = true;
for (const auto &slot : result) {
if (!native_ptr_to_seval<dragonBones::Slot>(slot, &tmp)) {
ok = false;
break;
}
arr->setArrayElement(i, tmp);
++i;
}
if (ok)
s.rval().setObject(arr);
SE_PRECONDITION2(ok, false, "Convert getSlots to se::Value failed!");
return true;
}
SE_BIND_FUNC(js_cocos2dx_dragonbones_Armature_getSlots)
static bool js_cocos2dx_dragonbones_Armature_getBones(se::State &s) {
dragonBones::Armature *cobj = (dragonBones::Armature *)s.nativeThisObject();
const auto &result = cobj->getBones();
se::HandleObject arr(se::Object::createArrayObject(result.size()));
uint32_t i = 0;
se::Value tmp;
bool ok = true;
for (const auto &bone : result) {
if (!native_ptr_to_seval<dragonBones::Bone>(bone, &tmp)) {
ok = false;
break;
}
arr->setArrayElement(i, tmp);
++i;
}
if (ok)
s.rval().setObject(arr);
SE_PRECONDITION2(ok, false, "Convert getBones to se::Value failed!");
return true;
}
SE_BIND_FUNC(js_cocos2dx_dragonbones_Armature_getBones)
static bool js_cocos2dx_dragonbones_Armature_getBoneByDisplay(se::State &s) {
dragonBones::Armature *cobj = (dragonBones::Armature *)s.nativeThisObject();
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
dragonBones::CCArmatureDisplay *display = nullptr;
ok = seval_to_native_ptr(args[0], &display);
SE_PRECONDITION2(ok, false, "Error processing arguments");
dragonBones::Bone *result = cobj->getBoneByDisplay(display);
ok &= native_ptr_to_seval<dragonBones::Bone>((dragonBones::Bone *)result, &s.rval());
SE_PRECONDITION2(ok, false, "Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_cocos2dx_dragonbones_Armature_getBoneByDisplay)
static bool js_cocos2dx_dragonbones_Armature_getSlotByDisplay(se::State &s) {
dragonBones::Armature *cobj = (dragonBones::Armature *)s.nativeThisObject();
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
dragonBones::CCArmatureDisplay *display = nullptr;
ok = seval_to_native_ptr(args[0], &display);
SE_PRECONDITION2(ok, false, "Error processing arguments");
dragonBones::Slot *result = cobj->getSlotByDisplay(display);
ok &= native_ptr_to_seval<dragonBones::Slot>((dragonBones::Slot *)result, &s.rval());
SE_PRECONDITION2(ok, false, "Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_cocos2dx_dragonbones_Armature_getSlotByDisplay)
static bool js_cocos2dx_dragonbones_Armature_setReplacedTexture(se::State &s) {
dragonBones::Armature *cobj = (dragonBones::Armature *)s.nativeThisObject();
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
middleware::Texture2D *texture = nullptr;
ok = seval_to_native_ptr(args[0], &texture);
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->setReplacedTexture(texture);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_cocos2dx_dragonbones_Armature_setReplacedTexture)
static bool js_cocos2dx_dragonbones_Armature_getReplacedTexture(se::State &s) {
dragonBones::Armature *cobj = (dragonBones::Armature *)s.nativeThisObject();
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 0) {
middleware::Texture2D *result = (middleware::Texture2D *)cobj->getReplacedTexture();
ok = native_ptr_to_seval<middleware::Texture2D>(result, __jsb_cc_middleware_Texture2D_class, &s.rval());
SE_PRECONDITION2(ok, false, "Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 0);
return false;
}
SE_BIND_FUNC(js_cocos2dx_dragonbones_Armature_getReplacedTexture)
static bool js_cocos2dx_dragonbones_ArmatureData_get_animations(se::State &s) {
dragonBones::ArmatureData *cobj = (dragonBones::ArmatureData *)s.nativeThisObject();
se::HandleObject retObj(se::Object::createPlainObject());
bool ok = false;
se::Value tmp;
for (const auto &e : cobj->animations) {
if (!e.first.empty()) {
ok = native_ptr_to_seval<dragonBones::AnimationData>(e.second, __jsb_dragonBones_AnimationData_class, &tmp);
SE_PRECONDITION2(ok, false, "Convert dragonBones::AnimationData to se::Value failed!");
retObj->setProperty(e.first.c_str(), tmp);
}
}
s.rval().setObject(retObj);
return true;
}
SE_BIND_PROP_GET(js_cocos2dx_dragonbones_ArmatureData_get_animations)
static bool js_cocos2dx_dragonbones_ArmatureData_get_bones(se::State &s) {
dragonBones::ArmatureData *cobj = (dragonBones::ArmatureData *)s.nativeThisObject();
se::HandleObject retObj(se::Object::createPlainObject());
bool ok = false;
se::Value tmp;
for (const auto &e : cobj->bones) {
if (!e.first.empty()) {
ok = native_ptr_to_seval<dragonBones::BoneData>(e.second, __jsb_dragonBones_BoneData_class, &tmp);
SE_PRECONDITION2(ok, false, "Convert dragonBones::AnimationData to se::Value failed!");
retObj->setProperty(e.first.c_str(), tmp);
}
}
s.rval().setObject(retObj);
return true;
}
SE_BIND_PROP_GET(js_cocos2dx_dragonbones_ArmatureData_get_bones)
static bool js_cocos2dx_dragonbones_ArmatureData_get_skins(se::State &s) {
dragonBones::ArmatureData *cobj = (dragonBones::ArmatureData *)s.nativeThisObject();
se::HandleObject retObj(se::Object::createPlainObject());
bool ok = false;
se::Value tmp;
for (const auto &e : cobj->skins) {
if (!e.first.empty()) {
ok = native_ptr_to_seval<dragonBones::SkinData>(e.second, __jsb_dragonBones_SkinData_class, &tmp);
SE_PRECONDITION2(ok, false, "Convert dragonBones::AnimationData to se::Value failed!");
retObj->setProperty(e.first.c_str(), tmp);
}
}
s.rval().setObject(retObj);
return true;
}
SE_BIND_PROP_GET(js_cocos2dx_dragonbones_ArmatureData_get_skins)
static bool js_cocos2dx_dragonbones_ArmatureData_get_slots(se::State &s) {
dragonBones::ArmatureData *cobj = (dragonBones::ArmatureData *)s.nativeThisObject();
se::HandleObject retObj(se::Object::createPlainObject());
bool ok = false;
se::Value tmp;
for (const auto &e : cobj->slots) {
if (!e.first.empty()) {
ok = native_ptr_to_seval<dragonBones::SlotData>(e.second, __jsb_dragonBones_SlotData_class, &tmp);
SE_PRECONDITION2(ok, false, "Convert dragonBones::AnimationData to se::Value failed!");
retObj->setProperty(e.first.c_str(), tmp);
}
}
s.rval().setObject(retObj);
return true;
}
SE_BIND_PROP_GET(js_cocos2dx_dragonbones_ArmatureData_get_slots)
static bool js_cocos2dx_dragonbones_DragonBonesData_get_armatureNames(se::State &s) {
dragonBones::DragonBonesData *cobj = (dragonBones::DragonBonesData *)s.nativeThisObject();
const auto &ret = cobj->getArmatureNames();
bool ok = nativevalue_to_se(ret, s.rval());
SE_PRECONDITION2(ok, false, "Convert ArmatureNames to se::Value failed!");
return true;
}
SE_BIND_PROP_GET(js_cocos2dx_dragonbones_DragonBonesData_get_armatureNames)
static bool js_cocos2dx_dragonbones_Slot_getDisplay(se::State &s) {
dragonBones::Slot *cobj = (dragonBones::Slot *)s.nativeThisObject();
dragonBones::CCArmatureDisplay *ret = static_cast<dragonBones::CCArmatureDisplay *>(cobj->getDisplay());
bool ok = native_ptr_to_seval<dragonBones::CCArmatureDisplay>(ret, __jsb_dragonBones_CCArmatureDisplay_class, &s.rval());
SE_PRECONDITION2(ok, false, "Convert dragonBones::DBCCSprite to se::Value failed!");
return true;
}
SE_BIND_FUNC(js_cocos2dx_dragonbones_Slot_getDisplay)
static bool js_cocos2dx_dragonbones_Slot_set_displayIndex(se::State &s) {
const auto &args = s.args();
dragonBones::Slot *cobj = (dragonBones::Slot *)s.nativeThisObject();
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
CC_UNUSED bool ok = true;
int32_t arg0;
ok &= sevalue_to_native(args[0], &arg0);
SE_PRECONDITION2(ok, false, "Error processing new value");
cobj->setDisplayIndex(arg0);
return true;
}
SE_BIND_PROP_SET(js_cocos2dx_dragonbones_Slot_set_displayIndex)
static bool js_cocos2dx_dragonbones_Slot_get_displayIndex(se::State &s) {
dragonBones::Slot *cobj = (dragonBones::Slot *)s.nativeThisObject();
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const int32_t ret = cobj->getDisplayIndex();
bool ok = nativevalue_to_se(ret, s.rval());
SE_PRECONDITION2(ok, false, "js_cocos2dx_dragonbones_Slot_get_displayIndex to se::Value failed!");
return true;
}
SE_BIND_PROP_GET(js_cocos2dx_dragonbones_Slot_get_displayIndex)
static bool js_cocos2dx_dragonbones_Slot_setDisplay(se::State &s) {
const auto &args = s.args();
int argc = (int)args.size();
if (argc == 2) {
dragonBones::Slot *cobj = (dragonBones::Slot *)s.nativeThisObject();
dragonBones::CCArmatureDisplay *dbSprite = nullptr;
bool ok = seval_to_native_ptr(args[0], &dbSprite);
SE_PRECONDITION2(ok, false, "Convert se::Value to dragonBones::DBCCSprite failed!");
dragonBones::DisplayType type;
ok = sevalue_to_native(args[1], (int32_t *)&type);
SE_PRECONDITION2(ok, false, "Convert se::Value to dragonBones::DisplayType failed!");
cobj->setDisplay(dbSprite, type);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", argc, 2);
return false;
}
SE_BIND_FUNC(js_cocos2dx_dragonbones_Slot_setDisplay)
static bool js_cocos2dx_dragonbones_BaseFactory_parseTextureAtlasData(se::State &s) {
dragonBones::BaseFactory *cobj = (dragonBones::BaseFactory *)s.nativeThisObject();
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 2) {
const char *arg0 = nullptr;
void *arg1 = nullptr;
ccstd::string arg0_tmp;
ok &= sevalue_to_native(args[0], &arg0_tmp);
arg0 = arg0_tmp.c_str();
ok &= seval_to_native_ptr(args[1], &arg1);
SE_PRECONDITION2(ok, false, "Error processing arguments");
dragonBones::TextureAtlasData *result = cobj->parseTextureAtlasData(arg0, arg1);
ok &= native_ptr_to_seval<dragonBones::TextureAtlasData>((dragonBones::TextureAtlasData *)result, &s.rval());
SE_PRECONDITION2(ok, false, "Error processing arguments");
return true;
}
if (argc == 3) {
const char *arg0 = nullptr;
void *arg1 = nullptr;
ccstd::string arg2;
ccstd::string arg0_tmp;
ok &= sevalue_to_native(args[0], &arg0_tmp);
arg0 = arg0_tmp.c_str();
ok &= seval_to_native_ptr(args[1], &arg1);
SE_PRECONDITION2(ok, false, "Error processing arguments");
ok &= sevalue_to_native(args[2], &arg2);
SE_PRECONDITION2(ok, false, "Error processing arguments");
dragonBones::TextureAtlasData *result = cobj->parseTextureAtlasData(arg0, arg1, arg2);
ok &= native_ptr_to_seval<dragonBones::TextureAtlasData>((dragonBones::TextureAtlasData *)result, &s.rval());
SE_PRECONDITION2(ok, false, "Error processing arguments");
return true;
}
if (argc == 4) {
const char *arg0 = nullptr;
void *arg1 = nullptr;
ccstd::string arg2;
float arg3 = 0;
ccstd::string arg0_tmp;
ok &= sevalue_to_native(args[0], &arg0_tmp);
arg0 = arg0_tmp.c_str();
ok &= seval_to_native_ptr(args[1], &arg1);
SE_PRECONDITION2(ok, false, "Error processing arguments");
ok &= sevalue_to_native(args[2], &arg2);
ok &= sevalue_to_native(args[3], &arg3);
SE_PRECONDITION2(ok, false, "Error processing arguments");
dragonBones::TextureAtlasData *result = cobj->parseTextureAtlasData(arg0, arg1, arg2, arg3);
ok &= native_ptr_to_seval<dragonBones::TextureAtlasData>((dragonBones::TextureAtlasData *)result, &s.rval());
SE_PRECONDITION2(ok, false, "Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 4);
return false;
}
SE_BIND_FUNC(js_cocos2dx_dragonbones_BaseFactory_parseTextureAtlasData)
bool register_all_dragonbones_manual(se::Object *obj) {
// add by fins
__jsb_dragonBones_Slot_proto->defineProperty("globalTransformMatrix", _SE(js_cocos2dx_dragonbones_Slot_get_globalTransformMatrix), nullptr);
// add by fins
__jsb_dragonBones_Animation_proto->defineProperty("animations", _SE(js_cocos2dx_dragonbones_Animation_get_animations), nullptr);
__jsb_dragonBones_Armature_proto->defineFunction("getDisplay", _SE(js_cocos2dx_dragonbones_Armature_getDisplay));
__jsb_dragonBones_Armature_proto->defineFunction("getSlots", _SE(js_cocos2dx_dragonbones_Armature_getSlots));
__jsb_dragonBones_Armature_proto->defineFunction("getBones", _SE(js_cocos2dx_dragonbones_Armature_getBones));
__jsb_dragonBones_Armature_proto->defineFunction("getBoneByDisplay", _SE(js_cocos2dx_dragonbones_Armature_getBoneByDisplay));
__jsb_dragonBones_Armature_proto->defineFunction("getSlotByDisplay", _SE(js_cocos2dx_dragonbones_Armature_getSlotByDisplay));
__jsb_dragonBones_Armature_proto->defineFunction("setReplacedTexture", _SE(js_cocos2dx_dragonbones_Armature_setReplacedTexture));
__jsb_dragonBones_Armature_proto->defineFunction("getReplacedTexture", _SE(js_cocos2dx_dragonbones_Armature_getReplacedTexture));
__jsb_dragonBones_ArmatureData_proto->defineProperty("animations", _SE(js_cocos2dx_dragonbones_ArmatureData_get_animations), nullptr);
__jsb_dragonBones_ArmatureData_proto->defineProperty("bones", _SE(js_cocos2dx_dragonbones_ArmatureData_get_bones), nullptr);
__jsb_dragonBones_ArmatureData_proto->defineProperty("skins", _SE(js_cocos2dx_dragonbones_ArmatureData_get_skins), nullptr);
__jsb_dragonBones_ArmatureData_proto->defineProperty("slots", _SE(js_cocos2dx_dragonbones_ArmatureData_get_slots), nullptr);
__jsb_dragonBones_DragonBonesData_proto->defineProperty("armatureNames", _SE(js_cocos2dx_dragonbones_DragonBonesData_get_armatureNames), nullptr);
__jsb_dragonBones_Slot_proto->defineProperty("displayIndex", _SE(js_cocos2dx_dragonbones_Slot_get_displayIndex), _SE(js_cocos2dx_dragonbones_Slot_set_displayIndex));
__jsb_dragonBones_Slot_proto->defineFunction("getDisplay", _SE(js_cocos2dx_dragonbones_Slot_getDisplay));
__jsb_dragonBones_Slot_proto->defineFunction("setDisplay", _SE(js_cocos2dx_dragonbones_Slot_setDisplay));
__jsb_dragonBones_BaseFactory_proto->defineFunction("parseTextureAtlasData", _SE(js_cocos2dx_dragonbones_BaseFactory_parseTextureAtlasData));
dragonBones::BaseObject::setObjectRecycleOrDestroyCallback([](dragonBones::BaseObject *obj, int type) {
//ccstd::string typeName = typeid(*obj).name();
if (!se::NativePtrToObjectMap::isValid()) {
return;
}
se::NativePtrToObjectMap::forEach(obj, [](se::Object *seObj) {
seObj->setClearMappingInFinalizer(false);
// Unmap native and js object since native object was destroyed.
// Otherwise, it may trigger 'assertion' in se::Object::setPrivateData later
// since native obj is already released and the new native object may be assigned with
// the same address.
});
se::NativePtrToObjectMap::erase(obj);
});
se::ScriptEngine::getInstance()->addAfterCleanupHook([]() {
// If dragonBones has not init,then no need to cleanup.
if (!dragonBones::CCFactory::isInit()) {
return;
}
dragonBones::DragonBones::checkInPool = false;
auto factory = dragonBones::CCFactory::getFactory();
factory->stopSchedule();
// Copy the dragonbones object vector since vector element will be deleted in BaseObject destructor.
ccstd::vector<dragonBones::BaseObject *> allDragonBonesObjects = dragonBones::BaseObject::getAllObjects();
CC_LOG_INFO("Starting to cleanup dragonbones object, count: %d\n", (int)allDragonBonesObjects.size());
for (auto dbObj : allDragonBonesObjects) {
if (!dbObj->isInPool()) {
dbObj->returnToPool();
}
}
dragonBones::BaseObject::clearPool(0);
dragonBones::CCFactory::destroyFactory();
dragonBones::DragonBones::checkInPool = true;
// Don't need to use copy operator since we only print leak object below.
auto &refAllDragonBonesObjects = dragonBones::BaseObject::getAllObjects();
SE_LOGD("After cleanup, dragonbones object remained count: %d\n", (int)refAllDragonBonesObjects.size());
// Print leak objects
for (auto dbObj : refAllDragonBonesObjects) {
SE_LOGD("Leak dragonbones object: %s, %p\n", typeid(*dbObj).name(), dbObj);
}
refAllDragonBonesObjects.clear();
});
se::ScriptEngine::getInstance()->clearException();
return true;
}

View File

@@ -0,0 +1,31 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
#pragma once
namespace se {
class Object;
}
bool register_all_dragonbones_manual(se::Object *obj);

View File

@@ -0,0 +1,139 @@
/****************************************************************************
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 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 "jsb_geometry_manual.h"
#include "bindings/manual/jsb_global.h"
#include "cocos/bindings/auto/jsb_geometry_auto.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global_init.h"
template <typename T>
static bool bindAsExternalBuffer(se::State &s) { // NOLINT
auto *self = SE_THIS_OBJECT<T>(s);
if (!self) {
return false;
}
// NOLINTNEXTLINE
se::HandleObject buffer(se::Object::createExternalArrayBufferObject(self, sizeof(*self), [](void *, size_t, void *) {}));
s.rval().setObject(buffer);
return true;
}
#define REG_UNDERLINE_DATA(type) \
__jsb_cc_geometry_##type##_proto->defineFunction("underlyingData", _SE(js_cc_geometry_##type##_underlyingData))
#define DESC_OFFSET_OF(type, field) \
static_cast<int>(reinterpret_cast<uintptr_t>(&(static_cast<type *>(nullptr)->field)))
#define DESC_UNDERLINE_DATA_BEGIN(kls) \
{ \
using current_type = cc::geometry::kls; \
se::HandleObject info{se::Object::createPlainObject()};
#define DESC_UNDERLINE_DATA_FIELD(field) \
{ \
se::HandleObject fieldInfo{se::Object::createPlainObject()}; \
int fieldOffset = DESC_OFFSET_OF(current_type, field); \
constexpr int fieldSize = static_cast<int>(sizeof(std::declval<current_type>().field)); \
fieldInfo->setProperty("fieldName", se::Value(#field)); \
fieldInfo->setProperty("fieldOffset", se::Value(fieldOffset)); \
fieldInfo->setProperty("fieldSize", se::Value(fieldSize)); \
info->setProperty(#field, se::Value(fieldInfo)); \
}
#define DESC_UNDERLINE_DATA_END(kls) \
se::Value protoVal; \
__jsb_cc_geometry_##kls##_proto->getProperty("constructor", &protoVal); \
protoVal.toObject()->setProperty("__nativeFields__", se::Value(info)); \
} \
REG_UNDERLINE_DATA(kls);
#define IMPL_UNDERLINE_DATA(type) \
static bool js_cc_geometry_##type##_underlyingData(se::State &s) { \
return bindAsExternalBuffer<cc::geometry::type>(s); \
} \
SE_BIND_FUNC(js_cc_geometry_##type##_underlyingData)
IMPL_UNDERLINE_DATA(Line)
IMPL_UNDERLINE_DATA(Plane)
IMPL_UNDERLINE_DATA(Ray)
IMPL_UNDERLINE_DATA(Triangle)
IMPL_UNDERLINE_DATA(Sphere)
IMPL_UNDERLINE_DATA(AABB)
IMPL_UNDERLINE_DATA(Capsule)
IMPL_UNDERLINE_DATA(Frustum)
bool register_all_geometry_manual(se::Object * /*obj*/) { // NOLINT(readability-identifier-naming)
DESC_UNDERLINE_DATA_BEGIN(Line)
DESC_UNDERLINE_DATA_FIELD(s)
DESC_UNDERLINE_DATA_FIELD(e)
DESC_UNDERLINE_DATA_END(Line)
DESC_UNDERLINE_DATA_BEGIN(Plane)
DESC_UNDERLINE_DATA_FIELD(n)
DESC_UNDERLINE_DATA_FIELD(d)
DESC_UNDERLINE_DATA_END(Plane)
DESC_UNDERLINE_DATA_BEGIN(Ray)
DESC_UNDERLINE_DATA_FIELD(o)
DESC_UNDERLINE_DATA_FIELD(d)
DESC_UNDERLINE_DATA_END(Ray)
DESC_UNDERLINE_DATA_BEGIN(Triangle)
DESC_UNDERLINE_DATA_FIELD(a)
DESC_UNDERLINE_DATA_FIELD(b)
DESC_UNDERLINE_DATA_FIELD(c)
DESC_UNDERLINE_DATA_END(Triangle)
DESC_UNDERLINE_DATA_BEGIN(Sphere)
DESC_UNDERLINE_DATA_FIELD(_center)
DESC_UNDERLINE_DATA_FIELD(_radius)
DESC_UNDERLINE_DATA_END(Sphere)
DESC_UNDERLINE_DATA_BEGIN(AABB)
DESC_UNDERLINE_DATA_FIELD(center)
DESC_UNDERLINE_DATA_FIELD(halfExtents)
DESC_UNDERLINE_DATA_END(AABB)
DESC_UNDERLINE_DATA_BEGIN(Capsule)
DESC_UNDERLINE_DATA_FIELD(radius)
DESC_UNDERLINE_DATA_FIELD(halfHeight)
DESC_UNDERLINE_DATA_FIELD(axis)
DESC_UNDERLINE_DATA_FIELD(center)
DESC_UNDERLINE_DATA_FIELD(rotation)
DESC_UNDERLINE_DATA_FIELD(ellipseCenter0)
DESC_UNDERLINE_DATA_FIELD(ellipseCenter1)
DESC_UNDERLINE_DATA_END(Capsule)
// underlying data not required for Frustum
// DESC_UNDERLINE_DATA_BEGIN(Frustum)
// DESC_UNDERLINE_DATA_FIELD(vertices)
// DESC_UNDERLINE_DATA_FIELD(planes)
// DESC_UNDERLINE_DATA_END(Frustum)
return true;
}

View File

@@ -0,0 +1,31 @@
/****************************************************************************
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 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.
****************************************************************************/
#pragma once
namespace se {
class Object;
}
bool register_all_geometry_manual(se::Object *obj); // NOLINT

View File

@@ -0,0 +1,516 @@
/****************************************************************************
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 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 "jsb_gfx_manual.h"
#include "bindings/auto/jsb_gfx_auto.h"
#include "bindings/jswrapper/SeApi.h"
#include "bindings/manual/jsb_conversions.h"
#include "bindings/manual/jsb_global.h"
#include "core/data/JSBNativeDataHolder.h"
#include <fstream>
#include <sstream>
bool js_gfx_Device_copyBuffersToTexture(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::gfx::Device *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 3) {
cc::gfx::BufferDataList arg0;
cc::gfx::Texture *arg1 = nullptr;
cc::gfx::BufferTextureCopyList arg2;
if (args[0].isObject()) {
se::Object *dataObj = args[0].toObject();
SE_PRECONDITION2(dataObj->isArray(), false, "Buffers must be an array!");
uint32_t length = 0;
dataObj->getArrayLength(&length);
arg0.resize(length);
se::Value value;
for (uint32_t i = 0; i < length; ++i) {
if (dataObj->getArrayElement(i, &value)) {
uint8_t *ptr = nullptr;
CC_UNUSED size_t dataLength = 0;
if (value.isObject()) {
se::Object *obj = value.toObject();
if (obj->isArrayBuffer()) {
ok = obj->getArrayBufferData(&ptr, &dataLength);
SE_PRECONDITION2(ok, false, "getArrayBufferData failed!");
} else if (obj->isTypedArray()) {
ok = obj->getTypedArrayData(&ptr, &dataLength);
SE_PRECONDITION2(ok, false, "getTypedArrayData failed!");
} else {
CC_ABORT();
}
} else {
ptr = reinterpret_cast<uint8_t *>(value.asPtr()); // NOLINT(performance-no-int-to-ptr) script engine bad API design
}
arg0[i] = ptr;
}
}
}
ok &= seval_to_native_ptr(args[1], &arg1);
ok &= sevalue_to_native(args[2], &arg2, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->copyBuffersToTexture(arg0, arg1, arg2);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 3);
return false;
}
SE_BIND_FUNC(js_gfx_Device_copyBuffersToTexture)
bool js_gfx_Device_copyTextureToBuffers(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::gfx::Device *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 3) {
cc::gfx::Texture *arg0 = nullptr;
ccstd::vector<uint8_t *> arg1;
cc::gfx::BufferTextureCopyList arg2;
if (args[1].isObject()) {
se::Object *dataObj = args[1].toObject();
SE_PRECONDITION2(dataObj->isArray(), false, "Buffers must be an array!");
uint32_t length = 0;
dataObj->getArrayLength(&length);
arg1.resize(length);
se::Value value;
for (uint32_t i = 0; i < length; ++i) {
if (dataObj->getArrayElement(i, &value)) {
uint8_t *ptr = nullptr;
CC_UNUSED size_t dataLength = 0;
if (value.isObject()) {
se::Object *obj = value.toObject();
if (obj->isArrayBuffer()) {
ok = obj->getArrayBufferData(&ptr, &dataLength);
SE_PRECONDITION2(ok, false, "getArrayBufferData failed!");
} else if (obj->isTypedArray()) {
ok = obj->getTypedArrayData(&ptr, &dataLength);
SE_PRECONDITION2(ok, false, "getTypedArrayData failed!");
} else {
CC_ABORT();
}
} else {
ptr = reinterpret_cast<uint8_t *>(value.asPtr()); // NOLINT(performance-no-int-to-ptr) script engine bad API design
}
arg1[i] = ptr;
}
}
}
ok &= seval_to_native_ptr(args[0], &arg0);
ok &= sevalue_to_native(args[2], &arg2, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->copyTextureToBuffers(arg0, arg1.data(), arg2.data(), cc::utils::toUint(arg2.size()));
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 3);
return false;
}
SE_BIND_FUNC(js_gfx_Device_copyTextureToBuffers)
bool js_gfx_Device_copyTexImagesToTexture(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::gfx::Device *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 3) {
cc::gfx::BufferDataList arg0;
cc::gfx::Texture *arg1 = nullptr;
cc::gfx::BufferTextureCopyList arg2;
if (args[0].isObject()) {
se::Object *dataObj = args[0].toObject();
SE_PRECONDITION2(dataObj->isArray(), false, "Buffers must be an array!");
uint32_t length = 0;
dataObj->getArrayLength(&length);
arg0.resize(length);
se::Value value;
for (uint32_t i = 0; i < length; ++i) {
if (dataObj->getArrayElement(i, &value)) {
if (value.isObject()) {
CC_UNUSED size_t dataLength = 0;
uint8_t *buffer{nullptr};
if (value.toObject()->isTypedArray()) {
value.toObject()->getTypedArrayData(&buffer, &dataLength);
} else if (value.toObject()->isArrayBuffer()) {
value.toObject()->getArrayBufferData(&buffer, &dataLength);
} else {
auto *dataHolder = static_cast<cc::JSBNativeDataHolder *>(value.toObject()->getPrivateData());
CC_ASSERT_NOT_NULL(dataHolder);
buffer = dataHolder->getData();
}
arg0[i] = buffer;
} else {
CC_ABORT();
}
}
}
} else {
ok &= false;
}
ok &= seval_to_native_ptr(args[1], &arg1);
ok &= sevalue_to_native(args[2], &arg2, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->copyBuffersToTexture(arg0, arg1, arg2);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 3);
return false;
}
SE_BIND_FUNC(js_gfx_Device_copyTexImagesToTexture)
static bool js_gfx_Device_createBuffer(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::gfx::Device *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
if (argc == 2) {
cc::gfx::Buffer *buffer = nullptr;
bool createBufferView = false;
sevalue_to_native(args[1], &createBufferView);
if (createBufferView) {
cc::gfx::BufferViewInfo bufferViewInfo;
sevalue_to_native(args[0], &bufferViewInfo, s.thisObject());
buffer = cobj->createBuffer(bufferViewInfo);
} else {
cc::gfx::BufferInfo bufferInfo;
sevalue_to_native(args[0], &bufferInfo, s.thisObject());
buffer = cobj->createBuffer(bufferInfo);
}
CC_UNUSED bool ok = native_ptr_to_seval(buffer, &s.rval());
s.rval().toObject()->getPrivateObject()->tryAllowDestroyInGC();
SE_PRECONDITION2(ok, false, "Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d", (int)argc);
return false;
}
SE_BIND_FUNC(js_gfx_Device_createBuffer)
static bool js_gfx_Device_createTexture(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::gfx::Device *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
if (argc == 2) {
cc::gfx::Texture *texture = nullptr;
bool createTextureView = false;
sevalue_to_native(args[1], &createTextureView);
if (createTextureView) {
cc::gfx::TextureViewInfo textureViewInfo;
sevalue_to_native(args[0], &textureViewInfo, s.thisObject());
texture = cobj->createTexture(textureViewInfo);
} else {
cc::gfx::TextureInfo textureInfo;
sevalue_to_native(args[0], &textureInfo, s.thisObject());
texture = cobj->createTexture(textureInfo);
}
CC_UNUSED bool ok = native_ptr_to_seval(texture, &s.rval());
s.rval().toObject()->getPrivateObject()->tryAllowDestroyInGC();
SE_PRECONDITION2(ok, false, "Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d", (int)argc);
return false;
}
SE_BIND_FUNC(js_gfx_Device_createTexture)
static bool js_gfx_Buffer_initialize(se::State &s) { // NOLINT(readability-identifier-naming)
CC_UNUSED bool ok = true;
auto *cobj = static_cast<cc::gfx::Buffer *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
if (argc == 2) {
bool initWithBufferViewInfo = false;
sevalue_to_native(args[1], &initWithBufferViewInfo);
if (initWithBufferViewInfo) {
cc::gfx::BufferViewInfo bufferViewInfo;
sevalue_to_native(args[0], &bufferViewInfo, s.thisObject());
cobj->initialize(bufferViewInfo);
} else {
cc::gfx::BufferInfo bufferInfo;
sevalue_to_native(args[0], &bufferInfo, s.thisObject());
cobj->initialize(bufferInfo);
}
ok &= nativevalue_to_se(ok, s.rval());
SE_PRECONDITION2(ok, false, "Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d", (int)argc);
return false;
}
SE_BIND_FUNC(js_gfx_Buffer_initialize)
static bool js_gfx_Texture_initialize(se::State &s) { // NOLINT(readability-identifier-naming)
CC_UNUSED bool ok = true;
auto *cobj = static_cast<cc::gfx::Texture *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
if (argc == 2) {
bool initWithTextureViewInfo = false;
sevalue_to_native(args[1], &initWithTextureViewInfo);
if (initWithTextureViewInfo) {
cc::gfx::TextureViewInfo textureViewInfo;
sevalue_to_native(args[0], &textureViewInfo, s.thisObject());
cobj->initialize(textureViewInfo);
} else {
cc::gfx::TextureInfo textureInfo;
sevalue_to_native(args[0], &textureInfo, s.thisObject());
cobj->initialize(textureInfo);
}
ok &= nativevalue_to_se(ok, s.rval());
SE_PRECONDITION2(ok, false, "Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d", (int)argc);
return false;
}
SE_BIND_FUNC(js_gfx_Texture_initialize)
static bool js_gfx_GFXBuffer_update(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::gfx::Buffer *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
uint8_t *arg0 = nullptr;
CC_UNUSED size_t dataLength = 0;
se::Object *obj = args[0].toObject();
if (obj->isArrayBuffer()) {
ok = obj->getArrayBufferData(&arg0, &dataLength);
SE_PRECONDITION2(ok, false, "getArrayBufferData failed!");
} else if (obj->isTypedArray()) {
ok = obj->getTypedArrayData(&arg0, &dataLength);
SE_PRECONDITION2(ok, false, "getTypedArrayData failed!");
} else {
ok = false;
}
if (argc == 1) {
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->update(arg0, static_cast<uint32_t>(dataLength));
return true;
}
if (argc == 2) {
unsigned int arg1 = 0;
ok &= sevalue_to_native(args[1], &arg1);
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->update(arg0, arg1);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 3);
return false;
}
SE_BIND_FUNC(js_gfx_GFXBuffer_update)
static bool js_gfx_CommandBuffer_execute(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::gfx::CommandBuffer *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 2) {
cc::gfx::CommandBufferList cmdBufs;
unsigned int count = 0;
ok &= sevalue_to_native(args[1], &count);
se::Object *jsarr = args[0].toObject();
CC_ASSERT(jsarr->isArray());
uint32_t len = 0;
ok &= jsarr->getArrayLength(&len);
if (len < count) {
ok = false;
}
if (ok) {
cmdBufs.resize(count);
se::Value tmp;
for (uint32_t i = 0; i < count; ++i) {
ok = jsarr->getArrayElement(i, &tmp);
if (!ok || !tmp.isObject()) {
cmdBufs.clear();
break;
}
auto *cmdBuf = static_cast<cc::gfx::CommandBuffer *>(tmp.toObject()->getPrivateData());
cmdBufs[i] = cmdBuf;
}
}
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->execute(cmdBufs, count);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
return false;
}
SE_BIND_FUNC(js_gfx_CommandBuffer_execute)
static bool js_gfx_CommandBuffer_updateBuffer(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::gfx::CommandBuffer *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
cc::gfx::Buffer *arg0 = nullptr;
SE_PRECONDITION2(args[0].isObject(), false, "Invalid Native Object");
arg0 = static_cast<cc::gfx::Buffer *>(args[0].toObject()->getPrivateData());
uint8_t *arg1 = nullptr;
CC_UNUSED size_t dataLength = 0;
se::Object *obj = args[1].toObject();
if (obj->isArrayBuffer()) {
ok = obj->getArrayBufferData(&arg1, &dataLength);
SE_PRECONDITION2(ok, false, "getArrayBufferData failed!");
} else if (obj->isTypedArray()) {
ok = obj->getTypedArrayData(&arg1, &dataLength);
SE_PRECONDITION2(ok, false, "getTypedArrayData failed!");
} else {
ok = false;
}
if (argc == 2) {
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->updateBuffer(arg0, arg1, static_cast<uint32_t>(dataLength));
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 3);
return false;
}
SE_BIND_FUNC(js_gfx_CommandBuffer_updateBuffer)
static bool js_gfx_CommandBuffer_copyBuffersToTexture(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::gfx::CommandBuffer *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 3) {
cc::gfx::BufferDataList arg0;
cc::gfx::Texture *arg1 = nullptr;
cc::gfx::BufferTextureCopyList arg2;
if (args[0].isObject()) {
se::Object *dataObj = args[0].toObject();
SE_PRECONDITION2(dataObj->isArray(), false, "Buffers must be an array!");
uint32_t length = 0;
dataObj->getArrayLength(&length);
arg0.resize(length);
se::Value value;
for (uint32_t i = 0; i < length; ++i) {
if (dataObj->getArrayElement(i, &value)) {
uint8_t *ptr = nullptr;
CC_UNUSED size_t dataLength = 0;
se::Object *obj = value.toObject();
if (obj->isArrayBuffer()) {
ok = obj->getArrayBufferData(&ptr, &dataLength);
SE_PRECONDITION2(ok, false, "getArrayBufferData failed!");
} else if (obj->isTypedArray()) {
ok = obj->getTypedArrayData(&ptr, &dataLength);
SE_PRECONDITION2(ok, false, "getTypedArrayData failed!");
} else {
CC_ABORT();
}
arg0[i] = ptr;
}
}
}
ok &= seval_to_native_ptr(args[1], &arg1);
ok &= seval_to_std_vector(args[2], &arg2);
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->copyBuffersToTexture(arg0, arg1, arg2);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 3);
return false;
}
SE_BIND_FUNC(js_gfx_CommandBuffer_copyBuffersToTexture)
bool js_gfx_get_deviceInstance(se::State &s) { // NOLINT(readability-identifier-naming)
nativevalue_to_se(cc::gfx::Device::getInstance(), s.rval(), nullptr);
return true;
}
SE_BIND_PROP_GET(js_gfx_get_deviceInstance)
bool register_all_gfx_manual(se::Object *obj) {
__jsb_cc_gfx_Device_proto->defineFunction("copyBuffersToTexture", _SE(js_gfx_Device_copyBuffersToTexture));
__jsb_cc_gfx_Device_proto->defineFunction("copyTextureToBuffers", _SE(js_gfx_Device_copyTextureToBuffers));
__jsb_cc_gfx_Device_proto->defineFunction("copyTexImagesToTexture", _SE(js_gfx_Device_copyTexImagesToTexture));
__jsb_cc_gfx_Device_proto->defineFunction("createBuffer", _SE(js_gfx_Device_createBuffer));
__jsb_cc_gfx_Device_proto->defineFunction("createTexture", _SE(js_gfx_Device_createTexture));
__jsb_cc_gfx_Buffer_proto->defineFunction("update", _SE(js_gfx_GFXBuffer_update));
__jsb_cc_gfx_CommandBuffer_proto->defineFunction("execute", _SE(js_gfx_CommandBuffer_execute));
__jsb_cc_gfx_CommandBuffer_proto->defineFunction("updateBuffer", _SE(js_gfx_CommandBuffer_updateBuffer));
__jsb_cc_gfx_CommandBuffer_proto->defineFunction("copyBuffersToTexture", _SE(js_gfx_CommandBuffer_copyBuffersToTexture));
__jsb_cc_gfx_Buffer_proto->defineFunction("initialize", _SE(js_gfx_Buffer_initialize));
__jsb_cc_gfx_Texture_proto->defineFunction("initialize", _SE(js_gfx_Texture_initialize));
// Get the ns
se::Value nsVal;
if (!obj->getProperty("gfx", &nsVal)) {
se::HandleObject jsobj(se::Object::createPlainObject());
nsVal.setObject(jsobj);
obj->setProperty("gfx", nsVal);
}
return true;
}

View File

@@ -0,0 +1,30 @@
/****************************************************************************
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 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.
****************************************************************************/
#pragma once
namespace se {
class Object;
}
bool register_all_gfx_manual(se::Object *obj); // NOLINT(readability-identifier-naming)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
#pragma once
#include "bindings/jswrapper/PrivateObject.h"
#include "jsb_global_init.h"
template <typename T, class... Args>
T *jsb_override_new(Args &&...args) { // NOLINT(readability-identifier-naming)
// create object in the default way
return ccnew T(std::forward<Args>(args)...);
}
template <typename T>
void jsb_override_delete(T *arg) { // NOLINT(readability-identifier-naming)
// create object in gfx way
delete (arg);
}
template <typename T, typename... ARGS>
se::PrivateObjectBase *jsb_make_private_object(ARGS &&...args) { // NOLINT(readability-identifier-naming)
if constexpr (std::is_base_of<cc::RefCounted, T>::value) {
return se::ccintrusive_ptr_private_object(ccnew T(std::forward<ARGS>(args)...));
} else {
return se::shared_ptr_private_object(std::make_shared<T>(std::forward<ARGS>(args)...));
}
}
template <typename T>
typename std::enable_if<std::is_base_of<cc::RefCounted, T>::value, se::TypedPrivateObject<T> *>::type
jsb_make_private_object_with_instance(T *instance) { // NOLINT(readability-identifier-naming)
return se::ccintrusive_ptr_private_object(instance);
}
template <typename T>
typename std::enable_if<!std::is_base_of<cc::RefCounted, T>::value, se::TypedPrivateObject<T> *>::type
jsb_make_private_object_with_instance(T *instance) { // NOLINT(readability-identifier-naming)
return se::shared_ptr_private_object(std::shared_ptr<T>(instance));
}
#define JSB_MAKE_PRIVATE_OBJECT(kls, ...) jsb_make_private_object<kls>(__VA_ARGS__)
#define JSB_MAKE_PRIVATE_OBJECT_WITH_INSTANCE(instance) jsb_make_private_object_with_instance(instance)
#define JSB_ALLOC(kls, ...) jsb_override_new<kls>(__VA_ARGS__)
#define JSB_FREE(kls) jsb_override_delete(kls)
namespace se {
class Class;
class Value;
} // namespace se
bool jsb_register_global_variables(se::Object *global); // NOLINT(readability-identifier-naming)
bool jsb_set_extend_property(const char *ns, const char *clsName); // NOLINT(readability-identifier-naming)
bool jsb_run_script(const ccstd::string &filePath, se::Value *rval = nullptr); // NOLINT(readability-identifier-naming)
bool jsb_run_script_module(const ccstd::string &filePath, se::Value *rval = nullptr); // NOLINT(readability-identifier-naming)
bool jsb_global_load_image(const ccstd::string &path, const se::Value &callbackVal); // NOLINT(readability-identifier-naming)

View File

@@ -0,0 +1,244 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
// clang-format off
#include "base/Macros.h"
// clang-format: off
#include "base/std/container/string.h"
#include "uv.h"
// clang-format on
#include "jsb_global_init.h"
#include <type_traits>
#include <utility>
#include "base/Scheduler.h"
#include "base/ZipUtils.h"
#include "base/base64.h"
#include "base/memory/Memory.h"
#include "jsb_conversions.h"
#include "xxtea/xxtea.h"
#include <chrono>
#include <regex>
#include <sstream>
using namespace cc; //NOLINT
se::Object *__jsbObj = nullptr; //NOLINT
se::Object *__glObj = nullptr; //NOLINT
static std::basic_string<unsigned char> xxteaKey;
void jsb_set_xxtea_key(const ccstd::string &key) { //NOLINT
xxteaKey.assign(key.begin(), key.end());
}
static const char *BYTE_CODE_FILE_EXT = ".jsc"; //NOLINT
static ccstd::string removeFileExt(const ccstd::string &filePath) {
size_t pos = filePath.rfind('.');
if (0 < pos) {
return filePath.substr(0, pos);
}
return filePath;
}
static int selectPort(int port) {
struct sockaddr_in addr;
static uv_tcp_t server;
uv_loop_t loop;
uv_loop_init(&loop);
int tryTimes = 200;
int startPort = port;
#if CC_PLATFORM == CC_PLATFORM_ANDROID
constexpr int localPortMin = 37000; // query from /proc/sys/net/ipv4/ip_local_port_range
if (startPort < localPortMin) {
uv_interface_address_t *info = nullptr;
int count = 0;
uv_interface_addresses(&info, &count);
if (count == 0) {
SE_LOGE("Failed to accquire interfaces, error: %s\n Re-select port after 37000", strerror(errno));
startPort = localPortMin + port;
}
if (info) {
uv_free_interface_addresses(info, count);
}
}
#endif
while (tryTimes-- > 0) {
uv_tcp_init(&loop, &server);
uv_ip4_addr("0.0.0.0", startPort, &addr);
uv_tcp_bind(&server, reinterpret_cast<const struct sockaddr *>(&addr), 0);
int r = uv_listen(reinterpret_cast<uv_stream_t *>(&server), 5, nullptr);
uv_close(reinterpret_cast<uv_handle_t *>(&server), nullptr);
if (r) {
SE_LOGD("Failed to listen port %d, error: %s. Try next port\n", startPort, uv_strerror(r));
startPort += 1;
} else {
break;
}
}
uv_loop_close(&loop);
return startPort;
}
void jsb_init_file_operation_delegate() { //NOLINT
static se::ScriptEngine::FileOperationDelegate delegate;
if (!delegate.isValid()) {
delegate.onGetDataFromFile = [](const ccstd::string &path, const std::function<void(const uint8_t *, size_t)> &readCallback) -> void {
CC_ASSERT(!path.empty());
Data fileData;
ccstd::string byteCodePath = removeFileExt(path) + BYTE_CODE_FILE_EXT;
if (FileUtils::getInstance()->isFileExist(byteCodePath)) {
fileData = FileUtils::getInstance()->getDataFromFile(byteCodePath);
uint32_t dataLen = 0;
uint8_t *data = xxtea_decrypt(fileData.getBytes(), static_cast<uint32_t>(fileData.getSize()),
const_cast<unsigned char *>(xxteaKey.data()),
static_cast<uint32_t>(xxteaKey.size()), reinterpret_cast<uint32_t *>(&dataLen));
if (data == nullptr) {
SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
return;
}
if (ZipUtils::isGZipBuffer(data, dataLen)) {
uint8_t *unpackedData;
uint32_t unpackedLen = ZipUtils::inflateMemory(data, dataLen, &unpackedData);
if (unpackedData == nullptr) {
SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
return;
}
readCallback(unpackedData, unpackedLen);
free(data);
free(unpackedData);
} else {
readCallback(data, dataLen);
free(data);
}
return;
}
fileData = FileUtils::getInstance()->getDataFromFile(path);
readCallback(fileData.getBytes(), fileData.getSize());
};
delegate.onGetStringFromFile = [](const ccstd::string &path) -> ccstd::string {
CC_ASSERT(!path.empty());
ccstd::string byteCodePath = removeFileExt(path) + BYTE_CODE_FILE_EXT;
if (FileUtils::getInstance()->isFileExist(byteCodePath)) {
Data fileData = FileUtils::getInstance()->getDataFromFile(byteCodePath);
uint32_t dataLen;
uint8_t *data = xxtea_decrypt(static_cast<uint8_t *>(fileData.getBytes()), static_cast<uint32_t>(fileData.getSize()),
const_cast<unsigned char *>(xxteaKey.data()),
static_cast<uint32_t>(xxteaKey.size()), &dataLen);
if (data == nullptr) {
SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
return "";
}
if (ZipUtils::isGZipBuffer(data, dataLen)) {
uint8_t *unpackedData;
uint32_t unpackedLen = ZipUtils::inflateMemory(data, dataLen, &unpackedData);
if (unpackedData == nullptr) {
SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
return "";
}
ccstd::string ret(reinterpret_cast<const char *>(unpackedData), unpackedLen);
free(unpackedData);
free(data);
return ret;
}
ccstd::string ret(reinterpret_cast<const char *>(data), dataLen);
free(data);
return ret;
}
if (FileUtils::getInstance()->isFileExist(path)) {
return FileUtils::getInstance()->getStringFromFile(path);
}
SE_LOGE("ScriptEngine::onGetStringFromFile %s not found, possible missing file.\n", path.c_str());
return "";
};
delegate.onGetFullPath = [](const ccstd::string &path) -> ccstd::string {
CC_ASSERT(!path.empty());
ccstd::string byteCodePath = removeFileExt(path) + BYTE_CODE_FILE_EXT;
if (FileUtils::getInstance()->isFileExist(byteCodePath)) {
return FileUtils::getInstance()->fullPathForFilename(byteCodePath);
}
return FileUtils::getInstance()->fullPathForFilename(path);
};
delegate.onCheckFileExist = [](const ccstd::string &path) -> bool {
CC_ASSERT(!path.empty());
return FileUtils::getInstance()->isFileExist(path);
};
CC_ASSERT(delegate.isValid());
se::ScriptEngine::getInstance()->setFileOperationDelegate(delegate);
} else {
// Games may be restarted in the same process and run in different threads. Android may restart from recent task list.
se::ScriptEngine::getInstance()->setFileOperationDelegate(delegate);
}
}
bool jsb_enable_debugger(const ccstd::string &debuggerServerAddr, uint32_t port, bool isWaitForConnect) { //NOLINT
#if SCRIPT_ENGINE_TYPE == SCRIPT_ENGINE_V8
if (debuggerServerAddr.empty() || port == 0) {
return false;
}
port = static_cast<uint32_t>(selectPort(static_cast<int>(port)));
auto *se = se::ScriptEngine::getInstance();
if (se != nullptr) {
se->enableDebugger(debuggerServerAddr, port, isWaitForConnect);
} else {
// NOTE: jsb_enable_debugger may be invoked before se::ScriptEngine is initialized,
// So cache the debugger information in global and use it in se::ScriptEngine::start.
// This strategy keeps the compatibility of se::ScriptEngine::enableDebugger.
se::ScriptEngine::DebuggerInfo debuggerInfo;
debuggerInfo.serverAddr = debuggerServerAddr;
debuggerInfo.port = port;
debuggerInfo.isWait = isWaitForConnect;
se::ScriptEngine::_setDebuggerInfo(debuggerInfo);
}
#endif
return true;
}

View File

@@ -0,0 +1,39 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
#pragma once
#include <cstdint>
#include "base/std/container/string.h"
namespace se {
class Object;
} // namespace se
extern se::Object *__jsbObj; //NOLINT
extern se::Object *__glObj; //NOLINT
void jsb_init_file_operation_delegate(); //NOLINT
void jsb_set_xxtea_key(const ccstd::string &key); //NOLINT
bool jsb_enable_debugger(const ccstd::string &debuggerServerAddr, uint32_t port, bool isWaitForConnect = false); //NOLINT

View File

@@ -0,0 +1,42 @@
/****************************************************************************
Copyright (c) 2017-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 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 "jsb_helper.h"
#include "base/DeferredReleasePool.h"
#include "base/memory/Memory.h"
/* static */
void CleanupTask::pushTaskToAutoReleasePool(const std::function<void()> &cb) {
auto *ret = ccnew CleanupTask;
ret->_cb = cb;
cc::DeferredReleasePool::add(ret);
}
CleanupTask::CleanupTask() = default;
CleanupTask::~CleanupTask() {
if (_cb != nullptr) {
_cb();
}
}

View File

@@ -0,0 +1,40 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
#pragma once
#include "base/RefCounted.h"
#include <functional>
class CleanupTask : public cc::RefCounted {
public:
static void pushTaskToAutoReleasePool(const std::function<void()> &cb);
CleanupTask();
~CleanupTask() override;
private:
std::function<void()> _cb{nullptr};
};

View File

@@ -0,0 +1,233 @@
/****************************************************************************
Copyright (c) 2017-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 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 "cocos/bindings/manual/jsb_module_register.h"
#include "cocos/base/DeferredReleasePool.h"
#include "cocos/bindings/auto/jsb_2d_auto.h"
#include "cocos/bindings/auto/jsb_assets_auto.h"
#include "cocos/bindings/auto/jsb_cocos_auto.h"
#include "cocos/bindings/auto/jsb_extension_auto.h"
#include "cocos/bindings/auto/jsb_geometry_auto.h"
#include "cocos/bindings/auto/jsb_gfx_auto.h"
#include "cocos/bindings/auto/jsb_gi_auto.h"
#include "cocos/bindings/auto/jsb_network_auto.h"
#include "cocos/bindings/auto/jsb_pipeline_auto.h"
#include "cocos/bindings/auto/jsb_render_auto.h"
#include "cocos/bindings/auto/jsb_scene_auto.h"
#include "cocos/bindings/dop/jsb_dop.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_assets_manual.h"
#include "cocos/bindings/manual/jsb_cocos_manual.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_geometry_manual.h"
#include "cocos/bindings/manual/jsb_gfx_manual.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "cocos/bindings/manual/jsb_network_manual.h"
#include "cocos/bindings/manual/jsb_pipeline_manual.h"
#include "cocos/bindings/manual/jsb_platform.h"
#include "cocos/bindings/manual/jsb_scene_manual.h"
#include "cocos/bindings/manual/jsb_xmlhttprequest.h"
#if USE_GFX_RENDERER
#endif
#if CC_USE_SOCKET
#include "cocos/bindings/manual/jsb_socketio.h"
#include "cocos/bindings/manual/jsb_websocket.h"
#endif // CC_USE_SOCKET
#if CC_USE_AUDIO
#include "cocos/bindings/auto/jsb_audio_auto.h"
#include "cocos/bindings/manual/jsb_audio_manual.h"
#endif
#if CC_USE_XR
#include "cocos/bindings/auto/jsb_xr_auto.h"
#include "cocos/bindings/auto/jsb_xr_extension_auto.h"
#endif
#if CC_USE_AR_MODULE
#include "cocos/bindings/auto/jsb_ar_auto.h"
#include "cocos/bindings/manual/jsb_ar_manual.h"
#endif
#if (CC_PLATFORM == CC_PLATFORM_IOS || CC_PLATFORM == CC_PLATFORM_MACOS)
#include "cocos/bindings/manual/JavaScriptObjCBridge.h"
#endif
#if (CC_PLATFORM == CC_PLATFORM_ANDROID || CC_PLATFORM == CC_PLATFORM_OHOS)
#include "cocos/bindings/manual/JavaScriptJavaBridge.h"
#endif
#if(CC_PLATFORM == CC_PLATFORM_OPENHARMONY)
#if CC_USE_WEBVIEW
#include "cocos/bindings/auto/jsb_webview_auto.h"
#endif
#endif
#if (CC_PLATFORM == CC_PLATFORM_IOS || CC_PLATFORM == CC_PLATFORM_ANDROID || CC_PLATFORM == CC_PLATFORM_OHOS)
#if CC_USE_VIDEO
#include "cocos/bindings/auto/jsb_video_auto.h"
#endif
#if CC_USE_WEBVIEW
#include "cocos/bindings/auto/jsb_webview_auto.h"
#endif
#endif // (CC_PLATFORM == CC_PLATFORM_IOS || CC_PLATFORM == CC_PLATFORM_ANDROID)
#if CC_USE_SOCKET && CC_USE_WEBSOCKET_SERVER
#include "cocos/bindings/manual/jsb_websocket_server.h"
#endif
#if CC_USE_MIDDLEWARE
#include "cocos/bindings/auto/jsb_editor_support_auto.h"
#if CC_USE_SPINE
#include "cocos/bindings/auto/jsb_spine_auto.h"
#include "cocos/bindings/manual/jsb_spine_manual.h"
#endif
#if CC_USE_DRAGONBONES
#include "cocos/bindings/auto/jsb_dragonbones_auto.h"
#include "cocos/bindings/manual/jsb_dragonbones_manual.h"
#endif
#endif // CC_USE_MIDDLEWARE
#if CC_USE_PHYSICS_PHYSX
#include "cocos/bindings/auto/jsb_physics_auto.h"
#endif
bool jsb_register_all_modules() {
se::ScriptEngine *se = se::ScriptEngine::getInstance();
se->addBeforeCleanupHook([se]() {
se->garbageCollect();
cc::DeferredReleasePool::clear();
se->garbageCollect();
cc::DeferredReleasePool::clear();
});
se->addRegisterCallback(jsb_register_global_variables);
se->addRegisterCallback(register_all_engine);
se->addRegisterCallback(register_all_cocos_manual);
se->addRegisterCallback(register_platform_bindings);
se->addRegisterCallback(register_all_gfx);
se->addRegisterCallback(register_all_gfx_manual);
se->addRegisterCallback(register_all_network);
se->addRegisterCallback(register_all_network_manual);
se->addRegisterCallback(register_all_xmlhttprequest);
// extension depend on network
se->addRegisterCallback(register_all_extension);
se->addRegisterCallback(register_all_dop_bindings);
se->addRegisterCallback(register_all_assets);
se->addRegisterCallback(register_all_assets_manual);
// pipeline depend on asset
se->addRegisterCallback(register_all_pipeline);
se->addRegisterCallback(register_all_pipeline_manual);
se->addRegisterCallback(register_all_geometry);
se->addRegisterCallback(register_all_geometry_manual);
se->addRegisterCallback(register_all_scene);
se->addRegisterCallback(register_all_gi);
se->addRegisterCallback(register_all_scene_manual);
se->addRegisterCallback(register_all_render);
se->addRegisterCallback(register_all_native2d);
#if (CC_PLATFORM == CC_PLATFORM_IOS || CC_PLATFORM == CC_PLATFORM_MACOS)
se->addRegisterCallback(register_javascript_objc_bridge);
se->addRegisterCallback(register_script_native_bridge);
#endif
#if (CC_PLATFORM == CC_PLATFORM_ANDROID || CC_PLATFORM == CC_PLATFORM_OHOS)
se->addRegisterCallback(register_javascript_java_bridge);
se->addRegisterCallback(register_script_native_bridge);
#endif
#if CC_USE_AUDIO
se->addRegisterCallback(register_all_audio);
se->addRegisterCallback(register_all_audio_manual);
#endif
#if CC_USE_XR
se->addRegisterCallback(register_all_xr);
se->addRegisterCallback(register_all_xr_extension);
#endif
#if CC_USE_SOCKET
se->addRegisterCallback(register_all_websocket);
se->addRegisterCallback(register_all_socketio);
#endif
#if CC_USE_MIDDLEWARE
se->addRegisterCallback(register_all_editor_support);
#if CC_USE_SPINE
se->addRegisterCallback(register_all_spine);
se->addRegisterCallback(register_all_spine_manual);
#endif
#if CC_USE_DRAGONBONES
se->addRegisterCallback(register_all_dragonbones);
se->addRegisterCallback(register_all_dragonbones_manual);
#endif
#endif // CC_USE_MIDDLEWARE
#if CC_USE_PHYSICS_PHYSX
se->addRegisterCallback(register_all_physics);
#endif
#if CC_USE_AR_MODULE
se->addRegisterCallback(register_all_ar);
se->addRegisterCallback(register_all_ar_manual);
#endif // CC_USE_AR_MODULE
#if (CC_PLATFORM == CC_PLATFORM_OPENHARMONY)
#if CC_USE_WEBVIEW
se->addRegisterCallback(register_all_webview);
#endif
#endif
#if (CC_PLATFORM == CC_PLATFORM_IOS || CC_PLATFORM == CC_PLATFORM_ANDROID || CC_PLATFORM == CC_PLATFORM_OHOS)
#if CC_USE_VIDEO
se->addRegisterCallback(register_all_video);
#endif
#if CC_USE_WEBVIEW
se->addRegisterCallback(register_all_webview);
#endif
#endif // (CC_PLATFORM == CC_PLATFORM_IOS || CC_PLATFORM == CC_PLATFORM_ANDROID)
#if CC_USE_SOCKET && CC_USE_WEBSOCKET_SERVER
se->addRegisterCallback(register_all_websocket_server);
#endif
se->addAfterCleanupHook([]() {
cc::DeferredReleasePool::clear();
JSBClassType::cleanup();
});
return true;
}

View File

@@ -0,0 +1,29 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
#pragma once
#include "base/std/container/string.h"
bool jsb_register_all_modules();

View File

@@ -0,0 +1,335 @@
/****************************************************************************
Copyright (c) 2017-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 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 "jsb_network_manual.h"
#include "base/Config.h"
#include "bindings/auto/jsb_network_auto.h"
#include "bindings/manual/jsb_conversions.h"
#include "bindings/manual/jsb_global.h"
#include "network/Downloader.h"
// deprecated since v3.6
static bool js_network_Downloader_createDownloadFileTask(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::network::Downloader *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false,
"js_network_Downloader_createDownloadFileTask : Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 2) {
ccstd::string arg0;
ccstd::string arg1;
ok &= sevalue_to_native(args[0], &arg0);
ok &= sevalue_to_native(args[1], &arg1);
SE_PRECONDITION2(ok, false,
"js_network_Downloader_createDownloadFileTask : Error processing arguments");
std::shared_ptr<const cc::network::DownloadTask> result = cobj->createDownloadTask(
arg0, arg1);
ok &= nativevalue_to_se(result, s.rval());
//ROOT downloader object
s.thisObject()->root();
SE_PRECONDITION2(ok, false,
"js_network_Downloader_createDownloadFileTask : Error processing arguments");
return true;
}
if (argc == 3) {
ccstd::string arg0;
ccstd::string arg1;
ccstd::string arg2;
ok &= sevalue_to_native(args[0], &arg0);
ok &= sevalue_to_native(args[1], &arg1);
ok &= sevalue_to_native(args[2], &arg2);
SE_PRECONDITION2(ok, false,
"js_network_Downloader_createDownloadFileTask : Error processing arguments");
std::shared_ptr<const cc::network::DownloadTask> result = cobj->createDownloadTask(
arg0, arg1, arg2);
ok &= nativevalue_to_se(result, s.rval());
//ROOT downloader object
s.thisObject()->root();
SE_PRECONDITION2(ok, false,
"js_network_Downloader_createDownloadFileTask : Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 3);
return false;
}
SE_BIND_FUNC(js_network_Downloader_createDownloadFileTask)
static bool js_network_Downloader_createDownloadTask(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::network::Downloader *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false,
"js_network_Downloader_createDownloadFileTask : Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 2) {
ccstd::string arg0;
ccstd::string arg1;
ok &= sevalue_to_native(args[0], &arg0);
ok &= sevalue_to_native(args[1], &arg1);
SE_PRECONDITION2(ok, false,
"js_network_Downloader_createDownloadTask : Error processing arguments");
std::shared_ptr<const cc::network::DownloadTask> result = cobj->createDownloadTask(
arg0, arg1);
ok &= nativevalue_to_se(result, s.rval());
//ROOT downloader object
s.thisObject()->root();
SE_PRECONDITION2(ok, false,
"js_network_Downloader_createDownloadTask : Error processing arguments");
return true;
}
if (argc == 3) {
ccstd::string arg0;
ccstd::string arg1;
ccstd::string arg2;
ok &= sevalue_to_native(args[0], &arg0);
ok &= sevalue_to_native(args[1], &arg1);
ok &= sevalue_to_native(args[2], &arg2);
SE_PRECONDITION2(ok, false,
"js_network_Downloader_createDownloadTask : Error processing arguments");
std::shared_ptr<const cc::network::DownloadTask> result = cobj->createDownloadTask(
arg0, arg1, arg2);
ok &= nativevalue_to_se(result, s.rval());
//ROOT downloader object
s.thisObject()->root();
SE_PRECONDITION2(ok, false,
"js_network_Downloader_createDownloadTask : Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 3);
return false;
}
SE_BIND_FUNC(js_network_Downloader_createDownloadTask)
// deprecated since v3.6
static bool js_network_Downloader_setOnFileTaskSuccess(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::network::Downloader *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
std::function<void(const cc::network::DownloadTask &)> arg0;
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();
auto lambda = [=](const cc::network::DownloadTask &larg0) -> void {
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
CC_UNUSED bool ok = true;
se::ValueArray args;
args.resize(1);
ok &= nativevalue_to_se(larg0, args[0]);
se::Value rval;
se::Object *funcObj = jsFunc.toObject();
bool succeed = funcObj->call(args, thisObj, &rval);
if (!succeed) {
se::ScriptEngine::getInstance()->clearException();
}
if (thisObj) {
thisObj->unroot();
}
};
arg0 = lambda;
} else {
arg0 = nullptr;
}
} while (false);
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->setOnSuccess(arg0);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_network_Downloader_setOnFileTaskSuccess) // NOLINT(readability-identifier-naming)
static bool js_network_Downloader_setOnSuccess(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::network::Downloader *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
std::function<void(const cc::network::DownloadTask &)> arg0;
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();
auto lambda = [=](const cc::network::DownloadTask &larg0) -> void {
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
CC_UNUSED bool ok = true;
se::ValueArray args;
args.resize(1);
ok &= nativevalue_to_se(larg0, args[0]);
se::Value rval;
se::Object *funcObj = jsFunc.toObject();
bool succeed = funcObj->call(args, thisObj, &rval);
if (!succeed) {
se::ScriptEngine::getInstance()->clearException();
}
if (thisObj) {
thisObj->unroot();
}
};
arg0 = lambda;
} else {
arg0 = nullptr;
}
} while (false);
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->setOnSuccess(arg0);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC_AS_PROP_SET(js_network_Downloader_setOnSuccess)
// deprecated in v3.6
static bool js_network_Downloader_setOnTaskError(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::network::Downloader *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
std::function<void(const cc::network::DownloadTask &, int, int, const ccstd::string &)> arg0;
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();
auto lambda = [=](const cc::network::DownloadTask &larg0, int larg1, int larg2, const ccstd::string &larg3) -> void {
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
CC_UNUSED bool ok = true;
se::ValueArray args;
args.resize(4);
ok &= nativevalue_to_se(larg0, args[0]);
ok &= nativevalue_to_se(larg1, args[1]);
ok &= nativevalue_to_se(larg2, args[2]);
ok &= nativevalue_to_se(larg3, args[3]);
se::Value rval;
se::Object *funcObj = jsFunc.toObject();
bool succeed = funcObj->call(args, thisObj, &rval);
if (!succeed) {
se::ScriptEngine::getInstance()->clearException();
}
if (thisObj) {
thisObj->unroot();
}
};
arg0 = lambda;
} else {
arg0 = nullptr;
}
} while (false);
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->setOnError(arg0);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_network_Downloader_setOnTaskError) // NOLINT(readability-identifier-naming)
static bool js_network_Downloader_setOnError(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::network::Downloader *>(s.nativeThisObject());
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
std::function<void(const cc::network::DownloadTask &, int, int, const ccstd::string &)> arg0;
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();
auto lambda = [=](const cc::network::DownloadTask &larg0, int larg1, int larg2, const ccstd::string &larg3) -> void {
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
CC_UNUSED bool ok = true;
se::ValueArray args;
args.resize(4);
ok &= nativevalue_to_se(larg0, args[0]);
ok &= nativevalue_to_se(larg1, args[1]);
ok &= nativevalue_to_se(larg2, args[2]);
ok &= nativevalue_to_se(larg3, args[3]);
se::Value rval;
se::Object *funcObj = jsFunc.toObject();
bool succeed = funcObj->call(args, thisObj, &rval);
if (!succeed) {
se::ScriptEngine::getInstance()->clearException();
}
if (thisObj) {
thisObj->unroot();
}
};
arg0 = lambda;
} else {
arg0 = nullptr;
}
} while (false);
SE_PRECONDITION2(ok, false, "Error processing arguments");
cobj->setOnError(arg0);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC_AS_PROP_SET(js_network_Downloader_setOnError)
bool register_all_network_manual(se::Object * /*obj*/) { // NOLINT(readability-identifier-naming)
__jsb_cc_network_Downloader_proto->defineProperty("onSuccess", nullptr, _SE(js_network_Downloader_setOnSuccess_asSetter));
__jsb_cc_network_Downloader_proto->defineProperty("onError", nullptr, _SE(js_network_Downloader_setOnError_asSetter));
__jsb_cc_network_Downloader_proto->defineFunction("createDownloadTask",
_SE(js_network_Downloader_createDownloadTask));
__jsb_cc_network_Downloader_proto->defineFunction("createDownloadFileTask",
_SE(js_network_Downloader_createDownloadFileTask)); // deprecated since v3.6
__jsb_cc_network_Downloader_proto->defineFunction("setOnTaskError",
_SE(js_network_Downloader_setOnTaskError)); // deprecated since v3.6
__jsb_cc_network_Downloader_proto->defineFunction("setOnFileTaskSuccess",
_SE(js_network_Downloader_setOnFileTaskSuccess)); // deprecated since v3.6
return true;
}

View File

@@ -0,0 +1,31 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
#pragma once
namespace se {
class Object;
}
bool register_all_network_manual(se::Object *obj);

View File

@@ -0,0 +1,69 @@
/****************************************************************************
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 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 "cocos/bindings/auto/jsb_gfx_auto.h"
#include "cocos/bindings/auto/jsb_pipeline_auto.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "gfx-base/GFXPipelineState.h"
#include "renderer/pipeline/Define.h"
#include "renderer/pipeline/PipelineStateManager.h"
#include "renderer/pipeline/RenderPipeline.h"
static bool JSB_getOrCreatePipelineState(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
size_t argc = args.size();
if (argc == 4) {
auto *pass = static_cast<cc::scene::Pass *>(args[0].toObject()->getPrivateData());
auto *shader = static_cast<cc::gfx::Shader *>(args[1].toObject()->getPrivateData());
auto *renderPass = static_cast<cc::gfx::RenderPass *>(args[2].toObject()->getPrivateData());
auto *inputAssembler = static_cast<cc::gfx::InputAssembler *>(args[3].toObject()->getPrivateData());
auto *pipelineState = cc::pipeline::PipelineStateManager::getOrCreatePipelineState(pass, shader, inputAssembler, renderPass);
native_ptr_to_seval<cc::gfx::PipelineState>(pipelineState, &s.rval());
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 4);
return false;
}
SE_BIND_FUNC(JSB_getOrCreatePipelineState);
bool register_all_pipeline_manual(se::Object *obj) { // NOLINT(readability-identifier-naming)
// Get the ns
se::Value nrVal;
if (!obj->getProperty("nr", &nrVal)) {
se::HandleObject jsobj(se::Object::createPlainObject());
nrVal.setObject(jsobj);
obj->setProperty("nr", nrVal);
}
se::Object *nr = nrVal.toObject();
se::Value psmVal;
se::HandleObject jsobj(se::Object::createPlainObject());
psmVal.setObject(jsobj);
nr->setProperty("PipelineStateManager", psmVal);
psmVal.toObject()->defineFunction("getOrCreatePipelineState", _SE(JSB_getOrCreatePipelineState));
return true;
}

View File

@@ -0,0 +1,30 @@
/****************************************************************************
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 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.
****************************************************************************/
#pragma once
namespace se {
class Object;
}
bool register_all_pipeline_manual(se::Object *obj);

View File

@@ -0,0 +1,34 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
#pragma once
#include "base/std/container/string.h"
#include "base/std/container/unordered_map.h"
namespace se {
class Object;
}
bool register_platform_bindings(se::Object *obj); // NOLINT[readability-identifier-naming]
const ccstd::unordered_map<ccstd::string, ccstd::string> &getFontFamilyNameMap();

View File

@@ -0,0 +1,88 @@
/****************************************************************************
Copyright (c) 2017-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 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 "jsb_platform.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "cocos/platform/FileUtils.h"
#include "cocos/platform/java/jni/JniHelper.h"
#include <regex>
#ifndef JCLS_CANVASIMPL
#define JCLS_CANVASIMPL "com/cocos/lib/CanvasRenderingContext2DImpl"
#endif
static ccstd::unordered_map<ccstd::string, ccstd::string> gFontFamilyNameMap;
const ccstd::unordered_map<ccstd::string, ccstd::string> &getFontFamilyNameMap() {
return gFontFamilyNameMap;
}
static bool jsbLoadFont(se::State &s) {
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc >= 1) {
s.rval().setNull();
ccstd::string originalFamilyName;
ok &= sevalue_to_native(args[0], &originalFamilyName);
SE_PRECONDITION2(ok, false, "Error processing argument: originalFamilyName");
ccstd::string source;
ok &= sevalue_to_native(args[1], &source);
SE_PRECONDITION2(ok, false, "Error processing argument: source");
ccstd::string fontFilePath;
std::regex re(R"(url\(\s*'\s*(.*?)\s*'\s*\))");
std::match_results<ccstd::string::const_iterator> results;
if (std::regex_search(source.cbegin(), source.cend(), results, re)) {
fontFilePath = results[1].str();
}
fontFilePath = cc::FileUtils::getInstance()->fullPathForFilename(fontFilePath);
if (fontFilePath.empty()) {
SE_LOGE("Font (%s) doesn't exist!", fontFilePath.c_str());
return true;
}
cc::JniHelper::callStaticVoidMethod(JCLS_CANVASIMPL, "loadTypeface", originalFamilyName, fontFilePath);
s.rval().setString(originalFamilyName);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(jsbLoadFont)
bool register_platform_bindings(se::Object * /*obj*/) { // NOLINT(readability-identifier-naming)
__jsbObj->defineFunction("loadFont", _SE(jsbLoadFont));
return true;
}

View File

@@ -0,0 +1,121 @@
/****************************************************************************
Copyright (c) 2017-2022 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.
****************************************************************************/
#import "jsb_platform.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "cocos/platform/FileUtils.h"
#import <Foundation/Foundation.h>
#import <CoreText/CoreText.h>
#include <regex>
using namespace cc;
static ccstd::unordered_map<ccstd::string, ccstd::string> _fontFamilyNameMap;
const ccstd::unordered_map<ccstd::string, ccstd::string> &getFontFamilyNameMap() {
return _fontFamilyNameMap;
}
static bool JSB_loadFont(se::State &s) {
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc >= 1) {
s.rval().setNull();
ccstd::string originalFamilyName;
ok &= sevalue_to_native(args[0], &originalFamilyName);
SE_PRECONDITION2(ok, false, "Error processing argument: originalFamilyName");
// Don't reload font again to avoid memory leak.
if (_fontFamilyNameMap.find(originalFamilyName) != _fontFamilyNameMap.end()) {
s.rval().setString(_fontFamilyNameMap[originalFamilyName]);
return true;
}
ccstd::string source;
ok &= sevalue_to_native(args[1], &source);
SE_PRECONDITION2(ok, false, "Error processing argument: source");
ccstd::string fontFilePath;
std::regex re("url\\(\\s*'\\s*(.*?)\\s*'\\s*\\)");
std::match_results<ccstd::string::const_iterator> results;
if (std::regex_search(source.cbegin(), source.cend(), results, re)) {
fontFilePath = results[1].str();
}
fontFilePath = FileUtils::getInstance()->fullPathForFilename(fontFilePath);
if (fontFilePath.empty()) {
SE_LOGE("Font (%s) doesn't exist!", fontFilePath.c_str());
return true;
}
NSData *dynamicFontData = [NSData dataWithContentsOfFile:[NSString stringWithUTF8String:fontFilePath.c_str()]];
if (!dynamicFontData) {
SE_LOGE("load font (%s) failed!", source.c_str());
return true;
}
bool succeed = true;
CFErrorRef error;
CGDataProviderRef providerRef = CGDataProviderCreateWithCFData((CFDataRef)dynamicFontData);
CGFontRef font = CGFontCreateWithDataProvider(providerRef);
if (!CTFontManagerRegisterGraphicsFont(font, &error)) {
CFStringRef errorDescription = CFErrorCopyDescription(error);
const char *cErrorStr = CFStringGetCStringPtr(errorDescription, kCFStringEncodingUTF8);
SE_LOGE("Failed to load font: %s", cErrorStr);
CFRelease(errorDescription);
succeed = false;
}
if (succeed) {
CFStringRef fontName = CGFontCopyFullName(font);
ccstd::string familyName([(NSString *)fontName UTF8String]);
if (!familyName.empty()) {
_fontFamilyNameMap.emplace(originalFamilyName, familyName);
s.rval().setString(familyName);
}
CFRelease(fontName);
}
CFRelease(font);
CFRelease(providerRef);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_loadFont)
bool register_platform_bindings(se::Object *obj) {
__jsbObj->defineFunction("loadFont", _SE(JSB_loadFont));
return true;
}

View File

@@ -0,0 +1,86 @@
/****************************************************************************
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 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 "jsb_platform.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global_init.h"
#include "cocos/platform/FileUtils.h"
#include <regex>
using namespace cc;
static ccstd::unordered_map<ccstd::string, ccstd::string> _fontFamilyNameMap;
const ccstd::unordered_map<ccstd::string, ccstd::string> &getFontFamilyNameMap() {
return _fontFamilyNameMap;
}
static bool JSB_loadFont(se::State &s) {
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc >= 1) {
s.rval().setNull();
ccstd::string originalFamilyName;
ok &= sevalue_to_native(args[0], &originalFamilyName);
SE_PRECONDITION2(ok, false, "Error processing argument: originalFamilyName");
ccstd::string source;
ok &= sevalue_to_native(args[1], &source);
SE_PRECONDITION2(ok, false, "Error processing argument: source");
ccstd::string fontFilePath;
std::regex re(R"(url\(\s*'\s*(.*?)\s*'\s*\))");
std::match_results<ccstd::string::const_iterator> results;
if (std::regex_search(source.cbegin(), source.cend(), results, re)) {
fontFilePath = results[1].str();
}
fontFilePath = FileUtils::getInstance()->fullPathForFilename(fontFilePath);
if (fontFilePath.empty()) {
SE_LOGE("Font (%s) doesn't exist!", fontFilePath.c_str());
return true;
}
// just put the path info, used at CanvasRenderingContext2DImpl::updateFont()
_fontFamilyNameMap.emplace(originalFamilyName, fontFilePath);
s.rval().setString(originalFamilyName);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_loadFont)
bool register_platform_bindings(se::Object *obj) {
__jsbObj->defineFunction("loadFont", _SE(JSB_loadFont));
return true;
}

View File

@@ -0,0 +1,90 @@
/****************************************************************************
Copyright (c) 2017-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 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 "jsb_platform.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "cocos/platform/FileUtils.h"
#include "cocos/platform/java/jni/JniHelper.h"
#include <regex>
#ifndef JCLS_CANVASIMPL
#define JCLS_CANVASIMPL "com/cocos/lib/CanvasRenderingContext2DImpl"
#endif
using namespace cc; //NOLINT
static ccstd::unordered_map<ccstd::string, ccstd::string> gFontFamilyNameMap;
const ccstd::unordered_map<ccstd::string, ccstd::string> &getFontFamilyNameMap() {
return gFontFamilyNameMap;
}
static bool JSB_loadFont(se::State &s) { //NOLINT
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc >= 1) {
s.rval().setNull();
ccstd::string originalFamilyName;
ok &= sevalue_to_native(args[0], &originalFamilyName);
SE_PRECONDITION2(ok, false, "Error processing argument: originalFamilyName");
ccstd::string source;
ok &= sevalue_to_native(args[1], &source);
SE_PRECONDITION2(ok, false, "Error processing argument: source");
ccstd::string fontFilePath;
std::regex re(R"(url\(\s*'\s*(.*?)\s*'\s*\))");
std::match_results<ccstd::string::const_iterator> results;
if (std::regex_search(source.cbegin(), source.cend(), results, re)) {
fontFilePath = results[1].str();
}
fontFilePath = FileUtils::getInstance()->fullPathForFilename(fontFilePath);
if (fontFilePath.empty()) {
SE_LOGE("Font (%s) doesn't exist!", fontFilePath.c_str());
return true;
}
JniHelper::callStaticVoidMethod(JCLS_CANVASIMPL, "loadTypeface", originalFamilyName, fontFilePath);
s.rval().setString(originalFamilyName);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_loadFont)
bool register_platform_bindings(se::Object *obj) { //NOLINT
__jsbObj->defineFunction("loadFont", _SE(JSB_loadFont));
return true;
}

View File

@@ -0,0 +1,52 @@
/****************************************************************************
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 "jsb_platform.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global_init.h"
#include "cocos/platform/FileUtils.h"
#include <regex>
using namespace cc;
static std::unordered_map<std::string, std::string> _fontFamilyNameMap;
const std::unordered_map<std::string, std::string> &getFontFamilyNameMap() {
return _fontFamilyNameMap;
}
static bool JSB_loadFont(se::State &s) {
// TODO(qgh):Currently it does not support loading OpenHarmony fonts, it may be supported in the future
return true;
}
SE_BIND_FUNC(JSB_loadFont)
bool register_platform_bindings(se::Object *obj) {
__jsbObj->defineFunction("loadFont", _SE(JSB_loadFont));
return true;
}

View File

@@ -0,0 +1,86 @@
/****************************************************************************
Copyright (c) 2017-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 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 "jsb_platform.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global_init.h"
#include "cocos/platform/FileUtils.h"
#include <regex>
using namespace cc;
static ccstd::unordered_map<ccstd::string, ccstd::string> fontFamilyNameMap;
const ccstd::unordered_map<ccstd::string, ccstd::string> &getFontFamilyNameMap() {
return fontFamilyNameMap;
}
static bool jsbLoadFont(se::State &s) {
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc >= 1) {
s.rval().setNull();
ccstd::string originalFamilyName;
ok &= sevalue_to_native(args[0], &originalFamilyName);
SE_PRECONDITION2(ok, false, "Error processing argument: originalFamilyName");
ccstd::string source;
ok &= sevalue_to_native(args[1], &source);
SE_PRECONDITION2(ok, false, "Error processing argument: source");
ccstd::string fontFilePath;
std::regex re(R"(url\(\s*'\s*(.*?)\s*'\s*\))");
std::match_results<ccstd::string::const_iterator> results;
if (std::regex_search(source.cbegin(), source.cend(), results, re)) {
fontFilePath = results[1].str();
}
fontFilePath = FileUtils::getInstance()->fullPathForFilename(fontFilePath);
if (fontFilePath.empty()) {
SE_LOGE("Font (%s) doesn't exist!", fontFilePath.c_str());
return true;
}
// just put the path info, used at CanvasRenderingContext2DImpl::updateFont()
fontFamilyNameMap.emplace(originalFamilyName, fontFilePath);
s.rval().setString(originalFamilyName);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(jsbLoadFont)
bool register_platform_bindings(se::Object * /*obj*/) { // NOLINT(readability-identifier-naming)
__jsbObj->defineFunction("loadFont", _SE(jsbLoadFont));
return true;
}

View File

@@ -0,0 +1,902 @@
/****************************************************************************
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 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 "jsb_scene_manual.h"
#include "bindings/auto/jsb_gfx_auto.h"
#include "bindings/auto/jsb_scene_auto.h"
#include "core/Root.h"
#include "core/scene-graph/Node.h"
#include "scene/Model.h"
#ifndef JSB_ALLOC
#define JSB_ALLOC(kls, ...) ccnew kls(__VA_ARGS__)
#endif
#ifndef JSB_FREE
#define JSB_FREE(ptr) delete ptr
#endif
#define DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emmiter) \
se::Object *jsObject = emitter->getScriptObject(); \
if (jsObject == nullptr) { \
jsObject = se::NativePtrToObjectMap::findFirst(emitter); \
emmiter->setScriptObject(jsObject); \
}
namespace {
class TempFloatArray final {
public:
TempFloatArray() = default;
~TempFloatArray() = default;
inline void setData(float *data) { _data = data; }
inline void writeVec3(const cc::Vec3 &p) {
_data[0] = p.x;
_data[1] = p.y;
_data[2] = p.z;
}
inline cc::Vec3 readVec3() const {
return cc::Vec3{_data[0], _data[1], _data[2]};
}
inline void writeQuaternion(const cc::Quaternion &p) {
_data[0] = p.x;
_data[1] = p.y;
_data[2] = p.z;
_data[3] = p.w;
}
inline cc::Quaternion readQuaternion() const {
return cc::Quaternion{_data[0], _data[1], _data[2], _data[3]};
}
inline void writeMat4(const cc::Mat4 &m) {
memcpy(_data, m.m, sizeof(float) * 16);
}
inline cc::Mat4 readMat4() const {
cc::Mat4 ret;
memcpy(ret.m, _data, sizeof(float) * 16);
return ret;
}
inline void writeRay(const cc::geometry::Ray &ray) {
_data[0] = ray.o.x;
_data[1] = ray.o.y;
_data[2] = ray.o.z;
_data[3] = ray.d.x;
_data[4] = ray.d.y;
_data[5] = ray.d.z;
}
inline cc::geometry::Ray readRay() const {
return cc::geometry::Ray{_data[0], _data[1], _data[2], _data[3], _data[4], _data[5]};
}
inline const float &operator[](size_t index) const { return _data[index]; }
inline float &operator[](size_t index) { return _data[index]; }
private:
float *_data{nullptr};
CC_DISALLOW_ASSIGN(TempFloatArray)
};
TempFloatArray tempFloatArray;
} // namespace
static bool js_root_registerListeners(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::Root>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
#define DISPATCH_EVENT_TO_JS_ARGS_0(eventType, jsFuncName) \
cobj->on<eventType>([](cc::Root *rootObj) { \
se::AutoHandleScope hs; \
se::Value rootVal; \
bool ok = nativevalue_to_se(rootObj, rootVal); \
SE_PRECONDITION2_FUNCNAME_VOID(ok, #jsFuncName, "js_root_registerListeners : Error processing arguments"); \
if (rootVal.isObject()) { \
se::ScriptEngine::getInstance()->callFunction(rootVal.toObject(), #jsFuncName, 0, nullptr); \
} \
});
DISPATCH_EVENT_TO_JS_ARGS_0(cc::Root::BeforeCommit, _onDirectorBeforeCommit);
DISPATCH_EVENT_TO_JS_ARGS_0(cc::Root::BeforeRender, _onDirectorBeforeRender);
DISPATCH_EVENT_TO_JS_ARGS_0(cc::Root::AfterRender, _onDirectorAfterRender);
DISPATCH_EVENT_TO_JS_ARGS_0(cc::Root::PipelineChanged, _onDirectorPipelineChanged);
return true;
}
SE_BIND_FUNC(js_root_registerListeners) // NOLINT(readability-identifier-naming)
static void registerOnTransformChanged(cc::Node *node) {
node->on<cc::Node::TransformChanged>(
+[](cc::Node *emitter, cc::TransformBit transformBit) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(transformBit, arg0);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onTransformChanged", 1, &arg0);
});
}
static void registerOnParentChanged(cc::Node *node) {
node->on<cc::Node::ParentChanged>(
+[](cc::Node *emitter, cc::Node *oldParent) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(oldParent, arg0);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onParentChanged", 1, &arg0);
});
}
static void registerOnMobilityChanged(cc::Node *node) {
node->on<cc::Node::MobilityChanged>(
+[](cc::Node *emitter) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onMobilityChanged", 0, nullptr);
});
}
static void registerOnLayerChanged(cc::Node *node) {
node->on<cc::Node::LayerChanged>(
+[](cc::Node *emitter, uint32_t layer) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(layer, arg0);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onLayerChanged", 1, &arg0);
});
}
static void registerOnChildRemoved(cc::Node *node) {
node->on<cc::Node::ChildRemoved>(
+[](cc::Node *emitter, cc::Node *child) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(child, arg0);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onChildRemoved", 1, &arg0);
});
}
static void registerOnChildAdded(cc::Node *node) {
node->on<cc::Node::ChildAdded>(
+[](cc::Node *emitter, cc::Node *child) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(child, arg0);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onChildAdded", 1, &arg0);
});
}
static void registerOnSiblingOrderChanged(cc::Node *node) {
node->on<cc::Node::SiblingOrderChanged>(
+[](cc::Node *emitter) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope scope;
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onSiblingOrderChanged", 0, nullptr);
});
}
static void registerOnActiveNode(cc::Node *node) {
node->on<cc::Node::ActiveNode>(
+[](cc::Node *emitter, bool shouldActiveNow) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(shouldActiveNow, arg0);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onActiveNode", 1, &arg0);
});
}
static void registerOnBatchCreated(cc::Node *node) {
node->on<cc::Node::BatchCreated>(
+[](cc::Node *emitter, bool dontChildPrefab) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(dontChildPrefab, arg0);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onBatchCreated", 1, &arg0);
});
}
static void registerLocalPositionRotationScaleUpdated(cc::Node *node) {
node->on<cc::Node::LocalPositionUpdated>(
+[](cc::Node *emitter, float x, float y, float z) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
ccstd::array<se::Value, 3> args;
nativevalue_to_se(x, args[0]);
nativevalue_to_se(y, args[1]);
nativevalue_to_se(z, args[2]);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onLocalPositionUpdated", static_cast<uint32_t>(args.size()), args.data());
});
node->on<cc::Node::LocalRotationUpdated>(
+[](cc::Node *emitter, float x, float y, float z, float w) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
ccstd::array<se::Value, 4> args;
nativevalue_to_se(x, args[0]);
nativevalue_to_se(y, args[1]);
nativevalue_to_se(z, args[2]);
nativevalue_to_se(w, args[3]);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onLocalRotationUpdated", static_cast<uint32_t>(args.size()), args.data());
});
node->on<cc::Node::LocalScaleUpdated>(
+[](cc::Node *emitter, float x, float y, float z) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
ccstd::array<se::Value, 3> args;
nativevalue_to_se(x, args[0]);
nativevalue_to_se(y, args[1]);
nativevalue_to_se(z, args[2]);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onLocalScaleUpdated", static_cast<uint32_t>(args.size()), args.data());
});
node->on<cc::Node::LocalRTSUpdated>(
+[](cc::Node *emitter, float px, float py, float pz, float rx, float ry, float rz, float rw, float sx, float sy, float sz) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
ccstd::array<se::Value, 10> args;
nativevalue_to_se(px, args[0]);
nativevalue_to_se(py, args[1]);
nativevalue_to_se(pz, args[2]);
nativevalue_to_se(rx, args[3]);
nativevalue_to_se(ry, args[4]);
nativevalue_to_se(rz, args[5]);
nativevalue_to_se(rw, args[6]);
nativevalue_to_se(sx, args[7]);
nativevalue_to_se(sy, args[8]);
nativevalue_to_se(sz, args[9]);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onLocalPositionRotationScaleUpdated", static_cast<uint32_t>(args.size()), args.data());
});
}
static void registerOnLightProbeBakingChanged(cc::Node *node, se::Object *jsObject) {
node->on<cc::Node::LightProbeBakingChanged>(
[jsObject](cc::Node * /*emitter*/) {
se::AutoHandleScope hs;
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onLightProbeBakingChanged", 0, nullptr);
});
}
static bool js_scene_Node_registerListeners(cc::Node *cobj) // NOLINT(readability-identifier-naming)
{
#define NODE_DISPATCH_EVENT_TO_JS(eventType, jsFuncName) \
cobj->on<eventType>( \
+[](cc::Node *emitter) { \
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter) \
se::AutoHandleScope scope; \
se::ScriptEngine::getInstance()->callFunction(jsObject, #jsFuncName, 0, nullptr); \
});
registerOnActiveNode(cobj);
// NOTE: Node.prototype._onBatchCreated was implemented in TS and invoked in scene.jsb.ts (Scene.prototype._load),
// so don't need to register the listener here.
// registerOnBatchCreated(cobj);
registerOnChildAdded(cobj);
registerOnChildRemoved(cobj);
NODE_DISPATCH_EVENT_TO_JS(cc::Node::Reattach, _onReAttach);
NODE_DISPATCH_EVENT_TO_JS(cc::Node::RemovePersistRootNode, _onRemovePersistRootNode);
cobj->on<cc::Node::SiblingIndexChanged>(+[](cc::Node *emitter, index_t newIndex) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(newIndex, arg0);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onSiblingIndexChanged", 1, &arg0);
});
cobj->on<cc::Node::SceneUpdated>(
+[](cc::Node *emitter, cc::Scene *scene) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(scene, arg0);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onSceneUpdated", 1, &arg0);
});
#if CC_EDITOR
cobj->on<cc::Node::EditorAttached>(
+[](cc::Node *emitter, bool attached) {
DEFINE_JS_OBJECT_IN_EVENT_CALLBACK(emitter)
se::AutoHandleScope hs;
se::Value arg0;
nativevalue_to_se(attached, arg0);
se::ScriptEngine::getInstance()->callFunction(jsObject, "_onEditorAttached", 1, &arg0);
});
#endif
registerLocalPositionRotationScaleUpdated(cobj);
return true;
}
static bool js_cc_Node_initAndReturnSharedBuffer(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::Node>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
auto *result = cobj->_getSharedArrayBufferObject();
js_scene_Node_registerListeners(cobj);
s.rval().setObject(result);
return true;
}
SE_BIND_FUNC(js_cc_Node_initAndReturnSharedBuffer) // NOLINT(readability-identifier-naming)
static bool js_scene_Node_registerOnTransformChanged(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::Node>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
registerOnTransformChanged(cobj);
return true;
}
SE_BIND_FUNC(js_scene_Node_registerOnTransformChanged) // NOLINT(readability-identifier-naming)
static bool js_scene_Node_registerOnParentChanged(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::Node>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
registerOnParentChanged(cobj);
return true;
}
SE_BIND_FUNC(js_scene_Node_registerOnParentChanged) // NOLINT(readability-identifier-naming)
static bool js_scene_Node_registerOnMobilityChanged(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::Node>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
registerOnMobilityChanged(cobj);
return true;
}
SE_BIND_FUNC(js_scene_Node_registerOnMobilityChanged) // NOLINT(readability-identifier-naming)
static bool js_scene_Node_registerOnLayerChanged(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::Node>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
registerOnLayerChanged(cobj);
return true;
}
SE_BIND_FUNC(js_scene_Node_registerOnLayerChanged) // NOLINT(readability-identifier-naming)
static bool js_scene_Node_registerOnSiblingOrderChanged(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::Node>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
registerOnSiblingOrderChanged(cobj);
return true;
}
SE_BIND_FUNC(js_scene_Node_registerOnSiblingOrderChanged) // NOLINT(readability-identifier-naming)
static bool js_scene_Node_registerOnLightProbeBakingChanged(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::Node>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
auto *jsObject = s.thisObject();
registerOnLightProbeBakingChanged(cobj, jsObject);
return true;
}
SE_BIND_FUNC(js_scene_Node_registerOnLightProbeBakingChanged) // NOLINT(readability-identifier-naming)
static bool js_scene_Camera_screenPointToRay(void *nativeObject) // NOLINT(readability-identifier-naming)
{
auto *cobj = reinterpret_cast<cc::scene::Camera *>(nativeObject);
cc::geometry::Ray ray = cobj->screenPointToRay(tempFloatArray[0], tempFloatArray[1]);
tempFloatArray.writeRay(ray);
return true;
}
SE_BIND_FUNC_FAST(js_scene_Camera_screenPointToRay)
static bool js_scene_Camera_screenToWorld(void *nativeObject) // NOLINT(readability-identifier-naming)
{
auto *cobj = reinterpret_cast<cc::scene::Camera *>(nativeObject);
cc::Vec3 ret = cobj->screenToWorld(tempFloatArray.readVec3());
tempFloatArray.writeVec3(ret);
return true;
}
SE_BIND_FUNC_FAST(js_scene_Camera_screenToWorld)
static bool js_scene_Camera_worldToScreen(void *nativeObject) // NOLINT(readability-identifier-naming)
{
auto *cobj = reinterpret_cast<cc::scene::Camera *>(nativeObject);
cc::Vec3 ret = cobj->worldToScreen(tempFloatArray.readVec3());
tempFloatArray.writeVec3(ret);
return true;
}
SE_BIND_FUNC_FAST(js_scene_Camera_worldToScreen)
static bool js_scene_Camera_worldMatrixToScreen(void *nativeObject) // NOLINT(readability-identifier-naming)
{
auto *cobj = reinterpret_cast<cc::scene::Camera *>(nativeObject);
cc::Mat4 worldMatrix = tempFloatArray.readMat4();
cc::Mat4 ret = cobj->worldMatrixToScreen(worldMatrix, static_cast<uint32_t>(tempFloatArray[16]), static_cast<uint32_t>(tempFloatArray[17]));
tempFloatArray.writeMat4(ret);
return true;
}
SE_BIND_FUNC_FAST(js_scene_Camera_worldMatrixToScreen)
static bool js_scene_Node_setTempFloatArray(se::State &s) // NOLINT(readability-identifier-naming)
{
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
uint8_t *buffer = nullptr;
args[0].toObject()->getArrayBufferData(&buffer, nullptr);
tempFloatArray.setData(reinterpret_cast<float *>(buffer));
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_scene_Node_setTempFloatArray)
#define FAST_GET_VALUE(ns, className, method, type) \
static bool js_scene_##className##_##method(void *nativeObject) { \
auto *cobj = reinterpret_cast<ns::className *>(nativeObject); \
auto result = cobj->method(); \
tempFloatArray.write##type(result); \
return true; \
} \
SE_BIND_FUNC_FAST(js_scene_##className##_##method)
#define FAST_GET_CONST_REF(ns, className, method, type) \
static bool js_scene_##className##_##method(void *nativeObject) { \
auto *cobj = reinterpret_cast<ns::className *>(nativeObject); \
const auto &result = cobj->method(); \
tempFloatArray.write##type(result); \
return true; \
} \
SE_BIND_FUNC_FAST(js_scene_##className##_##method)
FAST_GET_VALUE(cc, Node, getRight, Vec3)
FAST_GET_VALUE(cc, Node, getForward, Vec3)
FAST_GET_VALUE(cc, Node, getUp, Vec3)
FAST_GET_VALUE(cc, Node, getWorldRS, Mat4)
FAST_GET_VALUE(cc, Node, getWorldRT, Mat4)
FAST_GET_CONST_REF(cc, Node, getWorldPosition, Vec3)
FAST_GET_CONST_REF(cc, Node, getWorldRotation, Quaternion)
FAST_GET_CONST_REF(cc, Node, getWorldScale, Vec3)
FAST_GET_CONST_REF(cc, Node, getWorldMatrix, Mat4)
FAST_GET_CONST_REF(cc, Node, getEulerAngles, Vec3)
FAST_GET_CONST_REF(cc::scene, Camera, getMatView, Mat4)
FAST_GET_CONST_REF(cc::scene, Camera, getMatProj, Mat4)
FAST_GET_CONST_REF(cc::scene, Camera, getMatProjInv, Mat4)
FAST_GET_CONST_REF(cc::scene, Camera, getMatViewProj, Mat4)
FAST_GET_CONST_REF(cc::scene, Camera, getMatViewProjInv, Mat4)
static bool js_scene_Node_setPosition(void *s) // NOLINT(readability-identifier-naming)
{
auto *cobj = reinterpret_cast<cc::Node *>(s);
auto argc = static_cast<size_t>(tempFloatArray[0]);
if (argc == 2) {
cobj->setPositionInternal(tempFloatArray[1], tempFloatArray[2], true);
} else {
cobj->setPositionInternal(tempFloatArray[1], tempFloatArray[2], tempFloatArray[3], true);
}
return true;
}
SE_BIND_FUNC_FAST(js_scene_Node_setPosition)
static bool js_scene_Node_setRotation(void *s) // NOLINT(readability-identifier-naming)
{
auto *cobj = reinterpret_cast<cc::Node *>(s);
cobj->setRotationInternal(tempFloatArray[0], tempFloatArray[1], tempFloatArray[2], tempFloatArray[3], true);
return true;
}
SE_BIND_FUNC_FAST(js_scene_Node_setRotation)
static bool js_scene_Node_setRotationFromEuler(void *s) // NOLINT(readability-identifier-naming)
{
auto *cobj = reinterpret_cast<cc::Node *>(s);
cobj->setRotationFromEuler(tempFloatArray[0], tempFloatArray[1], tempFloatArray[2]);
return true;
}
SE_BIND_FUNC_FAST(js_scene_Node_setRotationFromEuler)
static bool js_scene_Node_setScale(void *s) // NOLINT(readability-identifier-naming)
{
auto *cobj = reinterpret_cast<cc::Node *>(s);
auto argc = static_cast<size_t>(tempFloatArray[0]);
if (argc == 2) {
cobj->setScaleInternal(tempFloatArray[1], tempFloatArray[2], true);
} else {
cobj->setScaleInternal(tempFloatArray[1], tempFloatArray[2], tempFloatArray[3], true);
}
return true;
}
SE_BIND_FUNC_FAST(js_scene_Node_setScale)
static bool js_scene_Node_setRTS(void *s) // NOLINT(readability-identifier-naming)
{
auto *cobj = reinterpret_cast<cc::Node *>(s);
cc::Quaternion qt;
auto rotSize = static_cast<int32_t>(tempFloatArray[0]);
if (rotSize > 0) {
qt.set(tempFloatArray[1], tempFloatArray[2], tempFloatArray[3], tempFloatArray[4]);
}
auto posSize = static_cast<int32_t>(tempFloatArray[5]);
cc::Vec3 pos;
if (posSize > 0) {
pos.set(tempFloatArray[6], tempFloatArray[7], tempFloatArray[8]);
}
auto scaleSize = static_cast<int32_t>(tempFloatArray[9]);
cc::Vec3 scale;
if (scaleSize > 0) {
scale.set(tempFloatArray[10], tempFloatArray[11], tempFloatArray[12]);
}
cobj->setRTSInternal(rotSize > 0 ? &qt : nullptr, posSize > 0 ? &pos : nullptr, scaleSize > 0 ? &scale : nullptr, true);
return true;
}
SE_BIND_FUNC_FAST(js_scene_Node_setRTS)
static bool js_scene_Node_rotateForJS(void *s) // NOLINT(readability-identifier-naming)
{
auto *cobj = reinterpret_cast<cc::Node *>(s);
auto argc = static_cast<size_t>(tempFloatArray[0]);
if (argc == 4) {
cobj->rotateForJS(tempFloatArray[1], tempFloatArray[2], tempFloatArray[3], tempFloatArray[4]);
} else {
auto size = static_cast<int32_t>(tempFloatArray[5]);
cobj->rotateForJS(tempFloatArray[1], tempFloatArray[2], tempFloatArray[3], tempFloatArray[4], size == 0 ? cc::NodeSpace::LOCAL : static_cast<cc::NodeSpace>(static_cast<int>(std::roundf(tempFloatArray[5]))));
}
const auto &lrot = cobj->getRotation();
tempFloatArray.writeQuaternion(lrot);
return true;
}
SE_BIND_FUNC_FAST(js_scene_Node_rotateForJS)
static bool js_scene_Node_inverseTransformPoint(void *nativeObject) // NOLINT(readability-identifier-naming)
{
auto *cobj = reinterpret_cast<cc::Node *>(nativeObject);
auto p = cobj->inverseTransformPoint(tempFloatArray.readVec3());
tempFloatArray.writeVec3(p);
return true;
}
SE_BIND_FUNC_FAST(js_scene_Node_inverseTransformPoint)
static bool js_scene_Pass_blocks_getter(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = SE_THIS_OBJECT<cc::scene::Pass>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
auto *thiz = s.thisObject();
se::Value blocksVal;
if (thiz->getProperty("_blocks", &blocksVal, true) && blocksVal.isObject() && blocksVal.toObject()->isArray()) {
s.rval() = blocksVal;
return true;
}
const auto &blocks = cobj->getBlocks();
const uint8_t *blockDataBase = cobj->getRootBlock()->getData();
se::HandleObject jsBlocks{se::Object::createArrayObject(blocks.size())};
int32_t i = 0;
for (const auto &block : blocks) {
se::HandleObject jsBlock{
se::Object::createTypedArrayWithBuffer(
se::Object::TypedArrayType::FLOAT32,
cobj->getRootBlock()->getJSArrayBuffer(),
reinterpret_cast<const uint8_t *>(block.data) - blockDataBase,
block.count * 4)};
jsBlocks->setArrayElement(i, se::Value(jsBlock));
++i;
}
thiz->setProperty("_blocks", se::Value(jsBlocks));
s.rval().setObject(jsBlocks);
return true;
}
SE_BIND_PROP_GET(js_scene_Pass_blocks_getter)
static bool js_scene_RenderScene_root_getter(se::State &s) { // NOLINT(readability-identifier-naming)
nativevalue_to_se(cc::Root::getInstance(), s.rval());
return true;
}
SE_BIND_PROP_GET(js_scene_RenderScene_root_getter)
static bool js_Model_setInstancedAttribute(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::scene::Model>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
const auto &args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 2) {
ccstd::string name;
ok &= sevalue_to_native(args[0], &name, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
const auto &val = args[1];
if (val.isObject()) {
if (val.toObject()->isArray()) {
uint32_t len = 0;
val.toObject()->getArrayLength(&len);
se::Value dataVal;
ccstd::array<float, 64> stackData;
float *pData = nullptr;
bool needFree = false;
if (len <= static_cast<uint32_t>(stackData.size())) {
pData = stackData.data();
} else {
pData = static_cast<float *>(CC_MALLOC(len));
needFree = true;
}
for (uint32_t i = 0; i < len; ++i) {
ok = val.toObject()->getArrayElement(i, &dataVal);
CC_ASSERT(ok && dataVal.isNumber());
pData[i] = dataVal.toFloat();
}
cobj->setInstancedAttribute(name, pData, len * sizeof(float));
if (needFree) {
CC_FREE(pData);
}
return true;
}
if (val.toObject()->isTypedArray()) {
se::Object::TypedArrayType type = val.toObject()->getTypedArrayType();
switch (type) {
case se::Object::TypedArrayType::FLOAT32: {
uint8_t *data = nullptr;
size_t byteLength = 0;
if (val.toObject()->getTypedArrayData(&data, &byteLength) && data != nullptr && byteLength > 0) {
cobj->setInstancedAttribute(name, reinterpret_cast<const float *>(data), static_cast<uint32_t>(byteLength));
}
} break;
default:
// FIXME:
CC_ABORT();
break;
}
return true;
}
}
SE_REPORT_ERROR("js_Model_setInstancedAttribute : Error processing arguments");
return false;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 0);
return false;
}
SE_BIND_FUNC(js_Model_setInstancedAttribute)
static bool js_Model_registerListeners(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::scene::Model>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
auto *thiz = s.thisObject();
#define MODEL_DISPATCH_EVENT_TO_JS(eventType, jsFuncName) \
cobj->on<eventType>([=](cc::scene::Model * /*emitter*/, uint32_t stamp) { \
cobj->setCalledFromJS(true); \
se::AutoHandleScope hs; \
se::Value stampVal{stamp}; \
se::ScriptEngine::getInstance()->callFunction(thiz, #jsFuncName, 1, &stampVal); \
})
MODEL_DISPATCH_EVENT_TO_JS(cc::scene::Model::UpdateTransform, updateTransform);
MODEL_DISPATCH_EVENT_TO_JS(cc::scene::Model::UpdateUBO, updateUBOs);
#undef MODEL_DISPATCH_EVENT_TO_JS
cobj->on<cc::scene::Model::UpdateLocalDescriptors>(
[=](cc::scene::Model * /*emitter*/, index_t subModelIndex, cc::gfx::DescriptorSet *descriptorSet) {
cobj->setCalledFromJS(true);
se::AutoHandleScope hs;
ccstd::array<se::Value, 2> args;
nativevalue_to_se(subModelIndex, args[0]);
nativevalue_to_se(descriptorSet, args[1]);
se::ScriptEngine::getInstance()->callFunction(thiz, "_updateLocalDescriptors", static_cast<uint32_t>(args.size()), args.data());
});
cobj->on<cc::scene::Model::UpdateLocalSHDescriptor>([=](cc::scene::Model * /*emitter*/, index_t subModelIndex, cc::gfx::DescriptorSet *descriptorSet) {
cobj->setCalledFromJS(true);
se::AutoHandleScope hs;
ccstd::array<se::Value, 2> args;
nativevalue_to_se(subModelIndex, args[0]);
nativevalue_to_se(descriptorSet, args[1]);
se::ScriptEngine::getInstance()->callFunction(thiz, "_updateLocalSHDescriptors", static_cast<uint32_t>(args.size()), args.data());
});
cobj->on<cc::scene::Model::UpdateWorldBound>([=](cc::scene::Model * /*emitter*/, index_t subModelIndex, cc::gfx::DescriptorSet *descriptorSet) {
cobj->setCalledFromJS(true);
se::AutoHandleScope hs;
ccstd::array<se::Value, 2> args;
nativevalue_to_se(subModelIndex, args[0]);
nativevalue_to_se(descriptorSet, args[1]);
se::ScriptEngine::getInstance()->callFunction(thiz, "_updateWorldBoundDescriptors", static_cast<uint32_t>(args.size()), args.data());
});
cobj->on<cc::scene::Model::UpdateInstancedAttributes>([=](cc::scene::Model * /*emitter*/, const ccstd::vector<cc::gfx::Attribute> &attributes, cc::scene::SubModel *subModel) {
cobj->setCalledFromJS(true);
se::AutoHandleScope hs;
ccstd::array<se::Value, 2> args;
nativevalue_to_se(attributes, args[0]);
nativevalue_to_se(subModel, args[1]);
se::ScriptEngine::getInstance()->callFunction(thiz, "_updateInstancedAttributes", static_cast<uint32_t>(args.size()), args.data());
});
cobj->on<cc::scene::Model::GetMacroPatches>(
[=](cc::scene::Model * /*emitter*/, index_t subModelIndex, ccstd::vector<cc::scene::IMacroPatch> *pPatches) {
cobj->setCalledFromJS(true);
se::AutoHandleScope hs;
se::Value rval;
ccstd::array<se::Value, 1> args;
nativevalue_to_se(subModelIndex, args[0]);
bool ok = se::ScriptEngine::getInstance()->callFunction(thiz, "getMacroPatches", static_cast<uint32_t>(args.size()), args.data(), &rval);
if (ok) {
sevalue_to_native(rval, pPatches);
}
});
return true;
}
SE_BIND_FUNC(js_Model_registerListeners) // NOLINT(readability-identifier-naming)
static bool js_assets_MaterialInstance_registerListeners(se::State &s) // NOLINT(readability-identifier-naming)
{
auto *cobj = SE_THIS_OBJECT<cc::MaterialInstance>(s);
SE_PRECONDITION2(cobj, false, "Invalid Native Object");
cobj->setRebuildPSOCallback([](index_t /*index*/, cc::Material *material) {
se::AutoHandleScope hs;
se::Value matVal;
bool ok = nativevalue_to_se(material, matVal);
if (!ok) {
return;
}
se::ScriptEngine::getInstance()->callFunction(matVal.toObject(), "_onRebuildPSO", 0, nullptr);
});
return true;
}
SE_BIND_FUNC(js_assets_MaterialInstance_registerListeners) // NOLINT(readability-identifier-naming)
bool register_all_scene_manual(se::Object *obj) // NOLINT(readability-identifier-naming)
{
// Get the ns
se::Value nsVal;
if (!obj->getProperty("ns", &nsVal)) {
se::HandleObject jsobj(se::Object::createPlainObject());
nsVal.setObject(jsobj);
obj->setProperty("ns", nsVal);
}
__jsb_cc_Root_proto->defineFunction("_registerListeners", _SE(js_root_registerListeners));
__jsb_cc_scene_Camera_proto->defineFunction("screenPointToRay", _SE(js_scene_Camera_screenPointToRay));
__jsb_cc_scene_Camera_proto->defineFunction("screenToWorld", _SE(js_scene_Camera_screenToWorld));
__jsb_cc_scene_Camera_proto->defineFunction("worldToScreen", _SE(js_scene_Camera_worldToScreen));
__jsb_cc_scene_Camera_proto->defineFunction("worldMatrixToScreen", _SE(js_scene_Camera_worldMatrixToScreen));
__jsb_cc_scene_Camera_proto->defineFunction("getMatView", _SE(js_scene_Camera_getMatView));
__jsb_cc_scene_Camera_proto->defineFunction("getMatProj", _SE(js_scene_Camera_getMatProj));
__jsb_cc_scene_Camera_proto->defineFunction("getMatProjInv", _SE(js_scene_Camera_getMatProjInv));
__jsb_cc_scene_Camera_proto->defineFunction("getMatViewProj", _SE(js_scene_Camera_getMatViewProj));
__jsb_cc_scene_Camera_proto->defineFunction("getMatViewProjInv", _SE(js_scene_Camera_getMatViewProjInv));
// Node TS wrapper will invoke this function to let native object listen some events.
__jsb_cc_Node_proto->defineFunction("_initAndReturnSharedBuffer", _SE(js_cc_Node_initAndReturnSharedBuffer));
__jsb_cc_Node_proto->defineFunction("_registerOnTransformChanged", _SE(js_scene_Node_registerOnTransformChanged));
__jsb_cc_Node_proto->defineFunction("_registerOnParentChanged", _SE(js_scene_Node_registerOnParentChanged));
__jsb_cc_Node_proto->defineFunction("_registerOnMobilityChanged", _SE(js_scene_Node_registerOnMobilityChanged));
__jsb_cc_Node_proto->defineFunction("_registerOnLayerChanged", _SE(js_scene_Node_registerOnLayerChanged));
__jsb_cc_Node_proto->defineFunction("_registerOnSiblingOrderChanged", _SE(js_scene_Node_registerOnSiblingOrderChanged));
__jsb_cc_Node_proto->defineFunction("_registerOnLightProbeBakingChanged", _SE(js_scene_Node_registerOnLightProbeBakingChanged));
se::Value jsbVal;
obj->getProperty("jsb", &jsbVal);
se::Value nodeVal;
jsbVal.toObject()->getProperty("Node", &nodeVal);
nodeVal.toObject()->defineFunction("_setTempFloatArray", _SE(js_scene_Node_setTempFloatArray));
__jsb_cc_Node_proto->defineFunction("_setPosition", _SE(js_scene_Node_setPosition));
__jsb_cc_Node_proto->defineFunction("_setScale", _SE(js_scene_Node_setScale));
__jsb_cc_Node_proto->defineFunction("_setRotation", _SE(js_scene_Node_setRotation));
__jsb_cc_Node_proto->defineFunction("_setRotationFromEuler", _SE(js_scene_Node_setRotationFromEuler));
__jsb_cc_Node_proto->defineFunction("_rotateForJS", _SE(js_scene_Node_rotateForJS));
__jsb_cc_Node_proto->defineFunction("_getEulerAngles", _SE(js_scene_Node_getEulerAngles));
__jsb_cc_Node_proto->defineFunction("_getForward", _SE(js_scene_Node_getForward));
__jsb_cc_Node_proto->defineFunction("_getUp", _SE(js_scene_Node_getUp));
__jsb_cc_Node_proto->defineFunction("_getRight", _SE(js_scene_Node_getRight));
__jsb_cc_Node_proto->defineFunction("_getWorldPosition", _SE(js_scene_Node_getWorldPosition));
__jsb_cc_Node_proto->defineFunction("_getWorldRotation", _SE(js_scene_Node_getWorldRotation));
__jsb_cc_Node_proto->defineFunction("_getWorldScale", _SE(js_scene_Node_getWorldScale));
__jsb_cc_Node_proto->defineFunction("_getWorldMatrix", _SE(js_scene_Node_getWorldMatrix));
__jsb_cc_Node_proto->defineFunction("_getWorldRS", _SE(js_scene_Node_getWorldRS));
__jsb_cc_Node_proto->defineFunction("_getWorldRT", _SE(js_scene_Node_getWorldRT));
__jsb_cc_Node_proto->defineFunction("_setRTS", _SE(js_scene_Node_setRTS));
__jsb_cc_Node_proto->defineFunction("_inverseTransformPoint", _SE(js_scene_Node_inverseTransformPoint));
__jsb_cc_scene_Pass_proto->defineProperty("blocks", _SE(js_scene_Pass_blocks_getter), nullptr);
__jsb_cc_scene_RenderScene_proto->defineProperty("root", _SE(js_scene_RenderScene_root_getter), nullptr);
__jsb_cc_scene_Model_proto->defineFunction("_setInstancedAttribute", _SE(js_Model_setInstancedAttribute));
__jsb_cc_scene_Model_proto->defineFunction("_registerListeners", _SE(js_Model_registerListeners));
__jsb_cc_MaterialInstance_proto->defineFunction("_registerListeners", _SE(js_assets_MaterialInstance_registerListeners));
return true;
}

View File

@@ -0,0 +1,33 @@
/****************************************************************************
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 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.
****************************************************************************/
#pragma once
#include "cocos/bindings/jswrapper/SeApi.h"
namespace se {
class Object;
}
bool register_all_scene_manual(se::Object *obj);

View File

@@ -0,0 +1,353 @@
/****************************************************************************
Copyright (c) 2017-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 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 "jsb_socketio.h"
#include "application/ApplicationManager.h"
#include "base/UTF8.h"
#include "cocos/base/DeferredReleasePool.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "cocos/network/SocketIO.h"
// using namespace cc;
// using namespace cc::network;
se::Class *__jsb_SocketIO_class = nullptr; // NOLINT
class JSB_SocketIODelegate : public cc::RefCounted, public cc::network::SocketIO::SIODelegate {
public:
// c++11 map to callbacks
using JSB_SIOCallbackRegistry = ccstd::unordered_map<ccstd::string /* eventName */, se::ValueArray /* 0:callbackFunc, 1:target */>;
JSB_SocketIODelegate() = default;
~JSB_SocketIODelegate() override {
CC_LOG_INFO("In the destructor of JSB_SocketIODelegate(%p)", this);
}
void onConnect(cc::network::SIOClient * /*client*/) override {
}
void onMessage(cc::network::SIOClient * /*client*/, const ccstd::string & /*data*/) override {
}
void onClose(cc::network::SIOClient *client) override { // NOLINT
CC_LOG_DEBUG("JSB SocketIO::SIODelegate->onClose method called from native");
this->fireEventToScript(client, "disconnect", "");
se::NativePtrToObjectMap::forEach(client, [](se::Object *obj) {
obj->unroot();
});
if (getRefCount() == 1) {
cc::DeferredReleasePool::add(this);
} else {
release();
}
}
void onError(cc::network::SIOClient *client, const ccstd::string &data) override { // NOLINT
CC_LOG_DEBUG("JSB SocketIO::SIODelegate->onError method called from native with data: %s", data.c_str());
this->fireEventToScript(client, "error", data);
se::NativePtrToObjectMap::forEach(client, [](se::Object *obj) {
obj->unroot();
});
}
void fireEventToScript(cc::network::SIOClient *client, const ccstd::string &eventName, const ccstd::string &data) override { // NOLINT
CC_LOG_DEBUG("JSB SocketIO::SIODelegate->fireEventToScript method called from native with name '%s' data: %s", eventName.c_str(), data.c_str());
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
if (!CC_CURRENT_APPLICATION()) {
return;
}
if (!se::NativePtrToObjectMap::contains(client)) { // IDEA: client probably be a new value with the same address as the old one, it may cause undefined result.
return;
}
se::Value dataVal;
if (data.empty()) {
dataVal.setNull();
} else {
dataVal.setString(data);
}
auto it = _eventRegistry.find(eventName);
if (it != _eventRegistry.end()) {
const se::ValueArray &cbStruct = it->second;
CC_ASSERT(cbStruct.size() == 2);
const se::Value &callback = cbStruct[0];
const se::Value &target = cbStruct[1];
if (callback.isObject() && callback.toObject()->isFunction() && target.isObject()) {
se::ValueArray args;
args.push_back(dataVal);
callback.toObject()->call(args, target.toObject());
}
}
if (eventName == "disconnect") {
CC_LOG_DEBUG("disconnect ... "); // IDEA:
}
}
void addEvent(const ccstd::string &eventName, const se::Value &callback, const se::Value &target) {
CC_ASSERT(callback.isObject() && callback.toObject()->isFunction());
CC_ASSERT(target.isObject());
_eventRegistry[eventName].clear();
_eventRegistry[eventName].push_back(callback);
_eventRegistry[eventName].push_back(target);
target.toObject()->attachObject(callback.toObject());
}
private:
JSB_SIOCallbackRegistry _eventRegistry;
};
static bool SocketIO_finalize(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::network::SIOClient *>(s.nativeThisObject());
CC_LOG_INFO("jsbindings: finalizing JS object %p (SocketIO)", cobj);
cobj->disconnect();
auto *delegate = static_cast<JSB_SocketIODelegate *>(cobj->getDelegate());
if (delegate->getRefCount() == 1) {
cc::DeferredReleasePool::add(delegate);
} else {
delegate->release();
}
return true;
}
SE_BIND_FINALIZE_FUNC(SocketIO_finalize) // NOLINT(readability-identifier-naming)
static bool SocketIO_prop_getTag(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::network::SIOClient *>(s.nativeThisObject());
s.rval().setString(cobj->getTag());
return true;
}
SE_BIND_PROP_GET(SocketIO_prop_getTag) // NOLINT(readability-identifier-naming)
static bool SocketIO_prop_setTag(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::network::SIOClient *>(s.nativeThisObject());
cobj->setTag(s.args()[0].toString().c_str());
return true;
}
SE_BIND_PROP_SET(SocketIO_prop_setTag) // NOLINT(readability-identifier-naming)
static bool SocketIO_send(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
auto *cobj = static_cast<cc::network::SIOClient *>(s.nativeThisObject());
if (argc == 1) {
ccstd::string payload;
bool ok = sevalue_to_native(args[0], &payload);
SE_PRECONDITION2(ok, false, "Converting payload failed!");
cobj->send(payload);
return true;
}
SE_REPORT_ERROR("Wrong number of arguments: %d, expected: %d", argc, 1);
return false;
}
SE_BIND_FUNC(SocketIO_send) // NOLINT(readability-identifier-naming)
static bool SocketIO_emit(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
auto *cobj = static_cast<cc::network::SIOClient *>(s.nativeThisObject());
if (argc >= 1) {
bool ok = false;
ccstd::string eventName;
ok = sevalue_to_native(args[0], &eventName);
SE_PRECONDITION2(ok, false, "Converting eventName failed!");
ccstd::string payload;
if (argc >= 2) {
const auto &arg1 = args[1];
// Add this check to make it compatible with old version.
// jsval_to_std_string in v1.6 returns empty string if arg1 is null or undefined
// while seval_to_std_string since 1.7.2 follows JS standard to return "null" or "undefined".
// Therefore, we need a workaround to make it be compatible with versions lower than v1.7.
if (!arg1.isNullOrUndefined()) {
ok = sevalue_to_native(arg1, &payload);
SE_PRECONDITION2(ok, false, "Converting payload failed!");
}
}
cobj->emit(eventName, payload);
return true;
}
SE_REPORT_ERROR("Wrong number of arguments: %d, expected: %d", argc, 2);
return false;
}
SE_BIND_FUNC(SocketIO_emit) // NOLINT(readability-identifier-naming)
static bool SocketIO_disconnect(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
auto *cobj = static_cast<cc::network::SIOClient *>(s.nativeThisObject());
if (argc == 0) {
cobj->disconnect();
return true;
}
SE_REPORT_ERROR("Wrong number of arguments: %d, expected: %d", argc, 0);
return false;
}
SE_BIND_FUNC(SocketIO_disconnect) // NOLINT(readability-identifier-naming)
static bool SocketIO_on(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
auto *cobj = static_cast<cc::network::SIOClient *>(s.nativeThisObject());
if (argc == 2) {
bool ok = false;
ccstd::string eventName;
ok = sevalue_to_native(args[0], &eventName);
SE_PRECONDITION2(ok, false, "Converting eventName failed!");
CC_LOG_DEBUG("JSB SocketIO eventName to: '%s'", eventName.c_str());
(static_cast<JSB_SocketIODelegate *>(cobj->getDelegate()))->addEvent(eventName, args[1], se::Value(s.thisObject()));
return true;
}
SE_REPORT_ERROR("Wrong number of arguments: %d, expected: %d", argc, 2);
return false;
}
SE_BIND_FUNC(SocketIO_on) // NOLINT(readability-identifier-naming)
// static
static bool SocketIO_connect(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
CC_LOG_DEBUG("JSB SocketIO.connect method called");
if (argc >= 1 && argc <= 3) {
ccstd::string url;
ccstd::string caFilePath;
bool ok = false;
ok = sevalue_to_native(args[0], &url);
SE_PRECONDITION2(ok, false, "Error processing arguments");
if (argc == 2) {
if (args[1].isObject()) {
// Just ignore the option argument
} else if (args[1].isString()) {
// Assume it's CA root file path
ok = sevalue_to_native(args[1], &caFilePath);
SE_PRECONDITION2(ok, false, "Error processing arguments");
}
}
if (argc == 3) {
// Just ignore the option argument
if (args[2].isString()) {
// Assume it's CA root file path
ok = sevalue_to_native(args[2], &caFilePath);
SE_PRECONDITION2(ok, false, "Error processing arguments");
}
}
auto *siodelegate = ccnew JSB_SocketIODelegate();
CC_LOG_DEBUG("Calling native SocketIO.connect method");
cc::network::SIOClient *ret = cc::network::SocketIO::connect(url, *siodelegate, caFilePath);
if (ret != nullptr) {
ret->addRef();
siodelegate->addRef();
se::Object *obj = se::Object::createObjectWithClass(__jsb_SocketIO_class);
obj->setPrivateData(ret);
s.rval().setObject(obj);
obj->root();
return true;
}
siodelegate->release();
SE_REPORT_ERROR("SocketIO.connect return nullptr!");
return false;
}
SE_REPORT_ERROR("JSB SocketIO.connect: Wrong number of arguments");
return false;
}
SE_BIND_FUNC(SocketIO_connect) // NOLINT(readability-identifier-naming)
// static
static bool SocketIO_close(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 0) {
return true;
}
SE_REPORT_ERROR("Wrong number of arguments: %d, expected: %d", argc, 0);
return false;
}
SE_BIND_FUNC(SocketIO_close) // NOLINT(readability-identifier-naming)
bool register_all_socketio(se::Object *global) {
se::Value nsVal;
if (!global->getProperty("jsb", &nsVal, true)) {
se::HandleObject jsobj(se::Object::createPlainObject());
nsVal.setObject(jsobj);
global->setProperty("jsb", nsVal);
}
se::Object *ns = nsVal.toObject();
se::Class *cls = se::Class::create("SocketIO", ns, nullptr, nullptr);
cls->defineFinalizeFunction(_SE(SocketIO_finalize));
cls->defineProperty("tag", _SE(SocketIO_prop_getTag), _SE(SocketIO_prop_setTag));
cls->defineFunction("send", _SE(SocketIO_send));
cls->defineFunction("emit", _SE(SocketIO_emit));
cls->defineFunction("disconnect", _SE(SocketIO_disconnect));
cls->defineFunction("on", _SE(SocketIO_on));
cls->install();
JSBClassType::registerClass<cc::network::SocketIO>(cls);
se::Value ctorVal;
ns->getProperty("SocketIO", &ctorVal);
ctorVal.toObject()->defineFunction("connect", _SE(SocketIO_connect));
ctorVal.toObject()->defineFunction("close", _SE(SocketIO_close));
__jsb_SocketIO_class = cls;
se::ScriptEngine::getInstance()->clearException();
return true;
}

View File

@@ -0,0 +1,31 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
#pragma once
namespace se {
class Object;
}
bool register_all_socketio(se::Object *obj);

View File

@@ -0,0 +1,609 @@
/****************************************************************************
Copyright (c) 2020-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 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 "jsb_spine_manual.h"
#include "base/Data.h"
#include "base/memory/Memory.h"
#include "bindings/auto/jsb_spine_auto.h"
#include "bindings/jswrapper/SeApi.h"
#include "bindings/manual/jsb_conversions.h"
#include "bindings/manual/jsb_global.h"
#include "bindings/manual/jsb_helper.h"
#include "editor-support/spine-creator-support/spine-cocos2dx.h"
#include "editor-support/spine/spine.h"
#include "middleware-adapter.h"
#include "platform/FileUtils.h"
#include "spine-creator-support/SkeletonDataMgr.h"
#include "spine-creator-support/SkeletonRenderer.h"
#include "spine-creator-support/spine-cocos2dx.h"
#include "spine-creator-support/Vector2.h"
using namespace cc;
static spine::Cocos2dTextureLoader textureLoader;
static cc::RefMap<ccstd::string, middleware::Texture2D *> *_preloadedAtlasTextures = nullptr;
static middleware::Texture2D *_getPreloadedAtlasTexture(const char *path) {
CC_ASSERT(_preloadedAtlasTextures);
auto it = _preloadedAtlasTextures->find(path);
return it != _preloadedAtlasTextures->end() ? it->second : nullptr;
}
static bool js_register_spine_initSkeletonData(se::State &s) {
const auto &args = s.args();
int argc = (int)args.size();
if (argc != 5) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", argc, 5);
return false;
}
bool ok = false;
ccstd::string uuid;
ok = sevalue_to_native(args[0], &uuid);
SE_PRECONDITION2(ok, false, "Invalid uuid content!");
auto mgr = spine::SkeletonDataMgr::getInstance();
bool hasSkeletonData = mgr->hasSkeletonData(uuid);
if (hasSkeletonData) {
spine::SkeletonData *skeletonData = mgr->retainByUUID(uuid);
native_ptr_to_seval<spine::SkeletonData>(skeletonData, &s.rval());
return true;
}
ccstd::string skeletonDataFile;
ok = sevalue_to_native(args[1], &skeletonDataFile);
SE_PRECONDITION2(ok, false, "Invalid json path!");
ccstd::string atlasText;
ok = sevalue_to_native(args[2], &atlasText);
SE_PRECONDITION2(ok, false, "Invalid atlas content!");
cc::RefMap<ccstd::string, middleware::Texture2D *> textures;
ok = seval_to_Map_string_key(args[3], &textures);
SE_PRECONDITION2(ok, false, "Invalid textures!");
float scale = 1.0f;
ok = sevalue_to_native(args[4], &scale);
SE_PRECONDITION2(ok, false, "Invalid scale!");
// create atlas from preloaded texture
_preloadedAtlasTextures = &textures;
spine::spAtlasPage_setCustomTextureLoader(_getPreloadedAtlasTexture);
spine::Atlas *atlas = ccnew_placement(__FILE__, __LINE__) spine::Atlas(atlasText.c_str(), (int)atlasText.size(), "", &textureLoader);
_preloadedAtlasTextures = nullptr;
spine::spAtlasPage_setCustomTextureLoader(nullptr);
spine::AttachmentLoader *attachmentLoader = ccnew_placement(__FILE__, __LINE__) spine::Cocos2dAtlasAttachmentLoader(atlas);
spine::SkeletonData *skeletonData = nullptr;
std::size_t length = skeletonDataFile.length();
auto binPos = skeletonDataFile.find(".skel", length - 5);
if (binPos == ccstd::string::npos) binPos = skeletonDataFile.find(".bin", length - 4);
if (binPos != ccstd::string::npos) {
auto fileUtils = cc::FileUtils::getInstance();
if (fileUtils->isFileExist(skeletonDataFile)) {
cc::Data cocos2dData;
const auto fullpath = fileUtils->fullPathForFilename(skeletonDataFile);
fileUtils->getContents(fullpath, &cocos2dData);
spine::SkeletonBinary binary(attachmentLoader);
binary.setScale(scale);
skeletonData = binary.readSkeletonData(cocos2dData.getBytes(), (int)cocos2dData.getSize());
CC_ASSERT(skeletonData); // Can use binary.getError() to get error message.
}
} else {
spine::SkeletonJson json(attachmentLoader);
json.setScale(scale);
skeletonData = json.readSkeletonData(skeletonDataFile.c_str());
CC_ASSERT(skeletonData); // Can use json.getError() to get error message.
}
if (skeletonData) {
ccstd::vector<int> texturesIndex;
for (auto it = textures.begin(); it != textures.end(); it++) {
texturesIndex.push_back(it->second->getRealTextureIndex());
}
mgr->setSkeletonData(uuid, skeletonData, atlas, attachmentLoader, texturesIndex);
native_ptr_to_seval<spine::SkeletonData>(skeletonData, &s.rval());
} else {
if (atlas) {
delete atlas;
atlas = nullptr;
}
if (attachmentLoader) {
delete attachmentLoader;
attachmentLoader = nullptr;
}
}
return true;
}
SE_BIND_FUNC(js_register_spine_initSkeletonData)
static bool js_register_spine_disposeSkeletonData(se::State &s) {
const auto &args = s.args();
int argc = (int)args.size();
if (argc != 1) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", argc, 5);
return false;
}
bool ok = false;
ccstd::string uuid;
ok = sevalue_to_native(args[0], &uuid);
SE_PRECONDITION2(ok, false, "Invalid uuid content!");
auto mgr = spine::SkeletonDataMgr::getInstance();
bool hasSkeletonData = mgr->hasSkeletonData(uuid);
if (!hasSkeletonData) return true;
mgr->releaseByUUID(uuid);
return true;
}
SE_BIND_FUNC(js_register_spine_disposeSkeletonData)
static bool js_register_spine_initSkeletonRenderer(se::State &s) {
// renderer, jsonPath, atlasText, textures, scale
const auto &args = s.args();
int argc = (int)args.size();
if (argc != 2) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", argc, 5);
return false;
}
bool ok = false;
spine::SkeletonRenderer *node = nullptr;
ok = seval_to_native_ptr(args[0], &node);
SE_PRECONDITION2(ok, false, "Converting SpineRenderer failed!");
ccstd::string uuid;
ok = sevalue_to_native(args[1], &uuid);
SE_PRECONDITION2(ok, false, "Invalid uuid content!");
auto mgr = spine::SkeletonDataMgr::getInstance();
bool hasSkeletonData = mgr->hasSkeletonData(uuid);
if (hasSkeletonData) {
node->initWithUUID(uuid);
}
return true;
}
SE_BIND_FUNC(js_register_spine_initSkeletonRenderer)
static bool js_register_spine_retainSkeletonData(se::State &s) {
const auto &args = s.args();
int argc = (int)args.size();
if (argc != 1) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", argc, 1);
return false;
}
bool ok = false;
ccstd::string uuid;
ok = sevalue_to_native(args[0], &uuid);
SE_PRECONDITION2(ok, false, "Invalid uuid content!");
auto mgr = spine::SkeletonDataMgr::getInstance();
bool hasSkeletonData = mgr->hasSkeletonData(uuid);
if (hasSkeletonData) {
spine::SkeletonData *skeletonData = mgr->retainByUUID(uuid);
native_ptr_to_seval<spine::SkeletonData>(skeletonData, &s.rval());
}
return true;
}
SE_BIND_FUNC(js_register_spine_retainSkeletonData)
static bool js_VertexAttachment_computeWorldVertices(se::State &s) {
const auto &args = s.args();
spine::VertexAttachment *vertexAttachment = SE_THIS_OBJECT<spine::VertexAttachment>(s);
if (nullptr == vertexAttachment) return true;
spine::Slot *slot = nullptr;
size_t start = 0, count = 0, offset = 0, stride = 0;
se::Value worldVerticesVal;
bool ok = false;
ok = sevalue_to_native(args[0], &slot, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing slot");
ok = sevalue_to_native(args[1], &start, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing start");
ok = sevalue_to_native(args[2], &worldVerticesVal, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing vertices");
ok = sevalue_to_native(args[3], &count, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing count");
ok = sevalue_to_native(args[4], &offset, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing offset");
ok = sevalue_to_native(args[5], &stride, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing stride");
if (worldVerticesVal.toObject()->isTypedArray()) {
uint8_t* ptr = nullptr;
size_t len = 0;
worldVerticesVal.toObject()->getTypedArrayData(&ptr, &len);
vertexAttachment->computeWorldVertices(*slot, start, count, reinterpret_cast<float*>(ptr), offset, stride);
} else if (worldVerticesVal.toObject()->isArray()) {
spine::Vector<float> worldVertices;
worldVertices.ensureCapacity(count);
vertexAttachment->computeWorldVertices(*slot, start, count, worldVertices, 0);
int tCount = offset + (count >> 1) * stride;
for (size_t i = offset, t = 0; i < tCount; i += stride, t += 2) {
worldVerticesVal.toObject()->setArrayElement(i, se::Value(worldVertices[t]));
worldVerticesVal.toObject()->setArrayElement(i + 1, se::Value(worldVertices[t + 1]));
}
}
return true;
}
SE_BIND_FUNC(js_VertexAttachment_computeWorldVertices)
static bool js_RegionAttachment_computeWorldVertices(se::State &s) {
const auto &args = s.args();
spine::RegionAttachment *regionAttachment = SE_THIS_OBJECT<spine::RegionAttachment>(s);
if (nullptr == regionAttachment) return true;
spine::Bone *bone = nullptr;
size_t offset = 0, stride = 0;
se::Value worldVerticesVal;
bool ok = false;
ok = sevalue_to_native(args[0], &bone, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
ok = sevalue_to_native(args[1], &worldVerticesVal, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
ok = sevalue_to_native(args[2], &offset, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
ok = sevalue_to_native(args[3], &stride, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
if (worldVerticesVal.toObject()->isTypedArray()) {
uint8_t* ptr = nullptr;
size_t len = 0;
worldVerticesVal.toObject()->getTypedArrayData(&ptr, &len);
regionAttachment->computeWorldVertices(*bone, reinterpret_cast<float*>(ptr), offset, stride);
} else if (worldVerticesVal.toObject()->isArray()) {
spine::Vector<float> worldVertices;
int count = 8;
worldVertices.ensureCapacity(count);
regionAttachment->computeWorldVertices(*bone, worldVertices, 0);
int curr = offset;
worldVerticesVal.toObject()->setArrayElement(curr, se::Value(worldVertices[0]));
worldVerticesVal.toObject()->setArrayElement(curr + 1, se::Value(worldVertices[1]));
curr += stride;
worldVerticesVal.toObject()->setArrayElement(curr, se::Value(worldVertices[2]));
worldVerticesVal.toObject()->setArrayElement(curr + 1, se::Value(worldVertices[3]));
curr += stride;
worldVerticesVal.toObject()->setArrayElement(curr, se::Value(worldVertices[4]));
worldVerticesVal.toObject()->setArrayElement(curr + 1, se::Value(worldVertices[5]));
curr += stride;
worldVerticesVal.toObject()->setArrayElement(curr, se::Value(worldVertices[6]));
worldVerticesVal.toObject()->setArrayElement(curr + 1, se::Value(worldVertices[7]));
}
return true;
}
SE_BIND_FUNC(js_RegionAttachment_computeWorldVertices)
static bool js_Skeleton_getBounds(se::State &s) {
const auto &args = s.args();
spine::Skeleton* skeleton = SE_THIS_OBJECT<spine::Skeleton>(s);
if (nullptr == skeleton) return true;
se::Value temp;
bool ok = false;
ok = sevalue_to_native(args[2], &temp, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
{
float offx = 0.F, offy = 0.F, sizex = 0.F, sizey = 0.F;
spine::Vector<float> outVertexBuffer;
skeleton->getBounds(offx, offy, sizex, sizey, outVertexBuffer);
args[0].toObject()->setProperty("x", se::Value(offx));
args[0].toObject()->setProperty("y", se::Value(offy));
args[1].toObject()->setProperty("x", se::Value(sizex));
args[1].toObject()->setProperty("y", se::Value(sizey));
if (temp.isObject()) {
for (int i = 0; i < outVertexBuffer.size(); ++i) {
temp.toObject()->setArrayElement(i, se::Value(outVertexBuffer[i]));
}
}
}
return true;
}
SE_BIND_FUNC(js_Skeleton_getBounds)
static bool js_Bone_worldToLocal(se::State &s) {
const auto &args = s.args();
spine::Bone* bone = SE_THIS_OBJECT<spine::Bone>(s);
if (nullptr == bone) return true;
spine::Vector2 world(0, 0);
bool ok = false;
ok = sevalue_to_native(args[0], &world, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
float outX = 0.F, outY = 0.F;
bone->worldToLocal(world.x, world.y, outX, outY);
spine::Vector2 outNative(outX, outY);
se::Value ret;
nativevalue_to_se(outNative, ret, s.thisObject());
s.rval().setObject(ret.toObject());
return true;
}
SE_BIND_FUNC(js_Bone_worldToLocal)
static bool js_Bone_localToWorld(se::State &s) {
const auto &args = s.args();
spine::Bone* bone = SE_THIS_OBJECT<spine::Bone>(s);
if (nullptr == bone) return true;
spine::Vector2 local(0, 0);
bool ok = false;
ok = sevalue_to_native(args[0], &local, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
float outX = 0.F, outY = 0.F;
bone->localToWorld(local.x, local.y, outX, outY);
spine::Vector2 outNative(outX, outY);
se::Value ret;
nativevalue_to_se(outNative, ret, s.thisObject());
s.rval().setObject(ret.toObject());
return true;
}
SE_BIND_FUNC(js_Bone_localToWorld)
static bool js_PointAttachment_computeWorldPosition(se::State &s) {
const auto &args = s.args();
spine::PointAttachment* pointAttachment = SE_THIS_OBJECT<spine::PointAttachment>(s);
if (nullptr == pointAttachment) return true;
spine::Bone* bone = nullptr;
bool ok = false;
ok = sevalue_to_native(args[0], &bone, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
float outX = 0.F, outY = 0.F;
pointAttachment->computeWorldPosition(*bone, outX, outY);
spine::Vector2 outNative(outX, outY);
se::Value ret;
nativevalue_to_se(outNative, ret, s.thisObject());
s.rval().setObject(ret.toObject());
return true;
}
SE_BIND_FUNC(js_PointAttachment_computeWorldPosition)
static bool js_Skin_findAttachmentsForSlot(se::State &s) {
const auto &args = s.args();
spine::Skin* skin = SE_THIS_OBJECT<spine::Skin>(s);
if (nullptr == skin) return true;
size_t slotIndex = 0;
se::Value attachmentsVal;
bool ok = false;
ok = sevalue_to_native(args[0], &slotIndex, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
attachmentsVal = args[1];
ok = attachmentsVal.isObject();
SE_PRECONDITION2(ok, false, "Error processing arguments");
spine::Skin::AttachmentMap::Entries entries = skin->getAttachments();
uint32_t index = 0;
while (entries.hasNext()) {
spine::Skin::AttachmentMap::Entry &entry = entries.next();
if (entry._slotIndex == slotIndex) {
se::Value entryVal;
ok = nativevalue_to_se(&entry, entryVal);
SE_PRECONDITION2(ok, false, "Error processing arguments");
attachmentsVal.toObject()->setArrayElement(index++, entryVal);
}
}
return true;
}
SE_BIND_FUNC(js_Skin_findAttachmentsForSlot)
static bool js_VertexEffect_transform(se::State &s) {
const auto &args = s.args();
spine::VertexEffect* effect = SE_THIS_OBJECT<spine::VertexEffect>(s);
if (nullptr == effect) return true;
float outX = 0.F, outY = 0.F;
effect->transform(outX, outY);
args[0].toObject()->setProperty("x", se::Value(outX));
args[0].toObject()->setProperty("y", se::Value(outY));
return true;
}
SE_BIND_FUNC(js_VertexEffect_transform)
static bool js_SwirlVertexEffect_transform(se::State &s) {
const auto &args = s.args();
spine::SwirlVertexEffect* effect = SE_THIS_OBJECT<spine::SwirlVertexEffect>(s);
if (nullptr == effect) return true;
float outX = 0.F, outY = 0.F;
effect->transform(outX, outY);
args[0].toObject()->setProperty("x", se::Value(outX));
args[0].toObject()->setProperty("y", se::Value(outY));
return true;
}
SE_BIND_FUNC(js_SwirlVertexEffect_transform)
static bool js_JitterVertexEffect_transform(se::State &s) {
const auto &args = s.args();
spine::JitterVertexEffect* effect = SE_THIS_OBJECT<spine::JitterVertexEffect>(s);
if (nullptr == effect) return true;
float outX = 0.F, outY = 0.F;
effect->transform(outX, outY);
args[0].toObject()->setProperty("x", se::Value(outX));
args[0].toObject()->setProperty("y", se::Value(outY));
return true;
}
SE_BIND_FUNC(js_JitterVertexEffect_transform)
static bool js_spine_Skin_getAttachments(se::State& s) {
CC_UNUSED bool ok = true;
const auto& args = s.args();
size_t argc = args.size();
spine::Skin *skin = (spine::Skin *) NULL ;
if(argc != 0) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 0);
return false;
}
skin = SE_THIS_OBJECT<spine::Skin>(s);
if (nullptr == skin) return true;
spine::Skin::AttachmentMap::Entries attachments = skin->getAttachments();
std::vector<se::Value> entries;
while (attachments.hasNext()) {
spine::Skin::AttachmentMap::Entry &entry = attachments.next();
se::Value entryVal;
ok = nativevalue_to_se(&entry, entryVal);
SE_PRECONDITION2(ok, false, "Error processing arguments");
entries.push_back(entryVal);
}
se::HandleObject array(se::Object::createArrayObject(entries.size()));
for (int i = 0; i < entries.size(); ++i) {
array->setArrayElement(i, entries[i]);
}
s.rval().setObject(array);
return true;
}
SE_BIND_FUNC(js_spine_Skin_getAttachments)
static bool js_spine_Slot_setAttachment(se::State& s) {
CC_UNUSED bool ok = true;
const auto& args = s.args();
spine::Slot *slot = (spine::Slot *) NULL ;
slot = SE_THIS_OBJECT<spine::Slot>(s);
if (nullptr == slot) return true;
spine::Attachment* attachment = nullptr;
ok = sevalue_to_native(args[0], &attachment, s.thisObject());
SE_PRECONDITION2(ok, false, "Error processing arguments");
slot->setAttachment(attachment);
return true;
}
SE_BIND_FUNC(js_spine_Slot_setAttachment)
static bool js_spine_Slot_getAttachment(se::State& s) {
CC_UNUSED bool ok = true;
const auto& args = s.args();
spine::Slot *slot = (spine::Slot *) NULL ;
slot = SE_THIS_OBJECT<spine::Slot>(s);
if (nullptr == slot) return true;
spine::Attachment *attachment = slot->getAttachment();
if (attachment) {
nativevalue_to_se(attachment, s.rval(), s.thisObject());
return true;
}
return false;
}
SE_BIND_FUNC(js_spine_Slot_getAttachment)
bool register_all_spine_manual(se::Object *obj) {
// Get the ns
se::Value nsVal;
if (!obj->getProperty("spine", &nsVal)) {
se::HandleObject jsobj(se::Object::createPlainObject());
nsVal.setObject(jsobj);
obj->setProperty("spine", nsVal);
}
se::Object *ns = nsVal.toObject();
ns->defineFunction("initSkeletonRenderer", _SE(js_register_spine_initSkeletonRenderer));
ns->defineFunction("initSkeletonData", _SE(js_register_spine_initSkeletonData));
ns->defineFunction("retainSkeletonData", _SE(js_register_spine_retainSkeletonData));
ns->defineFunction("disposeSkeletonData", _SE(js_register_spine_disposeSkeletonData));
__jsb_spine_VertexAttachment_proto->defineFunction("computeWorldVertices", _SE(js_VertexAttachment_computeWorldVertices));
__jsb_spine_RegionAttachment_proto->defineFunction("computeWorldVertices", _SE(js_RegionAttachment_computeWorldVertices));
__jsb_spine_Skeleton_proto->defineFunction("getBounds", _SE(js_Skeleton_getBounds));
__jsb_spine_Skin_proto->defineFunction("getAttachmentsForSlot", _SE(js_Skin_findAttachmentsForSlot));
__jsb_spine_Bone_proto->defineFunction("worldToLocal", _SE(js_Bone_worldToLocal));
__jsb_spine_Bone_proto->defineFunction("localToWorld", _SE(js_Bone_localToWorld));
__jsb_spine_PointAttachment_proto->defineFunction("computeWorldPosition", _SE(js_PointAttachment_computeWorldPosition));
__jsb_spine_VertexEffect_proto->defineFunction("transform", _SE(js_VertexEffect_transform));
__jsb_spine_SwirlVertexEffect_proto->defineFunction("transform", _SE(js_SwirlVertexEffect_transform));
__jsb_spine_JitterVertexEffect_proto->defineFunction("transform", _SE(js_JitterVertexEffect_transform));
__jsb_spine_Skin_proto->defineFunction("getAttachments", _SE(js_spine_Skin_getAttachments));
__jsb_spine_Slot_proto->defineFunction("setAttachment", _SE(js_spine_Slot_setAttachment));
__jsb_spine_Slot_proto->defineFunction("getAttachment", _SE(js_spine_Slot_getAttachment));
spine::setSpineObjectDisposeCallback([](void *spineObj) {
if (!se::NativePtrToObjectMap::isValid()) {
return;
}
// Support Native Spine fo Creator V3.0
se::NativePtrToObjectMap::forEach(spineObj, [](se::Object *seObj) {
// Unmap native and js object since native object was destroyed.
// Otherwise, it may trigger 'assertion' in se::Object::setPrivateData later
// since native obj is already released and the new native object may be assigned with
// the same address.
seObj->setClearMappingInFinalizer(false);
});
se::NativePtrToObjectMap::erase(spineObj);
});
se::ScriptEngine::getInstance()->addBeforeCleanupHook([]() {
spine::SkeletonDataMgr::destroyInstance();
});
se::ScriptEngine::getInstance()->clearException();
return true;
}

View File

@@ -0,0 +1,32 @@
/****************************************************************************
Copyright (c) 2020-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 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.
****************************************************************************/
#pragma once
#include "cocos/bindings/jswrapper/SeApi.h"
namespace se {
class Object;
}
bool register_all_spine_manual(se::Object *obj);

View File

@@ -0,0 +1,566 @@
/****************************************************************************
Copyright (c) 2017-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 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 "jsb_websocket.h"
#include "MappingUtils.h"
#include "base/std/container/unordered_set.h"
#include "cocos/base/DeferredReleasePool.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "application/ApplicationManager.h"
#include "base/UTF8.h"
/*
[Constructor(in DOMString url, in optional DOMString protocols)]
[Constructor(in DOMString url, in optional DOMString[] protocols)]
interface WebSocket {
readonly attribute DOMString url;
// ready state
const unsigned short CONNECTING = 0;
const unsigned short OPEN = 1;
const unsigned short CLOSING = 2;
const unsigned short CLOSED = 3;
readonly attribute unsigned short readyState;
readonly attribute unsigned long bufferedAmount;
// networking
attribute Function onopen;
attribute Function onmessage;
attribute Function onerror;
attribute Function onclose;
readonly attribute DOMString protocol;
void send(in DOMString data);
void close();
};
WebSocket implements EventTarget;
*/
#define GET_DELEGATE_FN(name) \
_JSDelegate.isObject() && _JSDelegate.toObject()->getProperty(name, &func)
namespace {
se::Class *jsbWebSocketClass = nullptr;
ccstd::unordered_set<JsbWebSocketDelegate *> jsbWebSocketDelegates;
} // namespace
JsbWebSocketDelegate::JsbWebSocketDelegate() {
jsbWebSocketDelegates.insert(this);
}
JsbWebSocketDelegate::~JsbWebSocketDelegate() {
CC_LOG_INFO("In the destructor of JSbWebSocketDelegate(%p)", this);
jsbWebSocketDelegates.erase(this);
}
void JsbWebSocketDelegate::onOpen(cc::network::WebSocket *ws) {
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
if (CC_CURRENT_APPLICATION() == nullptr) {
return;
}
se::Object *wsObj = se::NativePtrToObjectMap::findFirst(ws);
if (!wsObj) {
return;
}
wsObj->setProperty("protocol", se::Value(ws->getProtocol()));
se::HandleObject jsObj(se::Object::createPlainObject());
jsObj->setProperty("type", se::Value("open"));
se::Value target;
native_ptr_to_seval<cc::network::WebSocket>(ws, &target);
jsObj->setProperty("target", target);
se::Value func;
bool ok = GET_DELEGATE_FN("onopen");
if (ok && func.isObject() && func.toObject()->isFunction()) {
se::ValueArray args;
args.push_back(se::Value(jsObj));
func.toObject()->call(args, wsObj);
} else {
SE_REPORT_ERROR("Can't get onopen function!");
}
}
void JsbWebSocketDelegate::onMessage(cc::network::WebSocket *ws, const cc::network::WebSocket::Data &data) {
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
if (CC_CURRENT_APPLICATION() == nullptr) {
return;
}
se::Object *wsObj = se::NativePtrToObjectMap::findFirst(ws);
if (!wsObj) {
return;
}
se::HandleObject jsObj(se::Object::createPlainObject());
jsObj->setProperty("type", se::Value("message"));
se::Value target;
native_ptr_to_seval<cc::network::WebSocket>(ws, &target);
jsObj->setProperty("target", target);
se::Value func;
bool ok = GET_DELEGATE_FN("onmessage");
if (ok && func.isObject() && func.toObject()->isFunction()) {
se::ValueArray args;
args.push_back(se::Value(jsObj));
if (data.isBinary) {
se::HandleObject dataObj(se::Object::createArrayBufferObject(data.bytes, data.len));
jsObj->setProperty("data", se::Value(dataObj));
} else {
se::Value dataVal;
if (strlen(data.bytes) == 0 && data.len > 0) { // String with 0x00 prefix
ccstd::string str(data.bytes, data.len);
dataVal.setString(str);
} else { // Normal string
dataVal.setString(ccstd::string(data.bytes, data.len));
}
if (dataVal.isNullOrUndefined()) {
ws->closeAsync();
} else {
jsObj->setProperty("data", se::Value(dataVal));
}
}
func.toObject()->call(args, wsObj);
} else {
SE_REPORT_ERROR("Can't get onmessage function!");
}
}
void JsbWebSocketDelegate::onClose(cc::network::WebSocket *ws, uint16_t code, const ccstd::string &reason, bool wasClean) {
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
if (CC_CURRENT_APPLICATION() == nullptr) {
return;
}
se::Object *wsObj = se::NativePtrToObjectMap::findFirst(ws);
do {
if (!wsObj) {
CC_LOG_INFO("WebSocket js instance was destroyted, don't need to invoke onclose callback!");
break;
}
se::HandleObject jsObj(se::Object::createPlainObject());
jsObj->setProperty("type", se::Value("close")); // deprecated since v3.6
se::Value target;
native_ptr_to_seval<cc::network::WebSocket>(ws, &target);
jsObj->setProperty("target", target); // deprecated since v3.6
// CloseEvent attributes
jsObj->setProperty("code", se::Value(code));
jsObj->setProperty("reason", se::Value(reason));
jsObj->setProperty("wasClean", se::Value(wasClean));
se::Value func;
bool ok = GET_DELEGATE_FN("onclose");
if (ok && func.isObject() && func.toObject()->isFunction()) {
se::ValueArray args;
args.push_back(se::Value(jsObj));
func.toObject()->call(args, wsObj);
} else {
SE_REPORT_ERROR("Can't get onclose function!");
}
// JS Websocket object now can be GC, since the connection is closed.
wsObj->unroot();
if (_JSDelegate.isObject()) {
_JSDelegate.toObject()->unroot();
}
// Websocket instance is attached to global object in 'WebSocket_close'
// It's safe to detach it here since JS 'onclose' method has been already invoked.
se::ScriptEngine::getInstance()->getGlobalObject()->detachObject(wsObj);
} while (false);
ws->release();
release(); // Release delegate self at last
}
void JsbWebSocketDelegate::onError(cc::network::WebSocket *ws, const cc::network::WebSocket::ErrorCode & /*error*/) {
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
if (CC_CURRENT_APPLICATION() == nullptr) {
return;
}
se::Object *wsObj = se::NativePtrToObjectMap::findFirst(ws);
if (!wsObj) {
return;
}
se::HandleObject jsObj(se::Object::createPlainObject());
jsObj->setProperty("type", se::Value("error"));
se::Value target;
native_ptr_to_seval<cc::network::WebSocket>(ws, &target);
jsObj->setProperty("target", target);
se::Value func;
bool ok = GET_DELEGATE_FN("onerror");
if (ok && func.isObject() && func.toObject()->isFunction()) {
se::ValueArray args;
args.push_back(se::Value(jsObj));
func.toObject()->call(args, wsObj);
} else {
SE_REPORT_ERROR("Can't get onerror function!");
}
}
void JsbWebSocketDelegate::setJSDelegate(const se::Value &jsDelegate) {
CC_ASSERT(jsDelegate.isObject());
_JSDelegate = jsDelegate;
se::ScriptEngine::getInstance()->addBeforeCleanupHook([this]() {
if (jsbWebSocketDelegates.find(this) != jsbWebSocketDelegates.end()) {
_JSDelegate.setUndefined();
}
});
}
static bool webSocketFinalize(se::State &s) {
auto *cobj = static_cast<cc::network::WebSocket *>(s.nativeThisObject());
CC_LOG_INFO("jsbindings: finalizing JS object %p (WebSocket)", cobj);
// Manually close if web socket is not closed
if (cobj->getReadyState() != cc::network::WebSocket::State::CLOSED) {
CC_LOG_INFO("WebSocket (%p) isn't closed, try to close it!", cobj);
cobj->closeAsync();
}
static_cast<JsbWebSocketDelegate *>(cobj->getDelegate())->release();
return true;
}
SE_BIND_FINALIZE_FUNC(webSocketFinalize)
static bool webSocketConstructor(se::State &s) {
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 1 || argc == 2 || argc == 3) {
ccstd::string url;
bool ok = sevalue_to_native(args[0], &url);
SE_PRECONDITION2(ok, false, "Error processing url argument");
se::Object *obj = s.thisObject();
cc::network::WebSocket *cobj = nullptr;
if (argc >= 2) {
ccstd::string caFilePath;
ccstd::vector<ccstd::string> protocols;
if (args[1].isString()) {
ccstd::string protocol;
ok = sevalue_to_native(args[1], &protocol);
SE_PRECONDITION2(ok, false, "Error processing protocol string");
protocols.push_back(protocol);
} else if (args[1].isObject() && args[1].toObject()->isArray()) {
se::Object *protocolArr = args[1].toObject();
uint32_t len = 0;
ok = protocolArr->getArrayLength(&len);
SE_PRECONDITION2(ok, false, "getArrayLength failed!");
se::Value tmp;
for (uint32_t i = 0; i < len; ++i) {
if (!protocolArr->getArrayElement(i, &tmp)) {
continue;
}
ccstd::string protocol;
ok = sevalue_to_native(tmp, &protocol);
SE_PRECONDITION2(ok, false, "Error processing protocol object");
protocols.push_back(protocol);
}
}
if (argc > 2) {
ok = sevalue_to_native(args[2], &caFilePath);
SE_PRECONDITION2(ok, false, "Error processing caFilePath");
}
cobj = ccnew cc::network::WebSocket();
auto *delegate = ccnew JsbWebSocketDelegate();
delegate->addRef();
if (cobj->init(*delegate, url, &protocols, caFilePath)) {
delegate->setJSDelegate(se::Value(obj, true));
cobj->addRef(); // release in finalize function and onClose delegate method
delegate->addRef(); // release in finalize function and onClose delegate method
} else {
cobj->release();
delegate->release();
SE_REPORT_ERROR("WebSocket init failed!");
return false;
}
} else {
cobj = ccnew cc::network::WebSocket();
auto *delegate = ccnew JsbWebSocketDelegate();
delegate->addRef();
if (cobj->init(*delegate, url)) {
delegate->setJSDelegate(se::Value(obj, true));
cobj->addRef(); // release in finalize function and onClose delegate method
delegate->addRef(); // release in finalize function and onClose delegate method
} else {
cobj->release();
delegate->release();
SE_REPORT_ERROR("WebSocket init failed!");
return false;
}
}
obj->setProperty("url", args[0]);
// The websocket draft uses lowercase 'url', so 'URL' need to be deprecated.
obj->setProperty("URL", args[0]);
// Initialize protocol property with an empty string, it will be assigned in onOpen delegate.
obj->setProperty("protocol", se::Value(""));
obj->setPrivateData(cobj);
obj->root();
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1<= and <=3", argc);
return false;
}
SE_BIND_CTOR(webSocketConstructor, jsbWebSocketClass, webSocketFinalize)
static bool webSocketSend(se::State &s) {
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 1) {
auto *cobj = static_cast<cc::network::WebSocket *>(s.nativeThisObject());
bool ok = false;
if (args[0].isString()) {
ccstd::string data;
ok = sevalue_to_native(args[0], &data);
SE_PRECONDITION2(ok, false, "Convert string failed");
// IDEA: We didn't find a way to get the JS string length in JSB2.0.
// if (data.empty() && len > 0)
// {
// CC_LOG_DEBUGWARN("Text message to send is empty, but its length is greater than 0!");
// //IDEA: Note that this text message contains '0x00' prefix, so its length calcuted by strlen is 0.
// // we need to fix that if there is '0x00' in text message,
// // since javascript language could support '0x00' inserted at the beginning or the middle of text message
// }
cobj->send(data);
} else if (args[0].isObject()) {
se::Object *dataObj = args[0].toObject();
uint8_t *ptr = nullptr;
size_t length = 0;
if (dataObj->isArrayBuffer()) {
ok = dataObj->getArrayBufferData(&ptr, &length);
SE_PRECONDITION2(ok, false, "getArrayBufferData failed!");
} else if (dataObj->isTypedArray()) {
ok = dataObj->getTypedArrayData(&ptr, &length);
SE_PRECONDITION2(ok, false, "getTypedArrayData failed!");
} else {
CC_ABORT();
}
cobj->send(ptr, static_cast<unsigned int>(length));
} else {
CC_ABORT();
}
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1", argc);
return false;
}
SE_BIND_FUNC(webSocketSend)
static bool webSocketClose(se::State &s) {
const auto &args = s.args();
int argc = static_cast<int>(args.size());
auto *cobj = static_cast<cc::network::WebSocket *>(s.nativeThisObject());
if (argc == 0) {
cobj->closeAsync();
} else if (argc == 1) {
if (args[0].isNumber()) {
int reasonCode{0};
sevalue_to_native(args[0], &reasonCode);
cobj->closeAsync(reasonCode, "no_reason");
} else if (args[0].isString()) {
ccstd::string reasonString;
sevalue_to_native(args[0], &reasonString);
cobj->closeAsync(1005, reasonString);
} else {
CC_ABORT();
}
} else if (argc == 2) {
if (args[0].isNumber()) {
int reasonCode{0};
if (args[1].isString()) {
ccstd::string reasonString;
sevalue_to_native(args[0], &reasonCode);
sevalue_to_native(args[1], &reasonString);
cobj->closeAsync(reasonCode, reasonString);
} else if (args[1].isNullOrUndefined()) {
sevalue_to_native(args[0], &reasonCode);
cobj->closeAsync(reasonCode, "no_reason");
} else {
CC_ABORT();
}
} else if (args[0].isNullOrUndefined()) {
if (args[1].isString()) {
ccstd::string reasonString;
sevalue_to_native(args[1], &reasonString);
cobj->closeAsync(1005, reasonString);
} else if (args[1].isNullOrUndefined()) {
cobj->closeAsync();
} else {
CC_ABORT();
}
} else {
CC_ABORT();
}
} else {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting <=2", argc);
CC_ABORT();
}
// Attach current WebSocket instance to global object to prevent WebSocket instance
// being garbage collected after "ws.close(); ws = null;"
// There is a state that current WebSocket JS instance is being garbaged but its finalize
// callback has not be invoked. Then in "JSB_WebSocketDelegate::onClose", se::Object is
// still be able to be found and while invoking JS 'onclose' method, crash will happen since
// JS instance is invalid and is going to be collected. This bug is easiler reproduced on iOS
// because JavaScriptCore is more GC sensitive.
// Please note that we need to detach it from global object in "JSB_WebSocketDelegate::onClose".
se::ScriptEngine::getInstance()->getGlobalObject()->attachObject(s.thisObject());
return true;
}
SE_BIND_FUNC(webSocketClose)
static bool webSocketGetReadyState(se::State &s) {
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 0) {
auto *cobj = static_cast<cc::network::WebSocket *>(s.nativeThisObject());
s.rval().setInt32(static_cast<int>(cobj->getReadyState()));
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
return false;
}
SE_BIND_PROP_GET(webSocketGetReadyState)
static bool webSocketGetBufferedAmount(se::State &s) {
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 0) {
auto *cobj = static_cast<cc::network::WebSocket *>(s.nativeThisObject());
s.rval().setUint32(static_cast<uint32_t>(cobj->getBufferedAmount()));
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
return false;
}
SE_BIND_PROP_GET(webSocketGetBufferedAmount)
static bool webSocketGetExtensions(se::State &s) {
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 0) {
auto *cobj = static_cast<cc::network::WebSocket *>(s.nativeThisObject());
s.rval().setString(cobj->getExtensions());
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
return false;
}
SE_BIND_PROP_GET(webSocketGetExtensions)
#define WEBSOCKET_DEFINE_READONLY_INT_FIELD(full_name, value) \
static bool full_name(se::State &s) { \
const auto &args = s.args(); \
int argc = (int)args.size(); \
if (argc == 0) { \
s.rval().setInt32(value); \
return true; \
} \
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc); \
return false; \
} \
SE_BIND_PROP_GET(full_name)
WEBSOCKET_DEFINE_READONLY_INT_FIELD(Websocket_CONNECTING, static_cast<int>(cc::network::WebSocket::State::CONNECTING))
WEBSOCKET_DEFINE_READONLY_INT_FIELD(Websocket_OPEN, static_cast<int>(cc::network::WebSocket::State::OPEN))
WEBSOCKET_DEFINE_READONLY_INT_FIELD(Websocket_CLOSING, static_cast<int>(cc::network::WebSocket::State::CLOSING))
WEBSOCKET_DEFINE_READONLY_INT_FIELD(Websocket_CLOSED, static_cast<int>(cc::network::WebSocket::State::CLOSED))
bool register_all_websocket(se::Object *global) { // NOLINT (readability-identifier-naming)
se::Value nsVal;
if (!global->getProperty("jsb", &nsVal, true)) {
se::HandleObject jsobj(se::Object::createPlainObject());
nsVal.setObject(jsobj);
global->setProperty("jsb", nsVal);
}
se::Object *ns = nsVal.toObject();
se::Class *cls = se::Class::create("WebSocket", ns, nullptr, _SE(webSocketConstructor));
cls->defineFinalizeFunction(_SE(webSocketFinalize));
cls->defineFunction("send", _SE(webSocketSend));
cls->defineFunction("close", _SE(webSocketClose));
cls->defineProperty("readyState", _SE(webSocketGetReadyState), nullptr);
cls->defineProperty("bufferedAmount", _SE(webSocketGetBufferedAmount), nullptr);
cls->defineProperty("extensions", _SE(webSocketGetExtensions), nullptr);
cls->defineProperty("CONNECTING", _SE(Websocket_CONNECTING), nullptr);
cls->defineProperty("CLOSING", _SE(Websocket_CLOSING), nullptr);
cls->defineProperty("OPEN", _SE(Websocket_OPEN), nullptr);
cls->defineProperty("CLOSED", _SE(Websocket_CLOSED), nullptr);
cls->install();
se::Value tmp;
ns->getProperty("WebSocket", &tmp);
tmp.toObject()->defineProperty("CONNECTING", _SE(Websocket_CONNECTING), nullptr);
tmp.toObject()->defineProperty("CLOSING", _SE(Websocket_CLOSING), nullptr);
tmp.toObject()->defineProperty("OPEN", _SE(Websocket_OPEN), nullptr);
tmp.toObject()->defineProperty("CLOSED", _SE(Websocket_CLOSED), nullptr);
JSBClassType::registerClass<cc::network::WebSocket>(cls);
jsbWebSocketClass = cls;
se::ScriptEngine::getInstance()->clearException();
return true;
}

View File

@@ -0,0 +1,59 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
#pragma once
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/network/WebSocket.h"
namespace se {
class Object;
class Value;
} // namespace se
class JsbWebSocketDelegate : public cc::RefCounted, public cc::network::WebSocket::Delegate {
public:
JsbWebSocketDelegate();
void onOpen(cc::network::WebSocket *ws) override;
void onMessage(cc::network::WebSocket *ws,
const cc::network::WebSocket::Data &data) override;
void onClose(cc::network::WebSocket *ws, uint16_t code, const ccstd::string &reason, bool wasClean) override;
void onError(cc::network::WebSocket *ws,
const cc::network::WebSocket::ErrorCode &error) override;
void setJSDelegate(const se::Value &jsDelegate);
private:
~JsbWebSocketDelegate() override;
se::Value _JSDelegate; // NOLINT (bugprone-reserved-identifier)
};
SE_DECLARE_FINALIZE_FUNC(WebSocket_finalize);
bool register_all_websocket(se::Object *obj); // NOLINT (readability-identifier-naming)

View File

@@ -0,0 +1,932 @@
/****************************************************************************
Copyright (c) 2019-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 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.
****************************************************************************/
// clang-format off
#include "base/Macros.h"
#include "uv.h"
// clang-format on
#include "cocos/bindings/manual/jsb_websocket_server.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "cocos/network/WebSocketServer.h"
namespace {
template <typename T>
std::shared_ptr<T> sharedPtrObj(se::State &s) {
auto *privateObj = s.thisObject()->getPrivateObject();
assert(privateObj->isSharedPtr());
return static_cast<se::SharedPtrPrivateObject<T> *>(privateObj)->getData();
}
} // namespace
se::Class *__jsb_WebSocketServer_class = nullptr; // NOLINT
se::Class *__jsb_WebSocketServer_Connection_class = nullptr; // NOLINT
static int sendIndex = 1;
static ccstd::string genSendIndex() {
char buf[128] = {0};
snprintf(buf, 127, "__send_[%d]", sendIndex++);
return buf;
}
static bool WebSocketServer_finalize(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::network::WebSocketServer *>(s.nativeThisObject());
CC_LOG_INFO("jsbindings: finalizing JS object %p (WebSocketServer)", cobj);
return true;
}
SE_BIND_FINALIZE_FUNC(WebSocketServer_finalize)
static bool WebSocketServer_constructor(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 0) {
se::Object *obj = s.thisObject();
auto *cobj = ccnew cc::network::WebSocketServer();
obj->setPrivateData(cobj);
cobj->setData(obj);
cobj->setOnBegin([obj]() {
obj->root();
});
cobj->setOnEnd([obj]() {
obj->unroot();
});
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
return false;
}
SE_BIND_CTOR(WebSocketServer_constructor, __jsb_WebSocketServer_class, WebSocketServer_finalize)
static bool WebSocketServer_listen(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 0) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1,2,3", argc);
return false;
}
auto cobj = sharedPtrObj<cc::network::WebSocketServer>(s);
int argPort = 0;
ccstd::string argHost;
std::function<void(const ccstd::string &)> argCallback;
bool ok;
if (argc >= 1) { // port
ok = sevalue_to_native(args[0], &argPort);
SE_PRECONDITION2(ok, false, "Convert args[0] to port failed");
}
if (argc >= 2) { // host or callback
if (args[1].isString()) { //to host
ok = sevalue_to_native(args[1], &argHost);
SE_PRECONDITION2(ok, false, "Convert args[1] to host failed");
}
se::Object *funObj = nullptr;
if (args[1].isObject() && args[1].toObject()->isFunction()) {
funObj = args[1].toObject();
}
if (argc > 2 && args[2].isObject() && args[2].toObject()->isFunction()) {
funObj = args[2].toObject();
}
if (funObj) {
s.thisObject()->setProperty("__onlisten", se::Value(funObj));
std::weak_ptr<cc::network::WebSocketServer> serverWeak = cobj;
argCallback = [serverWeak](const ccstd::string &err) {
se::AutoHandleScope hs;
auto serverPtr = serverWeak.lock();
if (!serverPtr) {
return;
}
auto *sobj = static_cast<se::Object *>(serverPtr->getData());
if (!sobj) {
return;
}
se::Value callback;
if (!sobj->getProperty("__onlisten", &callback)) {
SE_REPORT_ERROR("onlisten attribute not set!");
return;
}
se::ValueArray args;
if (!err.empty()) {
args.push_back(se::Value(err));
}
bool success = callback.toObject()->call(args, sobj, nullptr);
if (!success) {
se::ScriptEngine::getInstance()->clearException();
}
};
}
}
cc::network::WebSocketServer::listenAsync(cobj, argPort, argHost, argCallback);
return true;
}
SE_BIND_FUNC(WebSocketServer_listen)
static bool WebSocketServer_onconnection(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction())) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
return false;
}
s.thisObject()->setProperty("__onconnection", args[0]);
auto cobj = sharedPtrObj<cc::network::WebSocketServer>(s);
std::weak_ptr<cc::network::WebSocketServer> serverWeak = cobj;
cobj->setOnConnection([serverWeak](const std::shared_ptr<cc::network::WebSocketServerConnection> &conn) {
se::AutoHandleScope hs;
auto server = serverWeak.lock();
if (!server) {
return;
}
auto *sobj = static_cast<se::Object *>(server->getData());
if (!sobj) {
return;
}
se::Value callback;
if (!sobj->getProperty("__onconnection", &callback)) {
SE_REPORT_ERROR("onconnection callback not found!");
return;
}
se::Object *obj = se::Object::createObjectWithClass(__jsb_WebSocketServer_Connection_class);
// a connection is dead only if no reference & closed!
obj->root();
obj->setPrivateObject(se::shared_ptr_private_object(conn));
conn->setData(obj);
std::weak_ptr<cc::network::WebSocketServerConnection> connWeak = conn;
conn->setOnEnd([connWeak, obj]() {
// release we connection is gone!
auto ptr = connWeak.lock();
if (ptr) {
auto *sobj = static_cast<se::Object *>(ptr->getData());
sobj->unroot();
CC_ASSERT_EQ(obj, sobj);
}
});
se::ValueArray args;
args.push_back(se::Value(obj));
bool success = callback.toObject()->call(args, sobj, nullptr);
;
if (!success) {
se::ScriptEngine::getInstance()->clearException();
}
});
return true;
}
SE_BIND_PROP_SET(WebSocketServer_onconnection)
static bool WebSocketServer_onclose(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc != 1) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1", argc);
return false;
}
if (!(args[0].isObject() && args[0].toObject()->isFunction())) {
SE_REPORT_ERROR("argument type error, function expected!");
}
std::function<void(const ccstd::string &)> callback;
auto cobj = sharedPtrObj<cc::network::WebSocketServer>(s);
std::weak_ptr<cc::network::WebSocketServer> serverWeak = cobj;
s.thisObject()->setProperty("__onclose", args[0]);
callback = [serverWeak](const ccstd::string &err) {
se::AutoHandleScope hs;
auto server = serverWeak.lock();
if (!server) {
return;
}
auto *sobj = static_cast<se::Object *>(server->getData());
if (!sobj) {
return;
}
se::Value callback;
if (!sobj->getProperty("__onclose", &callback)) {
SE_REPORT_ERROR("onclose callback not found!");
return;
}
se::ValueArray args;
if (!err.empty()) {
args.push_back(se::Value(err));
}
bool success = callback.toObject()->call(args, sobj, nullptr);
if (!success) {
se::ScriptEngine::getInstance()->clearException();
}
};
cobj->setOnClose(callback);
return true;
}
SE_BIND_PROP_SET(WebSocketServer_onclose)
static bool WebSocketServer_close(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc > 1) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0, 1", argc);
return false;
}
std::function<void(const ccstd::string &)> callback;
auto cobj = sharedPtrObj<cc::network::WebSocketServer>(s);
if (argc == 1) {
if (args[0].isObject() && args[0].toObject()->isFunction()) {
s.thisObject()->setProperty("__close", args[0]);
std::weak_ptr<cc::network::WebSocketServer> serverWeak = cobj;
callback = [serverWeak](const ccstd::string &err) {
se::AutoHandleScope hs;
auto server = serverWeak.lock();
if (!server) {
return;
}
auto *sobj = static_cast<se::Object *>(server->getData());
if (!sobj) {
return;
}
se::Value callback;
if (!sobj->getProperty("__close", &callback)) {
SE_REPORT_ERROR("onclose callback not found!");
return;
}
se::ValueArray args;
if (!err.empty()) {
args.push_back(se::Value(err));
}
bool success = callback.toObject()->call(args, sobj, nullptr);
if (!success) {
se::ScriptEngine::getInstance()->clearException();
}
};
cobj->closeAsync(callback);
} else {
SE_REPORT_ERROR("wrong argument type, function expected");
return false;
}
} else {
cobj->closeAsync();
}
return true;
}
SE_BIND_FUNC(WebSocketServer_close)
static bool WebSocketServer_connections(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 0) {
auto cobj = sharedPtrObj<cc::network::WebSocketServer>(s);
auto conns = cobj->getConnections();
se::Object *ret = se::Object::createArrayObject(conns.size());
for (uint32_t i = 0; i < conns.size(); i++) {
std::shared_ptr<cc::network::WebSocketServerConnection> &con = conns[i];
auto *obj = static_cast<se::Object *>(con->getData());
ret->setArrayElement(i, se::Value(obj));
}
s.rval().setObject(ret);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
return false;
}
SE_BIND_PROP_GET(WebSocketServer_connections)
static bool WebSocketServer_Connection_finalize(se::State &s) { // NOLINT(readability-identifier-naming)
auto *cobj = static_cast<cc::network::WebSocketServerConnection *>(s.nativeThisObject());
CC_LOG_INFO("jsbindings: finalizing JS object %p (WebSocketServer_Connection)", cobj);
return true;
}
SE_BIND_FINALIZE_FUNC(WebSocketServer_Connection_finalize)
static bool WebSocketServer_Connection_constructor(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 0) {
se::Object *obj = s.thisObject();
//private data should be set when connected
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
return false;
}
SE_BIND_CTOR(WebSocketServer_Connection_constructor, __jsb_WebSocketServer_Connection_class, WebSocketServer_Connection_finalize)
static bool WebSocketServer_Connection_send(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
auto cobj = sharedPtrObj<cc::network::WebSocketServerConnection>(s);
if (!cobj) {
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
return false;
}
if (argc >= 1) {
std::function<void(const ccstd::string &cb)> callback;
if (args[argc - 1].isObject() && args[argc - 1].toObject()->isFunction()) {
ccstd::string callbackId = genSendIndex();
s.thisObject()->setProperty(callbackId.c_str(), args[argc - 1]);
std::weak_ptr<cc::network::WebSocketServerConnection> connWeak = cobj;
callback = [callbackId, connWeak](const ccstd::string &err) {
se::AutoHandleScope hs;
auto conn = connWeak.lock();
if (!conn) {
return;
}
auto *sobj = static_cast<se::Object *>(conn->getData());
if (!sobj) {
return;
}
se::Value callback;
if (!sobj->getProperty(callbackId.c_str(), &callback)) {
SE_REPORT_ERROR("send[%s] callback not found!", callbackId.c_str());
return;
}
se::ValueArray args;
if (!err.empty()) {
args.push_back(se::Value(err));
}
bool success = callback.toObject()->call(args, sobj, nullptr);
if (!success) {
se::ScriptEngine::getInstance()->clearException();
}
sobj->deleteProperty(callbackId.c_str());
};
}
bool ok = false;
if (args[0].isString()) {
ccstd::string data;
ok = sevalue_to_native(args[0], &data);
SE_PRECONDITION2(ok, false, "Convert string failed");
cobj->sendTextAsync(data, callback);
} else if (args[0].isObject()) {
se::Object *dataObj = args[0].toObject();
uint8_t *ptr = nullptr;
size_t length = 0;
if (dataObj->isArrayBuffer()) {
ok = dataObj->getArrayBufferData(&ptr, &length);
SE_PRECONDITION2(ok, false, "getArrayBufferData failed!");
} else if (dataObj->isTypedArray()) {
ok = dataObj->getTypedArrayData(&ptr, &length);
SE_PRECONDITION2(ok, false, "getTypedArrayData failed!");
} else {
CC_ABORT();
}
cobj->sendBinaryAsync(ptr, static_cast<unsigned int>(length), callback);
} else {
CC_ABORT();
}
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1", argc);
return false;
}
SE_BIND_FUNC(WebSocketServer_Connection_send)
static bool WebSocketServer_Connection_close(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc > 1) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0, 1", argc);
return false;
}
auto *cobj = static_cast<cc::network::WebSocketServerConnection *>(s.nativeThisObject());
if (!cobj) {
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
return false;
}
std::function<void(const ccstd::string &)> callback;
int argCode = -1;
ccstd::string argReason;
bool ok;
if (argc >= 1) {
ok = sevalue_to_native(args[0], &argCode);
SE_PRECONDITION2(ok, false, "Convert args[0] should be a number");
if (argc >= 2) {
ok = sevalue_to_native(args[1], &argReason);
SE_PRECONDITION2(ok, false, "Convert args[1] should be a string");
}
}
if (argCode > 0 && !argReason.empty()) {
cobj->closeAsync(argCode, argReason);
} else if (argCode > 0) {
cobj->closeAsync(argCode, "unknown reason");
} else {
cobj->closeAsync(1000, "default close reason");
}
return true;
}
SE_BIND_FUNC(WebSocketServer_Connection_close)
static bool WebSocketServer_Connection_onconnect(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction())) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
return false;
}
auto cobj = sharedPtrObj<cc::network::WebSocketServerConnection>(s);
if (!cobj) {
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
return false;
}
s.thisObject()->setProperty("__onconnect", args[0]);
std::weak_ptr<cc::network::WebSocketServerConnection> connWeak = cobj;
cobj->setOnConnect([connWeak]() {
se::AutoHandleScope hs;
auto conn = connWeak.lock();
if (!conn) {
return;
}
auto *sobj = static_cast<se::Object *>(conn->getData());
if (!sobj) {
return;
}
se::Value callback;
if (!sobj->getProperty("__onconnect", &callback)) {
SE_REPORT_ERROR("__onconnect callback not found!");
return;
}
se::ValueArray args;
bool success = callback.toObject()->call(args, sobj, nullptr);
;
if (!success) {
se::ScriptEngine::getInstance()->clearException();
}
});
return true;
}
SE_BIND_PROP_SET(WebSocketServer_Connection_onconnect)
static bool WebSocketServer_Connection_onerror(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction())) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
return false;
}
auto cobj = sharedPtrObj<cc::network::WebSocketServerConnection>(s);
if (!cobj) {
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
return false;
}
s.thisObject()->setProperty("__onerror", args[0]);
std::weak_ptr<cc::network::WebSocketServerConnection> connWeak = cobj;
cobj->setOnError([connWeak](const ccstd::string &err) {
se::AutoHandleScope hs;
auto conn = connWeak.lock();
if (!conn) {
return;
}
auto *sobj = static_cast<se::Object *>(conn->getData());
if (!sobj) {
return;
}
se::Value callback;
if (!sobj->getProperty("__onerror", &callback)) {
SE_REPORT_ERROR("__onerror callback not found!");
return;
}
se::ValueArray args;
if (!err.empty()) {
args.push_back(se::Value(err));
}
bool success = callback.toObject()->call(args, sobj, nullptr);
;
if (!success) {
se::ScriptEngine::getInstance()->clearException();
}
});
return true;
}
SE_BIND_PROP_SET(WebSocketServer_Connection_onerror)
static bool WebSocketServer_Connection_onclose(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction())) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
return false;
}
auto cobj = sharedPtrObj<cc::network::WebSocketServerConnection>(s);
if (!cobj) {
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
return false;
}
s.thisObject()->setProperty("__onclose", args[0]);
std::weak_ptr<cc::network::WebSocketServerConnection> connWeak = cobj;
cobj->setOnClose([connWeak](int code, const ccstd::string &err) {
se::AutoHandleScope hs;
auto conn = connWeak.lock();
if (!conn) {
return;
}
auto *sobj = static_cast<se::Object *>(conn->getData());
if (!sobj) {
return;
}
se::Value callback;
if (!sobj->getProperty("__onclose", &callback)) {
SE_REPORT_ERROR("__onclose callback not found!");
return;
}
se::ValueArray args;
args.push_back(se::Value(code));
if (!err.empty()) {
args.push_back(se::Value(err));
}
bool success = callback.toObject()->call(args, sobj, nullptr);
;
if (!success) {
se::ScriptEngine::getInstance()->clearException();
}
});
return true;
}
SE_BIND_PROP_SET(WebSocketServer_Connection_onclose)
static bool WebSocketServer_Connection_ontext(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction())) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
return false;
}
auto cobj = sharedPtrObj<cc::network::WebSocketServerConnection>(s);
if (!cobj) {
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
return false;
}
s.thisObject()->setProperty("__ontext", args[0]);
std::weak_ptr<cc::network::WebSocketServerConnection> connWeak = cobj;
cobj->setOnText([connWeak](const std::shared_ptr<cc::network::DataFrame> &text) {
se::AutoHandleScope hs;
auto conn = connWeak.lock();
if (!conn) {
return;
}
auto *sobj = static_cast<se::Object *>(conn->getData());
if (!sobj) {
return;
}
se::Value callback;
if (!sobj->getProperty("__ontext", &callback)) {
SE_REPORT_ERROR("__ontext callback not found!");
return;
}
se::ValueArray args;
args.push_back(se::Value(text->toString()));
bool success = callback.toObject()->call(args, sobj, nullptr);
;
if (!success) {
se::ScriptEngine::getInstance()->clearException();
}
});
return true;
}
SE_BIND_PROP_SET(WebSocketServer_Connection_ontext)
static bool WebSocketServer_Connection_onbinary(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction())) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
return false;
}
auto cobj = sharedPtrObj<cc::network::WebSocketServerConnection>(s);
if (!cobj) {
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
return false;
}
s.thisObject()->setProperty("__onbinary", args[0]);
std::weak_ptr<cc::network::WebSocketServerConnection> connWeak = cobj;
cobj->setOnBinary([connWeak](const std::shared_ptr<cc::network::DataFrame> &text) {
se::AutoHandleScope hs;
auto conn = connWeak.lock();
if (!conn) {
return;
}
auto *sobj = static_cast<se::Object *>(conn->getData());
if (!sobj) {
return;
}
se::Value callback;
if (!sobj->getProperty("__onbinary", &callback)) {
SE_REPORT_ERROR("__onbinary callback not found!");
return;
}
se::ValueArray args;
se::Object *buffer = se::Object::createArrayBufferObject(text->getData(), text->size());
args.push_back(se::Value(buffer));
bool success = callback.toObject()->call(args, sobj, nullptr);
;
if (!success) {
se::ScriptEngine::getInstance()->clearException();
}
});
return true;
}
SE_BIND_PROP_SET(WebSocketServer_Connection_onbinary)
//deprecated since v3.7, please use WebSocketServer_Connection_onmessage to instead.
static bool WebSocketServer_Connection_ondata(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction())) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
return false;
}
auto cobj = sharedPtrObj<cc::network::WebSocketServerConnection>(s);
if (!cobj) {
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
return false;
}
s.thisObject()->setProperty("__ondata", args[0]);
std::weak_ptr<cc::network::WebSocketServerConnection> connWeak = cobj;
cobj->setOnMessage([connWeak](const std::shared_ptr<cc::network::DataFrame> &text) {
se::AutoHandleScope hs;
auto connPtr = connWeak.lock();
if (!connPtr) {
return;
}
auto *sobj = static_cast<se::Object *>(connPtr->getData());
if (!sobj) {
return;
}
se::Value callback;
if (!sobj->getProperty("__ondata", &callback)) {
return;
}
se::ValueArray args;
if (text->isBinary()) {
se::Object *buffer = se::Object::createArrayBufferObject(text->getData(), text->size());
args.push_back(se::Value(buffer));
} else if (text->isString()) {
args.push_back(se::Value(text->toString()));
}
bool success = callback.toObject()->call(args, sobj, nullptr);
;
if (!success) {
se::ScriptEngine::getInstance()->clearException();
}
});
SE_REPORT_ERROR("Deprecated callback function ondata since v3.7, please use onmessage to instead.");
return true;
}
SE_BIND_PROP_SET(WebSocketServer_Connection_ondata)
static bool WebSocketServer_Connection_onmessage(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction())) {
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
return false;
}
auto cobj = sharedPtrObj<cc::network::WebSocketServerConnection>(s);
if (!cobj) {
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
return false;
}
s.thisObject()->setProperty("__onmessage", args[0]);
std::weak_ptr<cc::network::WebSocketServerConnection> connWeak = cobj;
cobj->setOnMessage([connWeak](const std::shared_ptr<cc::network::DataFrame> &text) {
se::AutoHandleScope hs;
auto connPtr = connWeak.lock();
if (!connPtr) {
return;
}
auto *sobj = static_cast<se::Object *>(connPtr->getData());
if (!sobj) {
return;
}
se::Value callback;
if (!sobj->getProperty("__onmessage", &callback)) {
return;
}
se::ValueArray args;
if (text->isBinary()) {
se::Object *buffer = se::Object::createArrayBufferObject(text->getData(), text->size());
args.push_back(se::Value(buffer));
} else if (text->isString()) {
args.push_back(se::Value(text->toString()));
}
bool success = callback.toObject()->call(args, sobj, nullptr);
;
if (!success) {
se::ScriptEngine::getInstance()->clearException();
}
});
return true;
}
SE_BIND_PROP_SET(WebSocketServer_Connection_onmessage)
static bool WebSocketServer_Connection_headers(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 0) {
auto *cobj = static_cast<cc::network::WebSocketServerConnection *>(s.nativeThisObject());
auto headers = cobj->getHeaders();
se::Object *ret = se::Object::createPlainObject();
for (auto &itr : headers) {
ret->setProperty(itr.first.c_str(), se::Value(itr.second));
}
s.rval().setObject(ret);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
return false;
}
SE_BIND_PROP_GET(WebSocketServer_Connection_headers)
static bool WebSocketServer_Connection_protocols(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 0) {
auto *cobj = static_cast<cc::network::WebSocketServerConnection *>(s.nativeThisObject());
auto protocols = cobj->getProtocols();
se::Object *ret = se::Object::createArrayObject(protocols.size());
for (uint32_t i = 0; i < protocols.size(); i++) {
ret->setArrayElement(i, se::Value(protocols[i]));
}
s.rval().setObject(ret);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
return false;
}
SE_BIND_PROP_GET(WebSocketServer_Connection_protocols)
static bool WebSocketServer_Connection_protocol(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 0) {
auto *cobj = static_cast<cc::network::WebSocketServerConnection *>(s.nativeThisObject());
auto protocols = cobj->getProtocols();
if (!protocols.empty()) {
s.rval().setString(protocols[0]);
} else {
s.rval().setUndefined();
}
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
return false;
}
SE_BIND_PROP_GET(WebSocketServer_Connection_protocol)
static bool WebSocketServer_Connection_readyState(se::State &s) { // NOLINT(readability-identifier-naming)
const auto &args = s.args();
int argc = static_cast<int>(args.size());
if (argc == 0) {
auto *cobj = static_cast<cc::network::WebSocketServerConnection *>(s.nativeThisObject());
auto state = cobj->getReadyState();
s.rval().setInt32(state);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
return false;
}
SE_BIND_PROP_GET(WebSocketServer_Connection_readyState)
bool register_all_websocket_server(se::Object *obj) {
se::Class *cls = se::Class::create("WebSocketServer", obj, nullptr, _SE(WebSocketServer_constructor));
cls->defineFinalizeFunction(_SE(WebSocketServer_finalize));
cls->defineFunction("close", _SE(WebSocketServer_close));
cls->defineFunction("listen", _SE(WebSocketServer_listen));
cls->defineProperty("onconnection", nullptr, _SE(WebSocketServer_onconnection));
cls->defineProperty("onclose", nullptr, _SE(WebSocketServer_onclose));
cls->defineProperty("connections", _SE(WebSocketServer_connections), nullptr);
cls->install();
JSBClassType::registerClass<cc::network::WebSocketServer>(cls);
__jsb_WebSocketServer_class = cls;
se::ScriptEngine::getInstance()->clearException();
cls = se::Class::create("WebSocketServerConnection", obj, nullptr, _SE(WebSocketServer_Connection_constructor));
cls->defineFinalizeFunction(_SE(WebSocketServer_Connection_finalize));
cls->defineFunction("close", _SE(WebSocketServer_Connection_close));
cls->defineFunction("send", _SE(WebSocketServer_Connection_send));
cls->defineProperty("ontext", nullptr, _SE(WebSocketServer_Connection_ontext));
cls->defineProperty("onbinary", nullptr, _SE(WebSocketServer_Connection_onbinary));
cls->defineProperty("onconnect", nullptr, _SE(WebSocketServer_Connection_onconnect));
cls->defineProperty("onerror", nullptr, _SE(WebSocketServer_Connection_onerror));
cls->defineProperty("onclose", nullptr, _SE(WebSocketServer_Connection_onclose));
cls->defineProperty("ondata", nullptr, _SE(WebSocketServer_Connection_ondata)); //deprecated since v3.7, please use onmessage to instead.
cls->defineProperty("onmessage", nullptr, _SE(WebSocketServer_Connection_onmessage));
cls->defineProperty("headers", _SE(WebSocketServer_Connection_headers), nullptr);
cls->defineProperty("protocols", _SE(WebSocketServer_Connection_protocols), nullptr);
cls->defineProperty("protocol", _SE(WebSocketServer_Connection_protocol), nullptr);
cls->defineProperty("readyState", _SE(WebSocketServer_Connection_readyState), nullptr);
cls->install();
se::Value tmp;
obj->getProperty("WebSocketServerConnection", &tmp);
tmp.toObject()->setProperty("CONNECTING", se::Value(cc::network::WebSocketServerConnection::CONNECTING));
tmp.toObject()->setProperty("OPEN", se::Value(cc::network::WebSocketServerConnection::OPEN));
tmp.toObject()->setProperty("CLOSING", se::Value(cc::network::WebSocketServerConnection::CLOSING));
tmp.toObject()->setProperty("CLOSED", se::Value(cc::network::WebSocketServerConnection::CLOSED));
JSBClassType::registerClass<cc::network::WebSocketServerConnection>(cls);
__jsb_WebSocketServer_Connection_class = cls;
se::ScriptEngine::getInstance()->clearException();
return true;
}

View File

@@ -0,0 +1,35 @@
/****************************************************************************
Copyright (c) 2019-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 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.
****************************************************************************/
#pragma once
#include "cocos/bindings/jswrapper/SeApi.h"
namespace se {
class Object;
class Value;
} // namespace se
SE_DECLARE_FINALIZE_FUNC(WebSocketServer_finalize);
bool register_all_websocket_server(se::Object *obj);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
/****************************************************************************
Copyright (c) 2017-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 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.
****************************************************************************/
#pragma once
namespace se {
class Object;
}
bool register_all_xmlhttprequest(se::Object *global); // NOLINT (readability-identifier-naming)