diff --git a/entry/src/main/cpp/CMakeLists.txt b/entry/src/main/cpp/CMakeLists.txt index 97c40974..9087bcc4 100644 --- a/entry/src/main/cpp/CMakeLists.txt +++ b/entry/src/main/cpp/CMakeLists.txt @@ -3,13 +3,28 @@ cmake_minimum_required(VERSION 3.5.0) project(OpenCAX) set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) - -if(DEFINED PACKAGE_FIND_FILE) - include(${PACKAGE_FIND_FILE}) -endif() +add_definitions(-DOHOS_PLATFORM) +#if(DEFINED PACKAGE_FIND_FILE) +# include(${PACKAGE_FIND_FILE}) +#endif() include_directories(${NATIVERENDER_ROOT_PATH} ${NATIVERENDER_ROOT_PATH}/include) -add_library(entry SHARED napi_init.cpp) -target_link_libraries(entry PUBLIC libace_napi.z.so) \ No newline at end of file +add_library(entry SHARED + render/egl_core.h + render/egl_core.cpp + render/plugin_render.h + render/plugin_render.cpp + manager/plugin_manager.h + manager/plugin_manager.cpp + napi_init.cpp + common/common.h ) +find_library(EGL-lib EGL) +find_library(GLES-lib GLESv3) +find_library(hilog-lib hilog_ndk.z) +find_library(libace-lib ace_ndk.z) +find_library(libnapi-lib ace_napi.z) +find_library(libuv-lib uv) + +target_link_libraries(entry PUBLIC ${EGL-lib} ${GLES-lib} ${hilog-lib} ${libace-lib} ${libnapi-lib} ${libuv-lib} libnative_window.so) \ No newline at end of file diff --git a/entry/src/main/cpp/common/common.h b/entry/src/main/cpp/common/common.h new file mode 100644 index 00000000..04a5445f --- /dev/null +++ b/entry/src/main/cpp/common/common.h @@ -0,0 +1,21 @@ +// +// Created on 2025/11/24. +// +// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, +// please include "napi/native_api.h". + +#ifndef NATIVE3D_COMMON_H +#define NATIVE3D_COMMON_H +#include +#include +#include +#include +#include + +namespace NativeXComponentDemo { +/** + * Log print domain. + */ +const unsigned int LOG_PRINT_DOMAIN = 0xFF00; +} // namespace NativeXComponentDemo +#endif //NATIVE3D_COMMON_H diff --git a/entry/src/main/cpp/manager/plugin_manager.cpp b/entry/src/main/cpp/manager/plugin_manager.cpp new file mode 100644 index 00000000..280ccff1 --- /dev/null +++ b/entry/src/main/cpp/manager/plugin_manager.cpp @@ -0,0 +1,220 @@ +// +// Created on 2025/11/24. +// +// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, +// please include "napi/native_api.h". + +#include "plugin_manager.h" +#include +#include +#include +#include +#include +#include "../common/common.h" +#include + +namespace NativeXComponentDemo { +// [Start xcomponent_manager_cpp] +namespace { + // 解析从ArkTS侧传入的surfaceId,此处surfaceId是一个64位int值 + int64_t ParseId(napi_env env, napi_callback_info info) + { + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ParseId", "env or info is null"); + return -1; + } + size_t argc = 1; + napi_value args[1] = {nullptr}; + if (napi_ok != napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ParseId", "GetContext napi_get_cb_info failed"); + return -1; + } + int64_t value = 0; + bool lossless = true; + if (napi_ok != napi_get_value_bigint_int64(env, args[0], &value, &lossless)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ParseId", "Get value failed"); + return -1; + } + return value; + } +} +// [StartExclude xcomponent_manager_cpp] +std::unordered_map PluginManager::pluginRenderMap_; +std::unordered_map PluginManager::windowMap_; + +PluginManager::~PluginManager() +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "~PluginManager"); + for (auto iter = pluginRenderMap_.begin(); iter != pluginRenderMap_.end(); ++iter) { + if (iter->second != nullptr) { + delete iter->second; + iter->second = nullptr; + } + } + pluginRenderMap_.clear(); + for (auto iter = windowMap_.begin(); iter != windowMap_.end(); ++iter) { + if (iter->second != nullptr) { + delete iter->second; + iter->second = nullptr; + } + } + windowMap_.clear(); +} +// [EndExclude xcomponent_manager_cpp] + +PluginRender* PluginManager::GetPluginRender(int64_t& id) +{ + if (pluginRenderMap_.find(id) != pluginRenderMap_.end()) { + return pluginRenderMap_[id]; + } + return nullptr; +} + +// 设置SurfaceId,基于SurfaceId完成对NativeWindow的初始化 +napi_value PluginManager::SetSurfaceId(napi_env env, napi_callback_info info) +{ + int64_t surfaceId = ParseId(env, info); + OHNativeWindow *nativeWindow; + PluginRender *pluginRender; + if (windowMap_.find(surfaceId) == windowMap_.end()) { + OH_NativeWindow_CreateNativeWindowFromSurfaceId(surfaceId, &nativeWindow); + windowMap_[surfaceId] = nativeWindow; + } else { + return nullptr; + } + if (pluginRenderMap_.find(surfaceId) == pluginRenderMap_.end()) { + pluginRender = new PluginRender(surfaceId); + pluginRenderMap_[surfaceId] = pluginRender; + } + pluginRender->InitNativeWindow(nativeWindow); + return nullptr; +} + +// 销毁Surface +napi_value PluginManager::DestroySurface(napi_env env, napi_callback_info info) +{ + int64_t surfaceId = ParseId(env, info); + auto pluginRenderMapIter = pluginRenderMap_.find(surfaceId); + if (pluginRenderMapIter != pluginRenderMap_.end()) { + delete pluginRenderMapIter->second; + pluginRenderMap_.erase(pluginRenderMapIter); + } + auto windowMapIter = windowMap_.find(surfaceId); + if (windowMapIter != windowMap_.end()) { + OH_NativeWindow_DestroyNativeWindow(windowMapIter->second); + windowMap_.erase(windowMapIter); + } + return nullptr; +} + +// 根据传入的surfaceId、width、height实现Surface大小的变动 +napi_value PluginManager::ChangeSurface(napi_env env, napi_callback_info info) +{ + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", + "ChangeSurface: OnLoad env or info is null"); + return nullptr; + } + int64_t surfaceId = 0; + size_t argc = 3; + napi_value args[3] = {nullptr}; + + if (napi_ok != napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", + "ChangeSurface: GetContext napi_get_cb_info failed"); + } + bool lossless = true; + int index = 0; + if (napi_ok != napi_get_value_bigint_int64(env, args[index++], &surfaceId, &lossless)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "ChangeSurface: Get value failed"); + } + double width; + if (napi_ok != napi_get_value_double(env, args[index++], &width)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "ChangeSurface: Get width failed"); + } + double height; + if (napi_ok != napi_get_value_double(env, args[index++], &height)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "ChangeSurface: Get height failed"); + } + auto pluginRender = GetPluginRender(surfaceId); + if (pluginRender == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "ChangeSurface: Get pluginRender failed"); + return nullptr; + } + pluginRender->UpdateNativeWindowSize(width, height); + return nullptr; +} + +// 实现改变绘制图形颜色的功能 +napi_value PluginManager::ChangeColor(napi_env env, napi_callback_info info) +{ + int64_t surfaceId = ParseId(env, info); + auto pluginRender = GetPluginRender(surfaceId); + if (pluginRender == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "ChangeColor: Get pluginRender failed"); + return nullptr; + } + pluginRender->ChangeColor(); // 参考Native XComponent场景ChangeColor实现 + return nullptr; +} + +// 实现EGL绘画逻辑 +napi_value PluginManager::DrawPattern(napi_env env, napi_callback_info info) +{ + int64_t surfaceId = ParseId(env, info); + auto pluginRender = GetPluginRender(surfaceId); + if (pluginRender == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "DrawPattern: Get pluginRender failed"); + return nullptr; + } + pluginRender->DrawPattern(); + return nullptr; +} + +// 获得xcomponent状态,并返回至ArkTS侧 +napi_value PluginManager::GetXComponentStatus(napi_env env, napi_callback_info info) +{ + int64_t surfaceId = ParseId(env, info); + auto pluginRender = GetPluginRender(surfaceId); + if (pluginRender == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", + "GetXComponentStatus: Get pluginRender failed"); + return nullptr; + } + napi_value hasDraw; + napi_value hasChangeColor; + napi_status ret = napi_create_int32(env, pluginRender->HasDraw(), &(hasDraw)); + if (ret != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", + "GetXComponentStatus: napi_create_int32 hasDraw_ error"); + return nullptr; + } + ret = napi_create_int32(env, pluginRender->HasChangedColor(), &(hasChangeColor)); + if (ret != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", + "GetXComponentStatus: napi_create_int32 hasChangeColor_ error"); + return nullptr; + } + napi_value obj; + ret = napi_create_object(env, &obj); + if (ret != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, + "PluginManager", "GetXComponentStatus: napi_create_object error"); + return nullptr; + } + ret = napi_set_named_property(env, obj, "hasDraw", hasDraw); + if (ret != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", + "GetXComponentStatus: napi_set_named_property hasDraw error"); + return nullptr; + } + ret = napi_set_named_property(env, obj, "hasChangeColor", hasChangeColor); + if (ret != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", + "GetXComponentStatus: napi_set_named_property hasChangeColor error"); + return nullptr; + } + return obj; +} +// [End xcomponent_manager_cpp] +} // namespace NativeXComponentDemo diff --git a/entry/src/main/cpp/manager/plugin_manager.h b/entry/src/main/cpp/manager/plugin_manager.h new file mode 100644 index 00000000..df41fd9b --- /dev/null +++ b/entry/src/main/cpp/manager/plugin_manager.h @@ -0,0 +1,36 @@ +// +// Created on 2025/11/24. +// +// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, +// please include "napi/native_api.h". + +#ifndef NATIVE3D_PLUGIN_MANAGER_H +#define NATIVE3D_PLUGIN_MANAGER_H + +#include +#include +#include +#include +#include +#include "../render/plugin_render.h" + +namespace NativeXComponentDemo { +// [Start xcomponent_define_class] +// PluginManager类定义 +class PluginManager { +public: + ~PluginManager(); + static PluginRender* GetPluginRender(int64_t& id); + static napi_value ChangeColor(napi_env env, napi_callback_info info); + static napi_value DrawPattern(napi_env env, napi_callback_info info); + static napi_value SetSurfaceId(napi_env env, napi_callback_info info); + static napi_value ChangeSurface(napi_env env, napi_callback_info info); + static napi_value DestroySurface(napi_env env, napi_callback_info info); + static napi_value GetXComponentStatus(napi_env env, napi_callback_info info); +public: + static std::unordered_map pluginRenderMap_; + static std::unordered_map windowMap_; +}; +// [End xcomponent_define_class] +} +#endif //NATIVE3D_PLUGIN_MANAGER_H diff --git a/entry/src/main/cpp/napi_init.cpp b/entry/src/main/cpp/napi_init.cpp index 987bd48b..16feac31 100644 --- a/entry/src/main/cpp/napi_init.cpp +++ b/entry/src/main/cpp/napi_init.cpp @@ -1,53 +1,56 @@ -#include "napi/native_api.h" - -static napi_value Add(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); - - napi_valuetype valuetype0; - napi_typeof(env, args[0], &valuetype0); - - napi_valuetype valuetype1; - napi_typeof(env, args[1], &valuetype1); - - double value0; - napi_get_value_double(env, args[0], &value0); - - double value1; - napi_get_value_double(env, args[1], &value1); - - napi_value sum; - napi_create_double(env, value0 + value1, &sum); - - return sum; - -} +#include +#include "common/common.h" +#include "manager/plugin_manager.h" +namespace NativeXComponentDemo { +// 在napi_init.cpp文件中,Init方法注册接口函数,从而将封装的C++方法传递出来,供ArkTS侧调用 EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) { + // [StartExclude xcomponent_init] + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Init", "Init begins"); + if ((env == nullptr) || (exports == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "env or exports is null"); + return nullptr; + } + // [EndExclude xcomponent_init] + // 向ArkTS侧暴露接口SetSurfaceId(),ChangeSurface(),DestroySurface(), + // DrawPattern(),ChangeColor(),GetXComponentStatus() napi_property_descriptor desc[] = { - { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr } + {"ChangeColor", nullptr, PluginManager::ChangeColor, + nullptr, nullptr, nullptr, napi_default, nullptr}, + {"SetSurfaceId", nullptr, PluginManager::SetSurfaceId, + nullptr, nullptr, nullptr, napi_default, nullptr}, + {"ChangeSurface", nullptr, PluginManager::ChangeSurface, + nullptr, nullptr, nullptr, napi_default, nullptr}, + {"GetXComponentStatus", nullptr, PluginManager::GetXComponentStatus, + nullptr, nullptr, nullptr, napi_default, nullptr}, + {"DrawPattern", nullptr, PluginManager::DrawPattern, + nullptr, nullptr, nullptr, napi_default, nullptr}, + {"DestroySurface", nullptr, PluginManager::DestroySurface, + nullptr, nullptr, nullptr, napi_default, nullptr} }; - napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "napi_define_properties failed"); + return nullptr; + } return exports; } EXTERN_C_END - -static napi_module demoModule = { +// 编写接口的描述信息,根据实际需要可以修改对应参数 +static napi_module entryModel = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, + // 入口函数 .nm_register_func = Init, + // 模块名称 .nm_modname = "entry", .nm_priv = ((void*)0), - .reserved = { 0 }, -}; - -extern "C" __attribute__((constructor)) void RegisterEntryModule(void) + .reserved = { 0 } }; +} // namespace NativeXComponentSample +// __attribute__((constructor))修饰的方法由系统自动调用,使用Node-API接口napi_module_register()传入模块描述信息进行模块注册 +extern "C" __attribute__((constructor)) void RegisterModule(void) { - napi_module_register(&demoModule); + napi_module_register(&NativeXComponentDemo::entryModel); } diff --git a/entry/src/main/cpp/render/egl_core.cpp b/entry/src/main/cpp/render/egl_core.cpp new file mode 100644 index 00000000..c7e0c3f1 --- /dev/null +++ b/entry/src/main/cpp/render/egl_core.cpp @@ -0,0 +1,613 @@ +// +// Created on 2025/11/24. +// +// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, +// please include "napi/native_api.h". + +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "egl_core.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "../common/common.h" +#include "plugin_render.h" + +namespace NativeXComponentDemo { +namespace { +constexpr int32_t NUM_4 = 4; +/** + * Vertex shader. + */ +const char VERTEX_SHADER[] = "#version 300 es\n" + "layout(location = 0) in vec4 a_position;\n" + "layout(location = 1) in vec4 a_color; \n" + "out vec4 v_color; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " v_color = a_color; \n" + "} \n"; + +/** + * Fragment shader. + */ +const char FRAGMENT_SHADER[] = "#version 300 es\n" + "precision mediump float; \n" + "in vec4 v_color; \n" + "out vec4 fragColor; \n" + "void main() \n" + "{ \n" + " fragColor = v_color; \n" + "} \n"; + +/** + * Background color #f4f4f4. + */ +const GLfloat BACKGROUND_COLOR[] = {244.0f / 255, 244.0f / 255, 244.0f / 255, 1.0f}; + +/** + * Draw color #7E8FFB. + */ +const GLfloat DRAW_COLOR[] = {126.0f / 255, 143.0f / 255, 251.0f / 255, 1.0f}; + +/** + * Change color #92D6CC. + */ +const GLfloat CHANGE_COLOR[] = {146.0f / 255, 214.0f / 255, 204.0f / 255, 1.0f}; + +/** + * Background area. + */ +const GLfloat BACKGROUND_RECTANGLE_VERTICES[] = { + -1.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, -1.0f, + -1.0f, -1.0f}; + +/** + * Get context parameter count. + */ +const size_t GET_CONTEXT_PARAM_CNT = 1; + +/** + * Fifty percent. + */ +const float FIFTY_PERCENT = 0.5; + +/** + * Pointer size. + */ +const GLint POINTER_SIZE = 2; + +/** + * Triangle fan size. + */ +const GLsizei TRIANGLE_FAN_SIZE = 4; + +/** + * Egl red size default. + */ +const int EGL_RED_SIZE_DEFAULT = 8; + +/** + * Egl green size default. + */ +const int EGL_GREEN_SIZE_DEFAULT = 8; + +/** + * Egl blue size default. + */ +const int EGL_BLUE_SIZE_DEFAULT = 8; + +/** + * Egl alpha size default. + */ +const int EGL_ALPHA_SIZE_DEFAULT = 8; + +/** + * Default x position. + */ +const int DEFAULT_X_POSITION = 0; + +/** + * Default y position. + */ +const int DEFAULT_Y_POSITION = 0; + +/** + * Gl red default. + */ +const GLfloat GL_RED_DEFAULT = 0.0; + +/** + * Gl green default. + */ +const GLfloat GL_GREEN_DEFAULT = 0.0; + +/** + * Gl blue default. + */ +const GLfloat GL_BLUE_DEFAULT = 0.0; + +/** + * Gl alpha default. + */ +const GLfloat GL_ALPHA_DEFAULT = 1.0; + +/** + * Program error. + */ +const GLuint PROGRAM_ERROR = 0; + +/** + * Shape vertices size. + */ +const int SHAPE_VERTICES_SIZE = 8; + +/** + * Position handle name. + */ +const char POSITION_NAME[] = "a_position"; + +/** + * Position error. + */ +const GLint POSITION_ERROR = -1; + +/** + * Config attribute list. + */ +const EGLint ATTRIB_LIST[] = { + // Key,value. + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, EGL_RED_SIZE_DEFAULT, + EGL_GREEN_SIZE, EGL_GREEN_SIZE_DEFAULT, + EGL_BLUE_SIZE, EGL_BLUE_SIZE_DEFAULT, + EGL_ALPHA_SIZE, EGL_ALPHA_SIZE_DEFAULT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + // End. + EGL_NONE}; + +/** + * Context attributes. + */ +const EGLint CONTEXT_ATTRIBS[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE}; +} // namespace +bool EGLCore::EglContextInit(void* window) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit execute"); + eglWindow_ = static_cast(window); + + // Init display. + eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (eglDisplay_ == EGL_NO_DISPLAY) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglGetDisplay: unable to get EGL display"); + return false; + } + + EGLint majorVersion; + EGLint minorVersion; + if (!eglInitialize(eglDisplay_, &majorVersion, &minorVersion)) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglInitialize: unable to get initialize EGL display"); + return false; + } + + // Select configuration. + const EGLint maxConfigSize = 1; + EGLint numConfigs; + if (!eglChooseConfig(eglDisplay_, ATTRIB_LIST, &eglConfig_, maxConfigSize, &numConfigs)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglChooseConfig: unable to choose configs"); + return false; + } + + return CreateEnvironment(); +} + +bool EGLCore::CreateEnvironment() +{ + // Create surface. + if (eglWindow_ == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglWindow_ is null"); + return false; + } + eglSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, eglWindow_, NULL); + if (eglSurface_ == nullptr) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglCreateWindowSurface: unable to create surface"); + return false; + } + // Create context. + eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, EGL_NO_CONTEXT, CONTEXT_ATTRIBS); + if (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglMakeCurrent failed"); + return false; + } + // Create program. + program_ = CreateProgram(VERTEX_SHADER, FRAGMENT_SHADER); + if (program_ == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "CreateProgram: unable to create program"); + return false; + } + return true; +} + +void EGLCore::Background() +{ + GLint position = PrepareDraw(); + if (position == POSITION_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background get position failed"); + return; + } + + if (!ExecuteDraw(position, BACKGROUND_COLOR, + BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background execute draw failed"); + return; + } + + if (!FinishDraw()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background FinishDraw failed"); + return; + } +} + +void EGLCore::Draw(int& hasDraw) +{ + flag_ = false; + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "Draw"); + GLint position = PrepareDraw(); + if (position == POSITION_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw get position failed"); + return; + } + + if (!ExecuteDraw(position, BACKGROUND_COLOR, + BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw background failed"); + return; + } + + // Divided into five quadrilaterals and calculate one of the quadrilateral's Vertices + GLfloat rotateX = 0; + GLfloat rotateY = FIFTY_PERCENT * height_; + GLfloat centerX = 0; + // Convert DEG(54° & 18°) to RAD + GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18); + // Convert DEG(18°) to RAD + GLfloat leftX = -rotateY * (M_PI / 180 * 18); + GLfloat leftY = 0; + // Convert DEG(18°) to RAD + GLfloat rightX = rotateY * (M_PI / 180 * 18); + GLfloat rightY = 0; + + const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ }; + + if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); + return; + } + + // Convert DEG(72°) to RAD + GLfloat rad = M_PI / 180 * 72; + // Rotate four times + for (int i = 0; i < NUM_4; ++i) { + Rotate2d(centerX, centerY, &rotateX, &rotateY, rad); + Rotate2d(centerX, centerY, &leftX, &leftY, rad); + Rotate2d(centerX, centerY, &rightX, &rightY, rad); + + const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ }; + + if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); + return; + } + } + + if (!FinishDraw()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw FinishDraw failed"); + return; + } + hasDraw = 1; + + flag_ = true; +} + +void EGLCore::ChangeColor(int& hasChangeColor) +{ + if (!flag_) { + return; + } + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor"); + GLint position = PrepareDraw(); + if (position == POSITION_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor get position failed"); + return; + } + + if (!ExecuteDraw(position, BACKGROUND_COLOR, + BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor execute draw background failed"); + return; + } + + // Divided into five quadrilaterals and calculate one of the quadrilateral's Vertices + GLfloat rotateX = 0; + GLfloat rotateY = FIFTY_PERCENT * height_; + GLfloat centerX = 0; + // Convert DEG(54° & 18°) to RAD + GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18); + // Convert DEG(18°) to RAD + GLfloat leftX = -rotateY * (M_PI / 180 * 18); + GLfloat leftY = 0; + // Convert DEG(18°) to RAD + GLfloat rightX = rotateY * (M_PI / 180 * 18); + GLfloat rightY = 0; + + const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ }; + + if (!ExecuteDrawNewStar(0, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); + return; + } + + // Convert DEG(72°) to RAD + GLfloat rad = M_PI / 180 * 72; + // Rotate four times + for (int i = 0; i < NUM_4; ++i) { + Rotate2d(centerX, centerY, &rotateX, &rotateY, rad); + Rotate2d(centerX, centerY, &leftX, &leftY, rad); + Rotate2d(centerX, centerY, &rightX, &rightY, rad); + const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ }; + + if (!ExecuteDrawNewStar(position, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); + return; + } + } + + if (!FinishDraw()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor FinishDraw failed"); + } + hasChangeColor = 1; +} + +GLint EGLCore::PrepareDraw() +{ + if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (eglContext_ == nullptr) || + (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "PrepareDraw: param error"); + return POSITION_ERROR; + } + + // The gl function has no return value. + glViewport(DEFAULT_X_POSITION, DEFAULT_Y_POSITION, width_, height_); + glClearColor(GL_RED_DEFAULT, GL_GREEN_DEFAULT, GL_BLUE_DEFAULT, GL_ALPHA_DEFAULT); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(program_); + + return glGetAttribLocation(program_, POSITION_NAME); +} + +bool EGLCore::ExecuteDraw(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize) +{ + if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error"); + return false; + } + + // The gl function has no return value. + glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices); + glEnableVertexAttribArray(position); + glVertexAttrib4fv(1, color); + glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE); + glDisableVertexAttribArray(position); + + return true; +} + +bool EGLCore::ExecuteDrawStar( + GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize) +{ + if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error"); + return false; + } + + // The gl function has no return value. + glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices); + glVertexAttribPointer(1, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, color); + glEnableVertexAttribArray(position); + glEnableVertexAttribArray(1); + glVertexAttrib4fv(1, color); + glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE); + glDisableVertexAttribArray(position); + glDisableVertexAttribArray(1); + + return true; +} + +bool EGLCore::ExecuteDrawNewStar( + GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize) +{ + if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error"); + return false; + } + + // The gl function has no return value. + glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices); + glEnableVertexAttribArray(position); + glVertexAttrib4fv(1, color); + glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE); + glDisableVertexAttribArray(position); + + return true; +} + +void EGLCore::Rotate2d(GLfloat centerX, GLfloat centerY, GLfloat* rotateX, GLfloat* rotateY, GLfloat theta) +{ + GLfloat tempX = cos(theta) * (*rotateX - centerX) - sin(theta) * (*rotateY - centerY); + GLfloat tempY = sin(theta) * (*rotateX - centerX) + cos(theta) * (*rotateY - centerY); + *rotateX = tempX + centerX; + *rotateY = tempY + centerY; +} + +bool EGLCore::FinishDraw() +{ + // The gl function has no return value. + glFlush(); + glFinish(); + return eglSwapBuffers(eglDisplay_, eglSurface_); +} + +GLuint EGLCore::LoadShader(GLenum type, const char* shaderSrc) +{ + if ((type <= 0) || (shaderSrc == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCreateShader type or shaderSrc error"); + return PROGRAM_ERROR; + } + + GLuint shader = glCreateShader(type); + if (shader == 0) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCreateShader unable to load shader"); + return PROGRAM_ERROR; + } + + // The gl function has no return value. + glShaderSource(shader, 1, &shaderSrc, nullptr); + glCompileShader(shader); + + GLint compiled; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (compiled != 0) { + return shader; + } + + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen <= 1) { + glDeleteShader(shader); + return PROGRAM_ERROR; + } + + char* infoLog = (char*)malloc(sizeof(char) * (infoLen + 1)); + if (infoLog != nullptr) { + memset(infoLog, 0, infoLen + 1); + glGetShaderInfoLog(shader, infoLen, nullptr, infoLog); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCompileShader error = %s", infoLog); + free(infoLog); + infoLog = nullptr; + } + glDeleteShader(shader); + return PROGRAM_ERROR; +} + +GLuint EGLCore::CreateProgram(const char* vertexShader, const char* fragShader) +{ + if ((vertexShader == nullptr) || (fragShader == nullptr)) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram: vertexShader or fragShader is null"); + return PROGRAM_ERROR; + } + + GLuint vertex = LoadShader(GL_VERTEX_SHADER, vertexShader); + if (vertex == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram vertex error"); + return PROGRAM_ERROR; + } + + GLuint fragment = LoadShader(GL_FRAGMENT_SHADER, fragShader); + if (fragment == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram fragment error"); + return PROGRAM_ERROR; + } + + GLuint program = glCreateProgram(); + if (program == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram program error"); + glDeleteShader(vertex); + glDeleteShader(fragment); + return PROGRAM_ERROR; + } + + // The gl function has no return value. + glAttachShader(program, vertex); + glAttachShader(program, fragment); + glLinkProgram(program); + + GLint linked; + glGetProgramiv(program, GL_LINK_STATUS, &linked); + if (linked != 0) { + glDeleteShader(vertex); + glDeleteShader(fragment); + return program; + } + + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram linked error"); + GLint infoLen = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) { + char* infoLog = (char*)malloc(sizeof(char) * (infoLen + 1)); + memset(infoLog, 0, infoLen + 1); + glGetProgramInfoLog(program, infoLen, nullptr, infoLog); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glLinkProgram error = %s", infoLog); + free(infoLog); + infoLog = nullptr; + } + glDeleteShader(vertex); + glDeleteShader(fragment); + glDeleteProgram(program); + return PROGRAM_ERROR; +} + +void EGLCore::UpdateSize(int width, int height) +{ + width_ = width; + height_ = height; + if (width_ > 0) { + widthPercent_ = FIFTY_PERCENT * height_ / width_; + } +} + +void EGLCore::Release() +{ + if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (!eglDestroySurface(eglDisplay_, eglSurface_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroySurface failed"); + } + + if ((eglDisplay_ == nullptr) || (eglContext_ == nullptr) || (!eglDestroyContext(eglDisplay_, eglContext_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroyContext failed"); + } + + if ((eglDisplay_ == nullptr) || (!eglTerminate(eglDisplay_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglTerminate failed"); + } +} +} // namespace NativeXComponentDemo diff --git a/entry/src/main/cpp/render/egl_core.h b/entry/src/main/cpp/render/egl_core.h new file mode 100644 index 00000000..bc1f4b23 --- /dev/null +++ b/entry/src/main/cpp/render/egl_core.h @@ -0,0 +1,50 @@ +// +// Created on 2025/11/24. +// +// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, +// please include "napi/native_api.h". + +#ifndef NATIVE3D_EGL_CORE_H +#define NATIVE3D_EGL_CORE_H +#include +#include +#include + +namespace NativeXComponentDemo { +class EGLCore { +public: + explicit EGLCore() {}; + ~EGLCore() {} + bool EglContextInit(void* window); + bool CreateEnvironment(); + void Draw(int& hasDraw); + void Background(); + void ChangeColor(int& hasChangeColor); + void Release(); + void UpdateSize(int width, int height); + +private: + GLuint LoadShader(GLenum type, const char* shaderSrc); + GLuint CreateProgram(const char* vertexShader, const char* fragShader); + GLint PrepareDraw(); + bool ExecuteDraw(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize); + bool ExecuteDrawStar(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize); + bool ExecuteDrawNewStar(GLint position, const GLfloat* color, + const GLfloat shapeVertices[], unsigned long vertSize); + void Rotate2d(GLfloat centerX, GLfloat centerY, GLfloat* rotateX, GLfloat* rotateY, GLfloat theta); + bool FinishDraw(); + +private: + EGLNativeWindowType eglWindow_; + EGLDisplay eglDisplay_ = EGL_NO_DISPLAY; + EGLConfig eglConfig_ = EGL_NO_CONFIG_KHR; + EGLSurface eglSurface_ = EGL_NO_SURFACE; + EGLContext eglContext_ = EGL_NO_CONTEXT; + GLuint program_; + bool flag_ = false; + int width_; + int height_; + GLfloat widthPercent_; +}; +} // namespace NativeXComponentDemo +#endif //NATIVE3D_EGL_CORE_H diff --git a/entry/src/main/cpp/render/plugin_render.cpp b/entry/src/main/cpp/render/plugin_render.cpp new file mode 100644 index 00000000..c49ad917 --- /dev/null +++ b/entry/src/main/cpp/render/plugin_render.cpp @@ -0,0 +1,70 @@ +// +// Created on 2025/11/24. +// +// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, +// please include "napi/native_api.h". + +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "plugin_render.h" + +namespace NativeXComponentDemo { + +PluginRender::PluginRender(int64_t& id) +{ + this->id_ = id; + this->eglCore_ = new EGLCore(); + hasDraw_ = 0; + hasChangeColor_ = 0; +} +// [Start xcomponent_render_cpp] +void PluginRender::ChangeColor() +{ + eglCore_->ChangeColor(hasChangeColor_); +} + +void PluginRender::DrawPattern() +{ + eglCore_->Draw(hasDraw_); // 参考Native XComponent场景Draw实现 +} + +void PluginRender::InitNativeWindow(OHNativeWindow *window) +{ + eglCore_->EglContextInit(window); // 参考Native XComponent场景EglContextInit的实现 +} + +void PluginRender::UpdateNativeWindowSize(int width, int height) +{ + eglCore_->UpdateSize(width, height); // 参考Native XComponent场景UpdateSize的实现 + if (!hasChangeColor_ && !hasDraw_) { + eglCore_->Background(); // 参考Native XComponent场景Background的实现 + } +} + +int32_t PluginRender::HasDraw() +{ + return hasDraw_; +} + +int32_t PluginRender::HasChangedColor() +{ + return hasChangeColor_; +} +// [End xcomponent_render_cpp] +} // namespace NativeXComponentDemo + diff --git a/entry/src/main/cpp/render/plugin_render.h b/entry/src/main/cpp/render/plugin_render.h new file mode 100644 index 00000000..55a952d2 --- /dev/null +++ b/entry/src/main/cpp/render/plugin_render.h @@ -0,0 +1,38 @@ +// +// Created on 2025/11/24. +// +// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, +// please include "napi/native_api.h". + +#ifndef NATIVE3D_PLUGIN_RENDER_H +#define NATIVE3D_PLUGIN_RENDER_H +#include +#include +#include "egl_core.h" + +namespace NativeXComponentDemo { +class PluginRender { +public: + explicit PluginRender(int64_t& id); + ~PluginRender() + { + if (eglCore_ != nullptr) { + eglCore_->Release(); + delete eglCore_; + eglCore_ = nullptr; + } + } + void ChangeColor(); + void DrawPattern(); + int32_t HasDraw(); + int32_t HasChangedColor(); + void InitNativeWindow(OHNativeWindow* window); + void UpdateNativeWindowSize(int width, int height); +private: + EGLCore* eglCore_; + int64_t id_; + int32_t hasDraw_; + int32_t hasChangeColor_; +}; +} // namespace NativeXComponentDemo +#endif //NATIVE3D_PLUGIN_RENDER_H diff --git a/entry/src/main/cpp/types/libentry/Index.d.ts b/entry/src/main/cpp/types/libentry/Index.d.ts index e44f3615..c9c66ecf 100644 --- a/entry/src/main/cpp/types/libentry/Index.d.ts +++ b/entry/src/main/cpp/types/libentry/Index.d.ts @@ -1 +1,10 @@ -export const add: (a: number, b: number) => number; \ No newline at end of file +type XComponentContextStatus = { + hasDraw: boolean, + hasChangeColor: boolean, +}; +export const SetSurfaceId: (id: BigInt) => any; +export const ChangeSurface: (id: BigInt, w: number, h: number) =>any; +export const DrawPattern: (id: BigInt) => any; +export const GetXComponentStatus: (id: BigInt) => XComponentContextStatus +export const ChangeColor: (id: BigInt) => any; +export const DestroySurface: (id: BigInt) => any; \ No newline at end of file diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index e8c6f982..ccbd270f 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -3,7 +3,7 @@ import testNapi from 'libentry.so'; import { edgeColors } from '@kit.ArkUI'; import {TitleTab} from './titleTab' import {LeftSideTab} from './leftSideTab' - +import {ModelViewTab} from './modelViewTab' const DOMAIN = 0x0000; @Entry @@ -19,12 +19,13 @@ struct Index { LeftSideTab().borderWidth('1').width('20%'); //中间操作区域 Row() { - Text('操作区') - Blank().height('100%').width('100%') + ModelViewTab() }.width('80%') .height('100%') .borderWidth('1') + .align(Alignment.Center) }.height('80%') + .padding(1) Column(){ Text('状态栏').height('100%').width('100%') }.height('5%').borderWidth('1') diff --git a/entry/src/main/ets/pages/modelView.ets b/entry/src/main/ets/pages/modelView.ets new file mode 100644 index 00000000..2df5be1f --- /dev/null +++ b/entry/src/main/ets/pages/modelView.ets @@ -0,0 +1,91 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import Native3D from 'libentry.so'; + +class MyXComponentController extends XComponentController{ + onSurfaceCreated(surfaceId: string): void { + console.info(`onSurfaceCreated surfaceId: ${surfaceId}`); + Native3D.SetSurfaceId(BigInt(surfaceId)); + } + onSurfaceChanged(surfaceId: string, rect: SurfaceRect): void { + console.info(`onSurfaceChanged surfaceId: ${surfaceId}, rect: ${JSON.stringify(rect)}}`); + // 在onSurfaceChanged中调用ChangeSurface绘制内容 + Native3D.ChangeSurface(BigInt(surfaceId), rect.surfaceWidth, rect.surfaceHeight); + } + onSurfaceDestroyed(surfaceId: string): void { + console.info(`onSurfaceDestroyed surfaceId: ${surfaceId}`); + Native3D.DestroySurface(BigInt(surfaceId)); + } +} + +@Component +export struct ModelView { + @State objStatus: string = "当前状态:"; + @State currentStatus: string = "Null"; + @State btnRun:string ='绘制图形'; + @State btnChn:string ='改变颜色'; + ComCtrl: XComponentController = new MyXComponentController(); + build() { + Flex({ direction: FlexDirection.Column }) { + Column({ space: 10 }){ + XComponent({ + type: XComponentType.SURFACE, + controller: this.ComCtrl + }).height('80%') + + Row(){ + Text(this.objStatus) + .fontSize('24fp') + .fontWeight(500) + .height('20%') + + Text(this.currentStatus) + .fontSize('24fp') + .fontWeight(500) + .height('20%') + }.height('20%') + + }.height('80%') + + Column() { + Row(){ + Text('渲染后端:') + Checkbox() + Text('OpenGL ES') + Checkbox() + Text('Vulkan') + } + Row() { + Button(this.btnRun) + .fontSize(22) + .fontWeight(FontWeight.Bold) + .onClick(() => { + let surfaceId = this.ComCtrl.getXComponentSurfaceId(); + Native3D.DrawPattern(BigInt(surfaceId)); + let hasDraw: boolean = false; + if (Native3D.GetXComponentStatus(BigInt(surfaceId))) { + hasDraw = Native3D.GetXComponentStatus(BigInt(surfaceId)).hasDraw; + } + if (hasDraw) { + this.currentStatus = "绘制图形"; + } + }) + Button(this.btnChn) + .fontSize(22) + .fontWeight(FontWeight.Bold) + .onClick(() => { + let surfaceId = this.ComCtrl.getXComponentSurfaceId(); + Native3D.ChangeColor(BigInt(surfaceId)); + let hasChangeColor: boolean = false; + if (Native3D.GetXComponentStatus(BigInt(surfaceId))) { + hasChangeColor = Native3D.GetXComponentStatus(BigInt(surfaceId)).hasChangeColor; + } + if (hasChangeColor) { + this.currentStatus = "改变颜色"; + } + }) + } + }.height('10%') + }.width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/modelViewTab.ets b/entry/src/main/ets/pages/modelViewTab.ets new file mode 100644 index 00000000..a5359449 --- /dev/null +++ b/entry/src/main/ets/pages/modelViewTab.ets @@ -0,0 +1,84 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import {ModelView} from './modelView' + +class TaskTab{ + icon:string='' + str:string='default model' + event:string='' +} +let dTab:Array=[ + {icon:'',str:'默认任务',event:''} +] + +@Component +export struct ModelViewTab { + //顶部导航组件 + private modelViewBarTabs: TabsController = new TabsController(); + //当前的顶部导航选择页 + @State modelViewBarFocusIndex: number = 0; + + build() { + Flex({ direction: FlexDirection.Column }) { + Scroll() { + Row() { + ForEach(dTab, (item: TaskTab, index: number) => { + Row({ space: 0 }) { + Image($r('app.media.startIcon')) + .width(25) + .height(25) + .objectFit(ImageFit.Contain) + Button(item.str) + .fontWeight(index === this.modelViewBarFocusIndex ? FontWeight.Bold : FontWeight.Normal) + .height(25) + .width(60) + .padding(5) + .type(ButtonType.Normal) + Button('X') + .height(25) + .width(25) + .type(ButtonType.Normal) + .padding(1) + .align(Alignment.Center) + }.onClick(() => { + this.modelViewBarTabs.changeIndex(index); + this.modelViewBarFocusIndex = index; + }) + }) + } + }.borderWidth('1') + .borderColor(Color.Gray) + .align(Alignment.Start) + .scrollable(ScrollDirection.Horizontal) + .scrollBar(BarState.Off) + .margin({ + top: 2, + left: 2, + bottom: 2, + right: 2 + }) + .width('100%') + + Tabs({ barPosition: BarPosition.Start, index: 0, controller: this.modelViewBarTabs }) { + TabContent() { + ModelView() + }.align(Alignment.Start) + .padding(1) + .margin({ + top: 0, + left: 0, + bottom: 2, + right: 0 + }) + }.barHeight(0) + .margin({ + top: 0, + left: 0, + bottom: 0, + right: 0 + }) + .height('auto') + .barMode(BarMode.Fixed) + }.borderWidth('1') + .height('auto') + } +} diff --git a/log.txt b/log.txt new file mode 100644 index 00000000..4f85fe01 --- /dev/null +++ b/log.txt @@ -0,0 +1,14 @@ +20:56:05:541 log crossJumpDefinitionNAPI RegisterFile not found +20:56:07:496 log crossJumpDefinitionNAPI RegisterFile not found +20:56:09:738 log crossJumpDefinitionNAPI RegisterFile not found +20:56:09:753 log crossJumpDefinitionNAPI RegisterFile not found +20:56:09:765 log crossJumpDefinitionNAPI RegisterFile not found +20:56:09:780 log crossJumpDefinitionNAPI RegisterFile not found +20:56:09:793 log crossJumpDefinitionNAPI RegisterFile not found +20:56:09:806 log crossJumpDefinitionNAPI RegisterFile not found +20:56:13:104 log crossJumpDefinitionNAPI RegisterFile not found +20:56:13:114 log crossJumpDefinitionNAPI RegisterFile not found +20:56:13:123 log crossJumpDefinitionNAPI RegisterFile not found +20:56:13:132 log crossJumpDefinitionNAPI RegisterFile not found +20:56:13:140 log crossJumpDefinitionNAPI RegisterFile not found +20:56:13:151 log crossJumpDefinitionNAPI RegisterFile not found