#include "NativeMgr.h" #include #include #include #include #include #include "arkui/native_node.h" #include "arkui/native_node_napi.h" #include "arkui/native_interface.h" #include "common.h" #include #include #include #define COLUMN_MARGIN 10 #define XC_WIDTH 800 #define XC_HEIGHT 600 #define ARG_CNT 2 #ifndef NATIVE_TAG #define NATIVE_TAG "NativeMgr" #endif #include "arkui/ui_input_event.h" namespace NativeOpenCAX { // [Start plugin_manager_cpp] // plugin_manager.cpp std::unordered_map NativeMgr::nodeHandleMap_; std::unordered_map NativeMgr::callbackMap_; ArkUI_NativeNodeAPI_1 *nodeAPI = reinterpret_cast(OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1")); // [StartExclude plugin_manager_cpp] OH_NativeXComponent_Callback NativeMgr::xSurfaceTouchEventCallBack; OH_NativeXComponent_MouseEvent_Callback NativeMgr::xMouseEventCallBack; std::string NativeMgr::crtXCompId; NativeMgr NativeMgr::pluginManager_; OCCTMgr OCCTMgr::occtMgr; std::unordered_map NativeMgr::NxInfos; int32_t NativeMgr::hasDraw_ = 0; int32_t NativeMgr::hasChangeColor_ = 0; static std::mutex mapMutex; std::string uuid_v4() { // 使用当前时间戳和随机数生成UUID auto timestamp = std::chrono::high_resolution_clock::now().time_since_epoch().count(); std::random_device rd; std::mt19937_64 gen(rd()); std::uniform_int_distribution dis(0, std::numeric_limits::max()); uint64_t random_part = dis(gen); // 合并时间戳和随机数,并转换为UUID格式 uint64_t full_uuid = (timestamp << 32) | (random_part & 0xFFFFFFFF); std::stringstream ss; ss << std::hex << std::uppercase << std::setw(8) << std::setfill('0') << (full_uuid & 0xFFFFFFFF) << "-" << std::setw(4) << std::setfill('0') << (full_uuid >> 32 & 0xFFFF) << "-4" // UUID版本4,中间四位固定为04xx << std::setw(3) << std::setfill('0') << (random_part >> 48 & 0x0FFF | 0x4000) // 设置版本号和一些随机位 << "-" << std::setw(4) << std::setfill('0') << (random_part >> 32 & 0xFFFF) << "-" << std::setw(12) << std::setfill('0') << (random_part & 0xFFFFFFFFFFFF); return ss.str(); } NativeMgr::~NativeMgr() { OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "~NativeMgr"); nativeXComponentMap_.clear(); std::lock_guard lock(mapMutex); OCCTMgr::GetInstance()->destroy(crtXCompId); for (auto iter = pluginManagerMap_.begin(); iter != pluginManagerMap_.end(); ++iter) { if (iter->second != nullptr) { delete iter->second; iter->second = nullptr; } } pluginManagerMap_.clear(); } void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) { // [StartExclude plugin_on_surface_created] OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB"); //主动关闭CPU访问窗口缓冲区数据降低功耗 uint64_t usage = 0; int32_t ret2 = OH_NativeWindow_NativeWindowHandleOpt((OHNativeWindow*)window, SET_USAGE, usage); int32_t ret; char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { return; } std::string id(idStr); OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB id=%{public}s", id.c_str()); // [EndExclude plugin_on_surface_created] // 初始化环境与绘制背景 auto *pluginManger = NativeMgr::GetInstance(); pluginManger->OnSurfaceCreated(component, window); } void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window) { // [StartExclude plugin_on_surface_changed] OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceChangedCB"); int32_t ret; char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { return; } std::string id(idStr); // [EndExclude plugin_on_surface_changed] auto *pluginManger = NativeMgr::GetInstance(); // 封装OnSurfaceChanged方法 pluginManger->OnSurfaceChanged(component, window); } void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window) { // [StartExclude plugin_on_surface_destroyed] OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceDestroyedCB"); int32_t ret; char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { return; } std::string id(idStr); // [EndExclude plugin_on_surface_destroyed] auto *pluginManger = NativeMgr::GetInstance(); pluginManger->OnSurfaceDestroyed(component, window); } //NativeMgr回调 void NativeMgr::OnSurfaceCreated(OH_NativeXComponent *component, void *window) { OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceCreated"); if (!window) { OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "ERROR: window is NULL in OnSurfaceCreated!"); return; } OH_NativeXComponent_GetXComponentSize(component, window, &bfWidth, &bfHeight); std::lock_guard lock(mapMutex); if(!OCCTMgr::GetInstance()->findRenderThread(crtXCompId)){ HILOG_ERROR(NATIVE_TAG,"uint64_t bfSize:%{public}dX%{public}d",bfWidth,bfHeight); OCCTMgr::GetInstance()->initOCCTMgr(); } OCCTMgr::GetInstance()->createReaderThread(crtXCompId, bfWidth, bfHeight, reinterpret_cast(window)); } void NativeMgr::OnSurfaceDestroyed(OH_NativeXComponent *component, void *window) { OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceDestroyed"); { std::lock_guard lock(mapMutex); OCCTMgr::GetInstance()->destroy(crtXCompId); } } void NativeMgr::OnSurfaceChanged(OH_NativeXComponent *component, void *window) { OH_NativeXComponent_GetXComponentSize(component, window, &afWidth, &afHeight); { if(bfWidth==afWidth && bfHeight==afHeight){ return; } std::lock_guard lock(mapMutex); if (OCCTMgr::GetInstance()->findRenderThread(crtXCompId)) { HILOG_ERROR(NATIVE_TAG,"uint64_t Size:%{public}dX%{public}d",bfWidth,bfHeight); bfWidth=afWidth; bfHeight=afHeight; auto renderThread=OCCTMgr::GetInstance()->getRenderThread(crtXCompId); if(renderThread!=nullptr){ renderThread->resizeWindow(bfWidth, bfHeight); } } } } void OnMouseEventCB(OH_NativeXComponent* component, void* window) { auto* pluginManager = NativeMgr::GetInstance(); if (!pluginManager || !window) { return; } auto *pluginManger = NativeMgr::GetInstance(); pluginManger->OnMouseEvent(component, window); } void NativeMgr::OnMouseEvent(OH_NativeXComponent *comp, void *win) { int32_t ret; OH_NativeXComponent_MouseEvent mouseEvent; ret = OH_NativeXComponent_GetMouseEvent(comp, win, &mouseEvent); if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { return; } OH_NativeXComponent_ExtraMouseEventInfo* extra = NULL; ret = OH_NativeXComponent_GetExtraMouseEventInfo(comp, &extra); if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { return; } //Test Mouse MIDDLE_BUTTON Long Press HILOG_WARN(NATIVE_TAG, "ExtraMouseEventInfo:%{public}d",extra); std::lock_guard lock(mapMutex); //通过时间戳判断事件唯一性.保证单一时间戳只触发一次事件 if(mouseEvent.timestamp==NativeMgr::timestamp){ return; } NativeMgr::timestamp=mouseEvent.timestamp; auto renderThread=OCCTMgr::GetInstance()->getRenderThread(crtXCompId); if(renderThread==nullptr){ HILOG_WARN(NATIVE_TAG, "Render thread not found for rotation."); return; } float curtX,curtY; //开发测试模拟器输出鼠标按钮和时间类型,时间戳 bool _log=true; if(_log){ HILOG_INFO(NATIVE_TAG, "ALLButton:%{public}d",mouseEvent.button); HILOG_INFO(NATIVE_TAG, "ALLAction:%{public}d",mouseEvent.action); HILOG_INFO(NATIVE_TAG, "ALLTimestamp:%{public}d",mouseEvent.timestamp); } //鼠标滚轮缩放实现 //以下代码为采用按住鼠标右键不放进行Move改变Carmera的旋转视角 //旋转视角分为三种模式: //自由模式.基于世界坐标系0,0,0 //模型中心.通过边界盒计算模型的中心点,进行旋转 //基于鼠标按下右键点进行旋转 //按住Ctrl不放同时按住鼠标左键不放进行Carmera的移动 //移动模式:均为鼠标点按下后记录坐标增量移动 //鼠标按下并且事件为鼠标中键 if(mouseEvent.button==OH_NATIVEXCOMPONENT_LEFT_BUTTON&&mouseEvent.action==OH_NATIVEXCOMPONENT_MOUSE_PRESS){ if(NativeMgr::isMouseMiddleBtnPressed){ NativeMgr::isMouseMiddleBtnPressed=false; return; } //记录按下时候的X.Y坐标 NativeMgr::lastMouseX_=mouseEvent.x; NativeMgr::lastMouseY_=mouseEvent.y; NativeMgr::isMouseMiddleBtnPressed = true; //HILOG_WARN(NATIVE_TAG, "AtlastMouseX:%{public}d",NativeMgr::lastMouseX_); //HILOG_WARN(NATIVE_TAG, "AtlastMouseY:%{public}d",NativeMgr::lastMouseY_); //HILOG_WARN(NATIVE_TAG, "AtButton:%{public}d",mouseEvent.button); //HILOG_WARN(NATIVE_TAG, "AtButtonAction:%{public}d",mouseEvent.action); //HILOG_WARN(NATIVE_TAG, "AtisMouseMiddleBtnPressed:%{public}d",NativeMgr::isMouseMiddleBtnPressed); }else if(mouseEvent.action==OH_NATIVEXCOMPONENT_MOUSE_MOVE&&NativeMgr::isMouseMiddleBtnPressed){ // 计算鼠标移动距离 float deltaX = curtX - NativeMgr::lastMouseX_; float deltaY = curtY - NativeMgr::lastMouseY_; // 将像素移动量映射到旋转角度 // 这里的系数可以根据需要调整灵敏度 float rotationSpeed = 0.001f; float angleX = deltaX * rotationSpeed; float angleY = deltaY * rotationSpeed; // 通知渲染线程执行旋转 // 由于渲染在线程里,需要通过命令队列发送指令 renderThread->setRotation(angleX, angleY); // 更新最后的位置 //NativeMgr::lastMouseX_ = deltaX; //NativeMgr::lastMouseY_ = deltaY; //HILOG_WARN(NATIVE_TAG, "MoveAngleX:%{public}d",angleX); //HILOG_WARN(NATIVE_TAG, "MoveAngleY:%{public}d",angleY); //HILOG_WARN(NATIVE_TAG, "MoveButton:%{public}d",mouseEvent.button); //HILOG_WARN(NATIVE_TAG, "MoveButtonAction:%{public}d",mouseEvent.action); //HILOG_WARN(NATIVE_TAG, "MoveIsMouseMiddleBtnPressed:%{public}d",NativeMgr::isMouseMiddleBtnPressed); } } static std::string value2String(napi_env env, napi_value value) { size_t stringSize = 0; napi_get_value_string_utf8(env, value, nullptr, 0, &stringSize); std::string valueString; valueString.resize(stringSize); napi_get_value_string_utf8(env, value, &valueString[0], stringSize + 1, &stringSize); return valueString; } void DispatchTouchEventCB(OH_NativeXComponent* component, void* window) { // [StartExclude plugin_dispatch_touch_event] OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB"); int32_t ret; char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { return; } std::string id(idStr); // [EndExclude plugin_dispatch_touch_event] auto *pluginManger = NativeMgr::GetInstance(); pluginManger->DispatchTouchEvent(component, window); } // XComponent回调事件 NativeMgr::NativeMgr() { xSurfaceTouchEventCallBack.OnSurfaceCreated = OnSurfaceCreatedCB; xSurfaceTouchEventCallBack.OnSurfaceChanged = OnSurfaceChangedCB; xSurfaceTouchEventCallBack.OnSurfaceDestroyed = OnSurfaceDestroyedCB; xSurfaceTouchEventCallBack.DispatchTouchEvent=DispatchTouchEventCB; xMouseEventCallBack.DispatchMouseEvent= OnMouseEventCB; } // 创建节点组件 ArkUI_NodeHandle CreateNodeHandle(void* userData) { auto ud=static_cast(userData); HILOG_INFO(NATIVE_TAG,"CreateNodeHandle NODE ID:%{public}s",ud->nid.c_str()); HILOG_INFO(NATIVE_TAG,"CreateNodeHandle XCOMP ID:%{public}s",ud->xid.c_str()); // 创建Node也名创建ROW Column等容器 ArkUI_NodeHandle nodeHandel = nodeAPI->createNode(ARKUI_NODE_RELATIVE_CONTAINER); // 节点默认宽度or高度 ArkUI_NumberValue nodeMarginData[] = {{.u32 = 0}, {.f32 = 0}}; // ArkUI_AttributeItem // 参数1:指向数值数组 // 参数2:数组元素个数 // 参数3:属性名(可隐藏) ArkUI_AttributeItem nodeMarginItem = {nodeMarginData}; // 设置Node宽度or高度 nodeAPI->setAttribute(nodeHandel, NODE_MARGIN, &nodeMarginItem); NativeMgr::nodeHandleMap_[ud->nid]=nodeHandel; // 创建XComponent组件 // 组件类型Item ArkUI_NumberValue comTypeData[] = {ARKUI_XCOMPONENT_TYPE_SURFACE}; ArkUI_AttributeItem comTypeItem = {comTypeData}; // 组件ID Item ArkUI_AttributeItem comIdItem = {.string = ud->xid.c_str()}; // 组件Surface Size // 创建组件 ArkUI_NodeHandle xc; xc = nodeAPI->createNode(ARKUI_NODE_XCOMPONENT); // 设置XComponent组件属性 nodeAPI->setAttribute(xc, NODE_XCOMPONENT_TYPE, &comTypeItem); nodeAPI->setAttribute(xc, NODE_XCOMPONENT_ID, &comIdItem); // 焦点设置 ArkUI_NumberValue focusable[] = {1}; focusable[0].i32 = 1; ArkUI_AttributeItem focusableItem = {focusable}; nodeAPI->setAttribute(xc, NODE_FOCUSABLE, &focusableItem); // 节点ID ArkUI_AttributeItem nodeIdItem = {.string = ud->nid.c_str()}; nodeAPI->setAttribute(xc, NODE_ID, &nodeIdItem); auto *nativeXComponent = OH_NativeXComponent_GetNativeXComponent(xc); if (!nativeXComponent) { HILOG_ERROR(NATIVE_TAG,"GetNativeXComponent error"); return nodeHandel; } // 注册XComponent回调函数 OH_NativeXComponent_RegisterCallback(nativeXComponent, &NativeMgr::xSurfaceTouchEventCallBack); //注册XComponent组件鼠标回调事件 OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent, &NativeMgr::xMouseEventCallBack); // nodeAPI->registerNodeEvent(xc, NODE_ON_MOUSE, 1, &xc); // nodeAPI->registerNodeEvent(xc, NODE_ON_AXIS, 1, &xc); // nodeAPI->addNodeEventReceiver(xc, [](ArkUI_NodeEvent *event) { // auto *inputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event); // auto eventType = OH_ArkUI_UIInputEvent_GetType(inputEvent); // if (OH_ArkUI_NodeEvent_GetEventType(event) == NODE_ON_AXIS ) { // HILOG_WARN(NATIVE_TAG, "NODE_ON_AXIS:%{public}d",OH_ArkUI_NodeEvent_GetEventType(event)); // } // if (eventType == ARKUI_UIINPUTEVENT_TYPE_MOUSE) { // auto action = OH_ArkUI_MouseEvent_GetMouseAction(inputEvent); // auto button= OH_ArkUI_MouseEvent_GetMouseButton(inputEvent); // //HILOG_WARN(NATIVE_TAG, "MouseAction:%{public}d",action); // //HILOG_WARN(NATIVE_TAG, "MouseButton:%{public}d",button); // // int32_t buttonArray[10]; // int32_t arraySize = sizeof(buttonArray) / sizeof(buttonArray[0]); // int32_t actualCount = arraySize; // 将数组大小存入actualCount,作为输入值 // int32_t ret = OH_ArkUI_MouseEvent_GetPressedButtons(inputEvent, buttonArray, &actualCount); // // // --- 步骤 3: 检查API调用结果 --- // if (ret != 0) { // HILOG_WARN(NATIVE_TAG, "Error getting pressed mouse buttons. Error code: %{public}d\n", ret); // return; // } // for (int i = 0; i < actualCount; ++i) { // HILOG_WARN(NATIVE_TAG, "Curt code: %{public}d\n", buttonArray[i]); // // 根据常见的鼠标按钮ID进行解释 (具体ID定义请查阅官方文档) // // 通常 1=主按钮(左键), 2=辅助按钮(右键), 3=中间按钮(滚轮) // switch (buttonArray[i]) { // case 1: HILOG_WARN(NATIVE_TAG, "MouseButton:Left");break; // case 2: HILOG_WARN(NATIVE_TAG, "MouseButton:Right");break; // case 3: HILOG_WARN(NATIVE_TAG, "MouseButton:Middle"); break; // default: printf("(Other_%d) ", buttonArray[i]); break; // } // } // } // }); // 组件类型 auto comTypeRet = nodeAPI->getAttribute(xc, NODE_XCOMPONENT_TYPE); HILOG_INFO(NATIVE_TAG,"XCom type: %{public}d",comTypeRet->value[0].i32); // 组件ID auto comIdRet = nodeAPI->getAttribute(xc, NODE_XCOMPONENT_ID); HILOG_INFO(NATIVE_TAG,"XCom ID: %{public}d",comIdRet->string); // 增加组件到节点 nodeAPI->addChild(nodeHandel, xc); return nodeHandel; } // Native侧创建Node napi_value NativeMgr::initNativeNode(napi_env env, napi_callback_info info) { if ((env == nullptr) || (info == nullptr)) { HILOG_ERROR(NATIVE_TAG,"CreateNativeNode env or info is null"); return nullptr; } //获取传入NodeContent实例 size_t argCnt = 4; napi_value args[4] = {nullptr}; if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) { HILOG_ERROR(NATIVE_TAG,"CreateNativeNode napi_get_cb_info failed"); } bool type; NXInfo* nxInfo=new NXInfo; nxInfo->nid=value2String(env, args[0]); nxInfo->xid=value2String(env, args[1]); napi_get_value_bool(env, args[2], &type); crtXCompId=nxInfo->xid; NxInfos[nxInfo->xid]=nxInfo; ArkUI_NodeContentHandle _nodeContentHandle = nullptr; // 获取ArkTS侧创建的NodeContent对象,映射到Native侧的 OH_ArkUI_GetNodeContentFromNapiValue(env, args[3], &_nodeContentHandle); // 查询指定的模块接口名 nodeAPI = reinterpret_cast(OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1")); //下面的代码主要用于创建一个Native侧和arkui侧绑定数据的结构传递传输的操作 //node_data可以理解为一个结构体等等之类的指针 // 生成节点名采用NODE_ID_+UUID HILOG_INFO(NATIVE_TAG,"Native NODE ID:%{public}s",nxInfo->nid.c_str()); HILOG_INFO(NATIVE_TAG,"Native XCOMP ID:%{public}s",nxInfo->xid.c_str()); // 在NodeContent对象上保存自定义数据。 int32_t ret = OH_ArkUI_NodeContent_SetUserData(_nodeContentHandle, static_cast(nxInfo)); if (ret != ARKUI_ERROR_CODE_NO_ERROR) { HILOG_ERROR(NATIVE_TAG,"setUserData failed error=%{public}d",ret); } if (nodeAPI != nullptr && nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) { auto nodeContentEvent = [](ArkUI_NodeContentEvent *event) { // 获取Node连接事件的对应Node的Handle ArkUI_NodeContentHandle handle = OH_ArkUI_NodeContentEvent_GetNodeContentHandle(event); // 获取对应Handle的UserData void* ud=OH_ArkUI_NodeContent_GetUserData(handle); if (OH_ArkUI_NodeContentEvent_GetEventType(event) == NODE_CONTENT_EVENT_ON_ATTACH_TO_WINDOW) { ArkUI_NodeHandle testNode; if (ud) { testNode = CreateNodeHandle(ud); delete ud; ud = nullptr; } else { //testNode = CreateNodeHandle(nullptr); } // 向NodeContent中添加子组件 OH_ArkUI_NodeContent_AddNode(handle, testNode); } }; OH_ArkUI_NodeContent_RegisterCallback(_nodeContentHandle, nodeContentEvent); } return nullptr; } void NativeMgr::DispatchTouchEvent(OH_NativeXComponent* component, void* window) { OH_NativeXComponent_TouchEvent touchEvent_; int32_t ret = OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent_); std::lock_guard lock(mapMutex); //通过时间戳判断事件唯一性.保证单一时间戳只触发一次事件 if(touchEvent_.timeStamp==NativeMgr::timestamp){ return; } NativeMgr::timestamp=touchEvent_.timeStamp; auto renderThread=OCCTMgr::GetInstance()->getRenderThread(crtXCompId); if(renderThread==nullptr){ HILOG_WARN(NATIVE_TAG, "Render thread not found for rotation."); return; } if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { float tiltX = 2.2; float tiltY = 2.2; OH_NativeXComponent_TouchPointToolType toolType = OH_NativeXComponent_TouchPointToolType::OH_NATIVEXCOMPONENT_TOOL_TYPE_LENS; OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType); OH_NativeXComponent_GetTouchPointTiltX(component, 0, &tiltX); OH_NativeXComponent_GetTouchPointTiltY(component, 0, &tiltY); OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "Touch Info : x=%{public}f, y=%{public}f screenx=%{public}f, screeny=%{public}f," "type=%{public}d, force=%{public}f, tiltX=%{public}f, tiltY=%{public}f, toolType=%{public}d", touchEvent_.x, touchEvent_.y, touchEvent_.screenX, touchEvent_.screenY, touchEvent_.type, touchEvent_.force, tiltX, tiltY, toolType); //判断触控点数量 //当触点为1则判定为单指,处理单指对应事件 if(touchEvent_.numPoints==1){ //触屏按下记录按下点坐标 if(touchEvent_.type ==OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_DOWN){ NativeMgr::x=touchEvent_.x; NativeMgr::y=touchEvent_.y; } //按下并移动,计算移动增量需要乘以灵敏度 if (touchEvent_.type == OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_MOVE) { float dtx=(NativeMgr::x-touchEvent_.x)*0.1; float dty=(NativeMgr::y-touchEvent_.y)*0.1; renderThread->setRotation(dtx, dty); OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent_); NativeMgr::x=touchEvent_.x; NativeMgr::y=touchEvent_.y; } //的判断为双指,处理双指事件功能(缩放视距) } else if(touchEvent_.numPoints==2) { //双指同时处于按下状态,并且移动 if(touchEvent_.touchPoints[0].isPressed &&touchEvent_.touchPoints[1].isPressed){ //当双指按下时候,分别记录每个指的坐标 //双指移动,计算移动位移量,同时根据移动缩放因子计算视距,从调整相机相对于模型的距离.从而实现双指缩放 }else if(touchEvent_.type==OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_MOVE){ } } } else { OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "touch fail"); } int32_t size = 0; OH_NativeXComponent_HistoricalPoint *points = nullptr; if (OH_NativeXComponent_GetHistoricalPoints(component, window, &size, &points) == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "XComponent_Native", "HistoricalPoints size=%{public}d", size); for (auto i = 0; i < size; i++) { auto point = points[i]; OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "XComponent_Native", "HistoricalPoint %{public}d Info : id=%{public}d, x=%{public}f, y=%{public}f, " "type=%{public}d, timeStamp=%{public}lld, sourceTool=%{public}d", i, point.id, point.x, point.y, point.type, point.timeStamp, point.sourceTool); } } } //设置期望帧率 napi_value NativeMgr::SetFrameRate(napi_env env, napi_callback_info info) { size_t argc = 4; napi_value args[4] = {nullptr}; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); std::string nodeId = value2String(env, args[0]); auto node = nodeHandleMap_[nodeId]; int32_t min = 0; napi_get_value_int32(env, args[FIRST_ARG], &min); int32_t max = 0; napi_get_value_int32(env, args[SECOND_ARG], &max); int32_t expected = 0; napi_get_value_int32(env, args[THIRD_ARG], &expected); OH_NativeXComponent_ExpectedRateRange range = {.min = min, .max = max, .expected = expected}; OH_ArkUI_XComponent_SetExpectedFrameRateRange(node, range); // 设置期望帧率 return nullptr; } napi_value NativeMgr::SetNeedSoftKeyboard(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2] = {nullptr}; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); std::string nodeId = value2String(env, args[0]); ArkUI_NodeHandle node; if (nodeHandleMap_.find(nodeId) == nodeHandleMap_.end()) { OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "SetNeedSoftKeyboard", "nodeId not exit error"); return nullptr; } node = nodeHandleMap_[nodeId]; bool needSoftKeyboard = false; napi_get_value_bool(env, args[1], &needSoftKeyboard); OH_ArkUI_XComponent_SetNeedSoftKeyboard(node, needSoftKeyboard); // 设置是否需要软键盘 return nullptr; } napi_value NativeMgr::NapiLoadModel(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); std::string path = value2String(env, args[0]); { std::lock_guard lock(mapMutex); auto renderThread=OCCTMgr::GetInstance()->getRenderThread(crtXCompId); if(renderThread==nullptr){ HILOG_WARN(NATIVE_TAG, "Render thread not found for rotation."); }else{ renderThread->loadModel(std::string(path)); } } return nullptr; } //切换视图 napi_value NativeMgr::SwitchView(napi_env env, napi_callback_info info){ size_t argc = 1; napi_value args[1]; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); std::string viewName = value2String(env, args[0]); { std::lock_guard lock(mapMutex); auto renderThread=OCCTMgr::GetInstance()->getRenderThread(crtXCompId); if(renderThread==nullptr){ HILOG_WARN(NATIVE_TAG, "Render thread not found for rotation."); }else{ renderThread->swicthView(viewName); } } return nullptr; } //显示模型边界 napi_value NativeMgr::displayModelEdges(napi_env env, napi_callback_info info){ } //显示模型线框 napi_value NativeMgr::displayHLR(napi_env env, napi_callback_info info){ } //显示隐藏线 napi_value NativeMgr::displayHL(napi_env env, napi_callback_info info){ } } // namespace NativeOpenCAX