18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci#include <scene_plugin/api/camera_uid.h>
168bf80f4bSopenharmony_ci#include <scene_plugin/api/postprocess_uid.h>
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <meta/ext/concrete_base_object.h>
198bf80f4bSopenharmony_ci
208bf80f4bSopenharmony_ci#include "bind_templates.inl"
218bf80f4bSopenharmony_ci#include "intf_postprocess_private.h"
228bf80f4bSopenharmony_ci#include "node_impl.h"
238bf80f4bSopenharmony_ci#include "task_utils.h"
248bf80f4bSopenharmony_ci
258bf80f4bSopenharmony_ciusing SCENE_NS::MakeTask;
268bf80f4bSopenharmony_ci
278bf80f4bSopenharmony_cinamespace {
288bf80f4bSopenharmony_ciclass CameraImpl
298bf80f4bSopenharmony_ci    : public META_NS::ConcreteBaseMetaObjectFwd<CameraImpl, NodeImpl, SCENE_NS::ClassId::Camera, SCENE_NS::ICamera> {
308bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, FoV, 60.f * BASE_NS::Math::DEG2RAD)
318bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, AspectRatio, -1.f)
328bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, NearPlane, 0.3f)
338bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, FarPlane, 1000.f)
348bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, XMagnification, 0.f)
358bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, YMagnification, 0.f)
368bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, XOffset, 1.f)
378bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, YOffset, 1.f)
388bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(
398bf80f4bSopenharmony_ci        SCENE_NS::ICamera, uint8_t, Projection, SCENE_NS::ICamera::SCENE_CAM_PROJECTION_PERSPECTIVE)
408bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(
418bf80f4bSopenharmony_ci        SCENE_NS::ICamera, uint8_t, Culling, SCENE_NS::ICamera::SCENE_CAM_CULLING_VIEW_FRUSTUM)
428bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(
438bf80f4bSopenharmony_ci        SCENE_NS::ICamera, uint8_t, RenderingPipeline, SCENE_NS::ICamera::SCENE_CAM_PIPELINE_FORWARD)
448bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, uint32_t, SceneFlags, 0)
458bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, uint32_t, PipelineFlags, (1 << 3))
468bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(
478bf80f4bSopenharmony_ci        SCENE_NS::ICamera, BASE_NS::Math::Vec4, Viewport, BASE_NS::Math::Vec4(0.f, 0.f, 1.f, 1.f))
488bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(
498bf80f4bSopenharmony_ci        SCENE_NS::ICamera, BASE_NS::Math::Vec4, Scissor, BASE_NS::Math::Vec4(0.f, 0.f, 1.f, 1.f))
508bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(
518bf80f4bSopenharmony_ci        SCENE_NS::ICamera, BASE_NS::Math::UVec2, RenderTargetSize, BASE_NS::Math::UVec2(0, 0))
528bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, SCENE_NS::Color, ClearColor, SCENE_NS::Colors::TRANSPARENT)
538bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, ClearDepth, 1.f)
548bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, BASE_NS::string, RenderNodeGraphFile, {})
558bf80f4bSopenharmony_ci    META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, SCENE_NS::IPostProcess::Ptr, PostProcess, {})
568bf80f4bSopenharmony_ci
578bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_COMPONENT_NAME = "CameraComponent";
588bf80f4bSopenharmony_ci    static constexpr size_t CAMERA_COMPONENT_NAME_LEN = CAMERA_COMPONENT_NAME.size() + 1;
598bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_FOV = "CameraComponent.yFov";
608bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_ASPECT = "CameraComponent.aspect";
618bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_ZNEAR = "CameraComponent.zNear";
628bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_ZFAR = "CameraComponent.zFar";
638bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_XMAG = "CameraComponent.xMag";
648bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_YMAG = "CameraComponent.yMag";
658bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_XOFFSET = "CameraComponent.xOffset";
668bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_YOFFSET = "CameraComponent.yOffset";
678bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_PROJECTION = "CameraComponent.projection";
688bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_CULLING = "CameraComponent.culling";
698bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_RENDERINGPIPELINE = "CameraComponent.renderingPipeline";
708bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_SCENEFLAGS = "CameraComponent.sceneFlags";
718bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_PIPELINEFLAGS = "CameraComponent.pipelineFlags";
728bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_SCISSOR = "CameraComponent.scissor";
738bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_VIEWPORT = "CameraComponent.viewport";
748bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_CLEARCOLORVALUE = "CameraComponent.clearColorValue";
758bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_CLEARDEPTHVALUE = "CameraComponent.clearDepthValue";
768bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_LAYERMASK = "CameraComponent.layerMask";
778bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_RENDERRESOLUTION = "CameraComponent.renderResolution";
788bf80f4bSopenharmony_ci    static constexpr BASE_NS::string_view CAMERA_POSTPROCESS = "CameraComponent.postProcess";
798bf80f4bSopenharmony_ci
808bf80f4bSopenharmony_ci    bool Build(const IMetadata::Ptr& data) override
818bf80f4bSopenharmony_ci    {
828bf80f4bSopenharmony_ci        bool ret = false;
838bf80f4bSopenharmony_ci        if (ret = NodeImpl::Build(data); ret) {
848bf80f4bSopenharmony_ci            PropertyNameMask()[CAMERA_COMPONENT_NAME] = { CAMERA_FOV.substr(CAMERA_COMPONENT_NAME_LEN),
858bf80f4bSopenharmony_ci                CAMERA_ASPECT.substr(CAMERA_COMPONENT_NAME_LEN), CAMERA_ZNEAR.substr(CAMERA_COMPONENT_NAME_LEN),
868bf80f4bSopenharmony_ci                CAMERA_ZFAR.substr(CAMERA_COMPONENT_NAME_LEN), CAMERA_XMAG.substr(CAMERA_COMPONENT_NAME_LEN),
878bf80f4bSopenharmony_ci                CAMERA_YMAG.substr(CAMERA_COMPONENT_NAME_LEN), CAMERA_XOFFSET.substr(CAMERA_COMPONENT_NAME_LEN),
888bf80f4bSopenharmony_ci                CAMERA_YOFFSET.substr(CAMERA_COMPONENT_NAME_LEN), CAMERA_PROJECTION.substr(CAMERA_COMPONENT_NAME_LEN),
898bf80f4bSopenharmony_ci                CAMERA_CULLING.substr(CAMERA_COMPONENT_NAME_LEN),
908bf80f4bSopenharmony_ci                CAMERA_RENDERINGPIPELINE.substr(CAMERA_COMPONENT_NAME_LEN),
918bf80f4bSopenharmony_ci                CAMERA_SCENEFLAGS.substr(CAMERA_COMPONENT_NAME_LEN),
928bf80f4bSopenharmony_ci                CAMERA_PIPELINEFLAGS.substr(CAMERA_COMPONENT_NAME_LEN),
938bf80f4bSopenharmony_ci                CAMERA_SCISSOR.substr(CAMERA_COMPONENT_NAME_LEN), CAMERA_VIEWPORT.substr(CAMERA_COMPONENT_NAME_LEN),
948bf80f4bSopenharmony_ci                CAMERA_CLEARCOLORVALUE.substr(CAMERA_COMPONENT_NAME_LEN),
958bf80f4bSopenharmony_ci                CAMERA_CLEARDEPTHVALUE.substr(CAMERA_COMPONENT_NAME_LEN),
968bf80f4bSopenharmony_ci                CAMERA_LAYERMASK.substr(CAMERA_COMPONENT_NAME_LEN),
978bf80f4bSopenharmony_ci                CAMERA_POSTPROCESS.substr(CAMERA_COMPONENT_NAME_LEN),
988bf80f4bSopenharmony_ci                CAMERA_RENDERRESOLUTION.substr(CAMERA_COMPONENT_NAME_LEN) };
998bf80f4bSopenharmony_ci        }
1008bf80f4bSopenharmony_ci        return ret;
1018bf80f4bSopenharmony_ci    }
1028bf80f4bSopenharmony_ci
1038bf80f4bSopenharmony_ci    bool CompleteInitialization(const BASE_NS::string& path) override
1048bf80f4bSopenharmony_ci    {
1058bf80f4bSopenharmony_ci        if (!NodeImpl::CompleteInitialization(path)) {
1068bf80f4bSopenharmony_ci            return false;
1078bf80f4bSopenharmony_ci        }
1088bf80f4bSopenharmony_ci
1098bf80f4bSopenharmony_ci        auto meta = interface_pointer_cast<META_NS::IMetadata>(ecsObject_);
1108bf80f4bSopenharmony_ci        BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(FoV), meta, CAMERA_FOV);
1118bf80f4bSopenharmony_ci        BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(AspectRatio), meta, CAMERA_ASPECT);
1128bf80f4bSopenharmony_ci        BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(NearPlane), meta, CAMERA_ZNEAR);
1138bf80f4bSopenharmony_ci        BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(FarPlane), meta, CAMERA_ZFAR);
1148bf80f4bSopenharmony_ci        BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(XMagnification), meta, CAMERA_XMAG);
1158bf80f4bSopenharmony_ci        BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(YMagnification), meta, CAMERA_YMAG);
1168bf80f4bSopenharmony_ci        BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(XOffset), meta, CAMERA_XOFFSET);
1178bf80f4bSopenharmony_ci        BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(YOffset), meta, CAMERA_YOFFSET);
1188bf80f4bSopenharmony_ci        BindChanges<uint8_t>(propHandler_, META_ACCESS_PROPERTY(Projection), meta, CAMERA_PROJECTION);
1198bf80f4bSopenharmony_ci        BindChanges<uint8_t>(propHandler_, META_ACCESS_PROPERTY(Culling), meta, CAMERA_CULLING);
1208bf80f4bSopenharmony_ci        BindChanges<uint8_t>(propHandler_, META_ACCESS_PROPERTY(RenderingPipeline), meta, CAMERA_RENDERINGPIPELINE);
1218bf80f4bSopenharmony_ci        BindChanges<uint32_t>(propHandler_, META_ACCESS_PROPERTY(SceneFlags), meta, CAMERA_SCENEFLAGS);
1228bf80f4bSopenharmony_ci        BindChanges<uint32_t>(propHandler_, META_ACCESS_PROPERTY(PipelineFlags), meta, CAMERA_PIPELINEFLAGS);
1238bf80f4bSopenharmony_ci        BindChanges<BASE_NS::Math::Vec4>(propHandler_, META_ACCESS_PROPERTY(Scissor), meta, CAMERA_SCISSOR);
1248bf80f4bSopenharmony_ci        BindChanges<BASE_NS::Math::Vec4>(propHandler_, META_ACCESS_PROPERTY(Viewport), meta, CAMERA_VIEWPORT);
1258bf80f4bSopenharmony_ci        ConvertBindChanges<SCENE_NS::Color, BASE_NS::Math::Vec4>(
1268bf80f4bSopenharmony_ci            propHandler_, META_ACCESS_PROPERTY(ClearColor), meta, CAMERA_CLEARCOLORVALUE);
1278bf80f4bSopenharmony_ci        BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(ClearDepth), meta, CAMERA_CLEARDEPTHVALUE);
1288bf80f4bSopenharmony_ci
1298bf80f4bSopenharmony_ci        // override INode default handling for LayerMask
1308bf80f4bSopenharmony_ci        BindChanges<uint64_t>(propHandler_, NodeImpl::META_ACCESS_PROPERTY(LayerMask), meta, CAMERA_LAYERMASK);
1318bf80f4bSopenharmony_ci
1328bf80f4bSopenharmony_ci        if (auto scene = GetScene()) {
1338bf80f4bSopenharmony_ci            propHandler_.NewHandler(nullptr, nullptr)
1348bf80f4bSopenharmony_ci                .Subscribe(META_ACCESS_PROPERTY(RenderTargetSize),
1358bf80f4bSopenharmony_ci                    META_NS::MakeCallback<META_NS::IOnChanged>(
1368bf80f4bSopenharmony_ci                        [this](const auto& scene) {
1378bf80f4bSopenharmony_ci                            if (auto ecsObject = EcsObject(); scene && ecsObject) {
1388bf80f4bSopenharmony_ci                                auto renderSize = META_NS::GetValue(RenderTargetSize());
1398bf80f4bSopenharmony_ci                                if (renderSize.x != 0 && renderSize.y != 0) {
1408bf80f4bSopenharmony_ci                                    SceneHolder()->SetRenderSize(renderSize.x, renderSize.y, ecsObject->GetEntity().id);
1418bf80f4bSopenharmony_ci                                }
1428bf80f4bSopenharmony_ci                            }
1438bf80f4bSopenharmony_ci                        },
1448bf80f4bSopenharmony_ci                        scene));
1458bf80f4bSopenharmony_ci        } else {
1468bf80f4bSopenharmony_ci            // Engine side does not automatically resize camera resources even the size changes
1478bf80f4bSopenharmony_ci            BindChanges<BASE_NS::Math::UVec2>(
1488bf80f4bSopenharmony_ci                propHandler_, META_ACCESS_PROPERTY(RenderTargetSize), meta, CAMERA_RENDERRESOLUTION);
1498bf80f4bSopenharmony_ci        }
1508bf80f4bSopenharmony_ci
1518bf80f4bSopenharmony_ci        if (auto postProcess = meta->GetPropertyByName(CAMERA_POSTPROCESS)) {
1528bf80f4bSopenharmony_ci            // To quickly test / verify post-process bindings
1538bf80f4bSopenharmony_ci            // callback to carry out when toolkit side changes
1548bf80f4bSopenharmony_ci            auto metaCallback = [this](META_NS::IProperty::Ptr postProcessEntity,
1558bf80f4bSopenharmony_ci                                    SCENE_NS::IPostProcess::Ptr postProcessBridge) {
1568bf80f4bSopenharmony_ci                auto typed = META_NS::Property<CORE_NS::Entity>(postProcessEntity);
1578bf80f4bSopenharmony_ci                auto entity = META_NS::GetValue(typed);
1588bf80f4bSopenharmony_ci                auto sh = SceneHolder();
1598bf80f4bSopenharmony_ci                auto ecs = sh->GetEcs();
1608bf80f4bSopenharmony_ci                if (!CORE_NS::EntityUtil::IsValid(entity)) {
1618bf80f4bSopenharmony_ci                    // engine does not have existing entity, create new one
1628bf80f4bSopenharmony_ci                    entity = sh->CreatePostProcess();
1638bf80f4bSopenharmony_ci                    META_NS::SetValue(typed, entity);
1648bf80f4bSopenharmony_ci                }
1658bf80f4bSopenharmony_ci                // values from toolkit dominate initialization
1668bf80f4bSopenharmony_ci                interface_cast<IPostProcessPrivate>(postProcessBridge)->SetEntity(entity, sh, false);
1678bf80f4bSopenharmony_ci            };
1688bf80f4bSopenharmony_ci
1698bf80f4bSopenharmony_ci            // callback to carry out if the engine side drives the change
1708bf80f4bSopenharmony_ci            auto engineCallback = [this](META_NS::IProperty::Ptr postProcessEntity) {
1718bf80f4bSopenharmony_ci                auto entity = META_NS::GetValue(META_NS::Property<CORE_NS::Entity>(postProcessEntity));
1728bf80f4bSopenharmony_ci                auto sh = SceneHolder();
1738bf80f4bSopenharmony_ci                auto ecs = sh->GetEcs();
1748bf80f4bSopenharmony_ci                if (!CORE_NS::EntityUtil::IsValid(entity)) {
1758bf80f4bSopenharmony_ci                    META_NS::SetValue(PostProcess(), SCENE_NS::IPostProcess::Ptr {});
1768bf80f4bSopenharmony_ci                } else {
1778bf80f4bSopenharmony_ci                    auto ppo = META_NS::GetObjectRegistry().Create<IPostProcessPrivate>(SCENE_NS::ClassId::PostProcess);
1788bf80f4bSopenharmony_ci                    // values from ecs dominate initialization
1798bf80f4bSopenharmony_ci                    ppo->SetEntity(entity, sh, true);
1808bf80f4bSopenharmony_ci                    META_NS::SetValue(PostProcess(), interface_pointer_cast<SCENE_NS::IPostProcess>(ppo));
1818bf80f4bSopenharmony_ci                }
1828bf80f4bSopenharmony_ci            };
1838bf80f4bSopenharmony_ci
1848bf80f4bSopenharmony_ci            if (auto bridge = META_NS::GetValue(PostProcess())) {
1858bf80f4bSopenharmony_ci                metaCallback(postProcess, bridge);
1868bf80f4bSopenharmony_ci            } else {
1878bf80f4bSopenharmony_ci                engineCallback(postProcess);
1888bf80f4bSopenharmony_ci            }
1898bf80f4bSopenharmony_ci
1908bf80f4bSopenharmony_ci            // setup subscription for toolkit changes
1918bf80f4bSopenharmony_ci            PostProcess()->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>([this, metaCallback]() {
1928bf80f4bSopenharmony_ci                if (auto bridge = META_NS::GetValue(PostProcess())) {
1938bf80f4bSopenharmony_ci                    if (auto meta = interface_pointer_cast<META_NS::IMetadata>(ecsObject_)) {
1948bf80f4bSopenharmony_ci                        if (auto postProcess = meta->GetPropertyByName(CAMERA_POSTPROCESS)) {
1958bf80f4bSopenharmony_ci                            metaCallback(postProcess, bridge);
1968bf80f4bSopenharmony_ci                        }
1978bf80f4bSopenharmony_ci                    }
1988bf80f4bSopenharmony_ci                } else {
1998bf80f4bSopenharmony_ci                    if (auto meta = interface_pointer_cast<META_NS::IMetadata>(ecsObject_)) {
2008bf80f4bSopenharmony_ci                        if (auto postProcess = meta->GetPropertyByName(CAMERA_POSTPROCESS)) {
2018bf80f4bSopenharmony_ci                            if (auto typed = META_NS::Property<CORE_NS::Entity>(postProcess)) {
2028bf80f4bSopenharmony_ci                                META_NS::SetValue(typed, CORE_NS::Entity());
2038bf80f4bSopenharmony_ci                            }
2048bf80f4bSopenharmony_ci                        }
2058bf80f4bSopenharmony_ci                    }
2068bf80f4bSopenharmony_ci                }
2078bf80f4bSopenharmony_ci            }),
2088bf80f4bSopenharmony_ci                reinterpret_cast<uint64_t>(this));
2098bf80f4bSopenharmony_ci
2108bf80f4bSopenharmony_ci            // setup subscription to ecs changes
2118bf80f4bSopenharmony_ci            postProcess->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>([this, engineCallback]() {
2128bf80f4bSopenharmony_ci                if (auto meta = this->GetSelf<META_NS::IMetadata>()) {
2138bf80f4bSopenharmony_ci                    if (auto postProcess = meta->GetPropertyByName(CAMERA_POSTPROCESS)) {
2148bf80f4bSopenharmony_ci                        engineCallback(postProcess);
2158bf80f4bSopenharmony_ci                    }
2168bf80f4bSopenharmony_ci                }
2178bf80f4bSopenharmony_ci            }),
2188bf80f4bSopenharmony_ci                reinterpret_cast<uint64_t>(this));
2198bf80f4bSopenharmony_ci            ConvertBindChanges<SCENE_NS::IPostProcess::Ptr, CORE_NS::Entity, EntityConverter<SCENE_NS::IPostProcess>>(
2208bf80f4bSopenharmony_ci                propHandler_, PostProcess(), meta, "CameraComponent.postProcess", ONE_WAY_TO_ECS);
2218bf80f4bSopenharmony_ci        }
2228bf80f4bSopenharmony_ci
2238bf80f4bSopenharmony_ci        auto updateCustom = [this]() {
2248bf80f4bSopenharmony_ci            auto pipeline = RenderingPipeline()->GetValue();
2258bf80f4bSopenharmony_ci            if (pipeline == SCENE_NS::ICamera::SceneCameraPipeline::SCENE_CAM_PIPELINE_FORWARD) {
2268bf80f4bSopenharmony_ci                auto ecs0 = interface_cast<SCENE_NS::IEcsObject>(GetSelf());
2278bf80f4bSopenharmony_ci                auto ecs = ecs0->GetEcs();
2288bf80f4bSopenharmony_ci                auto ent = ecs0->GetEntity();
2298bf80f4bSopenharmony_ci                if (auto cameraManager = CORE_NS::GetManager<CORE3D_NS::ICameraComponentManager>(*ecs)) {
2308bf80f4bSopenharmony_ci                    if (cameraManager->HasComponent(ent)) {
2318bf80f4bSopenharmony_ci                        auto data = cameraManager->Get(ent);
2328bf80f4bSopenharmony_ci                        data.colorTargetCustomization.clear();
2338bf80f4bSopenharmony_ci                        data.colorTargetCustomization.push_back({ BASE_NS::BASE_FORMAT_R16G16B16A16_SFLOAT, {} });
2348bf80f4bSopenharmony_ci                        cameraManager->Set(ent, data);
2358bf80f4bSopenharmony_ci                    }
2368bf80f4bSopenharmony_ci                }
2378bf80f4bSopenharmony_ci            };
2388bf80f4bSopenharmony_ci        };
2398bf80f4bSopenharmony_ci        updateCustom();
2408bf80f4bSopenharmony_ci        RenderingPipeline()->OnChanged()->AddHandler(
2418bf80f4bSopenharmony_ci            META_NS::MakeCallback<META_NS::IOnChanged>(updateCustom), reinterpret_cast<uint64_t>(this));
2428bf80f4bSopenharmony_ci        return true;
2438bf80f4bSopenharmony_ci    }
2448bf80f4bSopenharmony_ci
2458bf80f4bSopenharmony_ci    void Destroy() override {}
2468bf80f4bSopenharmony_ci
2478bf80f4bSopenharmony_ci    BASE_NS::vector<SCENE_NS::ICamera::Ptr> multiviewCameras_;
2488bf80f4bSopenharmony_ci
2498bf80f4bSopenharmony_ci    // ToDo: Should someday listen to flags (or even entity changes from engine in case multiview is set up there)
2508bf80f4bSopenharmony_ci    void AddMultiviewCamera(ICamera::Ptr camera) override
2518bf80f4bSopenharmony_ci    {
2528bf80f4bSopenharmony_ci        if (camera) {
2538bf80f4bSopenharmony_ci            // add render bit
2548bf80f4bSopenharmony_ci            auto flags = META_NS::GetValue(camera->PipelineFlags()) | CORE3D_NS::CameraComponent::MULTI_VIEW_ONLY_BIT;
2558bf80f4bSopenharmony_ci            camera->PipelineFlags()->SetValue(flags);
2568bf80f4bSopenharmony_ci            // store to array and ecs
2578bf80f4bSopenharmony_ci            if (auto sh = SceneHolder()) {
2588bf80f4bSopenharmony_ci                sh->QueueEngineTask(MakeTask(
2598bf80f4bSopenharmony_ci                                        [source = interface_cast<SCENE_NS::IEcsObject>(camera)->GetEntity(),
2608bf80f4bSopenharmony_ci                                            target = GetSelf<SCENE_NS::IEcsObject>()->GetEntity()](auto sh) {
2618bf80f4bSopenharmony_ci                                            sh->SetMultiviewCamera(target, source);
2628bf80f4bSopenharmony_ci                                            return false;
2638bf80f4bSopenharmony_ci                                        },
2648bf80f4bSopenharmony_ci                                        sh),
2658bf80f4bSopenharmony_ci                    false);
2668bf80f4bSopenharmony_ci            }
2678bf80f4bSopenharmony_ci            // hold strong ref (allow adding multiple times)
2688bf80f4bSopenharmony_ci            multiviewCameras_.push_back(camera);
2698bf80f4bSopenharmony_ci        }
2708bf80f4bSopenharmony_ci    }
2718bf80f4bSopenharmony_ci
2728bf80f4bSopenharmony_ci    void RemoveMultiviewCamera(const ICamera::Ptr& camera) override
2738bf80f4bSopenharmony_ci    {
2748bf80f4bSopenharmony_ci        if (!camera) {
2758bf80f4bSopenharmony_ci            return;
2768bf80f4bSopenharmony_ci        }
2778bf80f4bSopenharmony_ci        size_t count = 0;
2788bf80f4bSopenharmony_ci        // release refs
2798bf80f4bSopenharmony_ci        for (size_t ii = 0; ii < multiviewCameras_.size();) {
2808bf80f4bSopenharmony_ci            if (multiviewCameras_[ii] == camera) // assuming shared ptr compares the object it points
2818bf80f4bSopenharmony_ci            {
2828bf80f4bSopenharmony_ci                if (++count == 1) {
2838bf80f4bSopenharmony_ci                    multiviewCameras_.erase(multiviewCameras_.cbegin() + ii);
2848bf80f4bSopenharmony_ci                } else {
2858bf80f4bSopenharmony_ci                    break;
2868bf80f4bSopenharmony_ci                }
2878bf80f4bSopenharmony_ci            } else {
2888bf80f4bSopenharmony_ci                ii++;
2898bf80f4bSopenharmony_ci            }
2908bf80f4bSopenharmony_ci        }
2918bf80f4bSopenharmony_ci
2928bf80f4bSopenharmony_ci        if (count == 1) {
2938bf80f4bSopenharmony_ci            // remove render-bit
2948bf80f4bSopenharmony_ci            auto flags = META_NS::GetValue(camera->PipelineFlags()) & ~CORE3D_NS::CameraComponent::MULTI_VIEW_ONLY_BIT;
2958bf80f4bSopenharmony_ci            camera->PipelineFlags()->SetValue(flags);
2968bf80f4bSopenharmony_ci
2978bf80f4bSopenharmony_ci            // tell ecs
2988bf80f4bSopenharmony_ci            if (auto sh = SceneHolder()) {
2998bf80f4bSopenharmony_ci                sh->QueueEngineTask(MakeTask(
3008bf80f4bSopenharmony_ci                                        [source = interface_cast<SCENE_NS::IEcsObject>(camera)->GetEntity(),
3018bf80f4bSopenharmony_ci                                            target = GetSelf<SCENE_NS::IEcsObject>()->GetEntity()](auto sh) {
3028bf80f4bSopenharmony_ci                                            sh->RemoveMultiviewCamera(target, source);
3038bf80f4bSopenharmony_ci                                            return false;
3048bf80f4bSopenharmony_ci                                        },
3058bf80f4bSopenharmony_ci                                        sh),
3068bf80f4bSopenharmony_ci                    false);
3078bf80f4bSopenharmony_ci            }
3088bf80f4bSopenharmony_ci        }
3098bf80f4bSopenharmony_ci    }
3108bf80f4bSopenharmony_ci    SCENE_NS::IPickingResult::Ptr ScreenToWorld(BASE_NS::Math::Vec3 screenCoordinate) const override
3118bf80f4bSopenharmony_ci    {
3128bf80f4bSopenharmony_ci        auto ret = objectRegistry_->Create<SCENE_NS::IPickingResult>(SCENE_NS::ClassId::PendingVec3Request);
3138bf80f4bSopenharmony_ci        if (ret && SceneHolder()) {
3148bf80f4bSopenharmony_ci            SceneHolder()->QueueEngineTask(
3158bf80f4bSopenharmony_ci                META_NS::MakeCallback<META_NS::ITaskQueueTask>(
3168bf80f4bSopenharmony_ci                    [screenCoordinate, weakRet = BASE_NS::weak_ptr(ret), weakSh = sceneHolder_,
3178bf80f4bSopenharmony_ci                        weakSelf = BASE_NS::weak_ptr(ecsObject_)]() {
3188bf80f4bSopenharmony_ci                        if (auto sh = weakSh.lock()) {
3198bf80f4bSopenharmony_ci                            if (auto ret = weakRet.lock()) {
3208bf80f4bSopenharmony_ci                                if (auto self = weakSelf.lock()) {
3218bf80f4bSopenharmony_ci                                    if (sh->ScreenToWorld(ret, self->GetEntity(), screenCoordinate)) {
3228bf80f4bSopenharmony_ci                                        sh->QueueApplicationTask(
3238bf80f4bSopenharmony_ci                                            META_NS::MakeCallback<META_NS::ITaskQueueTask>([weakRet]() {
3248bf80f4bSopenharmony_ci                                                if (auto writable = interface_pointer_cast<
3258bf80f4bSopenharmony_ci                                                        SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>(weakRet)) {
3268bf80f4bSopenharmony_ci                                                    writable->MarkReady();
3278bf80f4bSopenharmony_ci                                                }
3288bf80f4bSopenharmony_ci                                                return false;
3298bf80f4bSopenharmony_ci                                            }),
3308bf80f4bSopenharmony_ci                                            false);
3318bf80f4bSopenharmony_ci                                    }
3328bf80f4bSopenharmony_ci                                }
3338bf80f4bSopenharmony_ci                            }
3348bf80f4bSopenharmony_ci                        }
3358bf80f4bSopenharmony_ci                        return false;
3368bf80f4bSopenharmony_ci                    }),
3378bf80f4bSopenharmony_ci                false);
3388bf80f4bSopenharmony_ci            return ret;
3398bf80f4bSopenharmony_ci        }
3408bf80f4bSopenharmony_ci        return SCENE_NS::IPickingResult::Ptr();
3418bf80f4bSopenharmony_ci    }
3428bf80f4bSopenharmony_ci
3438bf80f4bSopenharmony_ci    SCENE_NS::IPickingResult::Ptr WorldToScreen(BASE_NS::Math::Vec3 worldCoordinate) const override
3448bf80f4bSopenharmony_ci    {
3458bf80f4bSopenharmony_ci        auto ret = objectRegistry_->Create<SCENE_NS::IPickingResult>(SCENE_NS::ClassId::PendingVec3Request);
3468bf80f4bSopenharmony_ci        if (ret && SceneHolder()) {
3478bf80f4bSopenharmony_ci            SceneHolder()->QueueEngineTask(
3488bf80f4bSopenharmony_ci                META_NS::MakeCallback<META_NS::ITaskQueueTask>(
3498bf80f4bSopenharmony_ci                    [worldCoordinate, weakRet = BASE_NS::weak_ptr(ret), weakSh = sceneHolder_,
3508bf80f4bSopenharmony_ci                        weakSelf = BASE_NS::weak_ptr(ecsObject_)]() {
3518bf80f4bSopenharmony_ci                        if (auto sh = weakSh.lock()) {
3528bf80f4bSopenharmony_ci                            if (auto ret = weakRet.lock()) {
3538bf80f4bSopenharmony_ci                                if (auto self = weakSelf.lock()) {
3548bf80f4bSopenharmony_ci                                    if (sh->WorldToScreen(ret, self->GetEntity(), worldCoordinate)) {
3558bf80f4bSopenharmony_ci                                        sh->QueueApplicationTask(
3568bf80f4bSopenharmony_ci                                            META_NS::MakeCallback<META_NS::ITaskQueueTask>([weakRet]() {
3578bf80f4bSopenharmony_ci                                                if (auto writable = interface_pointer_cast<
3588bf80f4bSopenharmony_ci                                                        SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>(weakRet)) {
3598bf80f4bSopenharmony_ci                                                    writable->MarkReady();
3608bf80f4bSopenharmony_ci                                                }
3618bf80f4bSopenharmony_ci                                                return false;
3628bf80f4bSopenharmony_ci                                            }),
3638bf80f4bSopenharmony_ci                                            false);
3648bf80f4bSopenharmony_ci                                    }
3658bf80f4bSopenharmony_ci                                }
3668bf80f4bSopenharmony_ci                            }
3678bf80f4bSopenharmony_ci                        }
3688bf80f4bSopenharmony_ci                        return false;
3698bf80f4bSopenharmony_ci                    }),
3708bf80f4bSopenharmony_ci                false);
3718bf80f4bSopenharmony_ci            return ret;
3728bf80f4bSopenharmony_ci        }
3738bf80f4bSopenharmony_ci        return SCENE_NS::IPickingResult::Ptr();
3748bf80f4bSopenharmony_ci    }
3758bf80f4bSopenharmony_ci
3768bf80f4bSopenharmony_ci    SCENE_NS::IRayCastResult::Ptr RayCastFromCamera(const BASE_NS::Math::Vec2& screenPos) const override
3778bf80f4bSopenharmony_ci    {
3788bf80f4bSopenharmony_ci        auto ret =
3798bf80f4bSopenharmony_ci            META_NS::GetObjectRegistry().Create<SCENE_NS::IRayCastResult>(SCENE_NS::ClassId::PendingDistanceRequest);
3808bf80f4bSopenharmony_ci        if (ret && SceneHolder()) {
3818bf80f4bSopenharmony_ci            SceneHolder()->QueueEngineTask(
3828bf80f4bSopenharmony_ci                META_NS::MakeCallback<META_NS::ITaskQueueTask>(
3838bf80f4bSopenharmony_ci                    [pos = screenPos, weakRet = BASE_NS::weak_ptr(ret), weakSh = sceneHolder_,
3848bf80f4bSopenharmony_ci                        weakSelf = BASE_NS::weak_ptr(ecsObject_), weakScene = BASE_NS::weak_ptr(GetScene())]() {
3858bf80f4bSopenharmony_ci                        if (auto sh = weakSh.lock()) {
3868bf80f4bSopenharmony_ci                            if (auto ret = weakRet.lock()) {
3878bf80f4bSopenharmony_ci                                if (auto self = weakSelf.lock()) {
3888bf80f4bSopenharmony_ci                                    if (sh->RayCastFromCamera(ret, self->GetEntity(), pos)) {
3898bf80f4bSopenharmony_ci                                        sh->QueueApplicationTask(
3908bf80f4bSopenharmony_ci                                            META_NS::MakeCallback<META_NS::ITaskQueueTask>([weakRet, weakScene]() {
3918bf80f4bSopenharmony_ci                                                if (auto writable = interface_pointer_cast<
3928bf80f4bSopenharmony_ci                                                        SCENE_NS::IPendingRequestData<SCENE_NS::NodeDistance>>(
3938bf80f4bSopenharmony_ci                                                        weakRet)) {
3948bf80f4bSopenharmony_ci                                                    if (auto scene = weakScene.lock()) {
3958bf80f4bSopenharmony_ci                                                        // resolve proxy nodes
3968bf80f4bSopenharmony_ci                                                        for (size_t ii = writable->MetaData().size(); ii > 0;) {
3978bf80f4bSopenharmony_ci                                                            --ii;
3988bf80f4bSopenharmony_ci                                                            writable->MutableData().at(ii).node =
3998bf80f4bSopenharmony_ci                                                                scene->GetNode(writable->MetaData().at(ii));
4008bf80f4bSopenharmony_ci                                                        }
4018bf80f4bSopenharmony_ci                                                        writable->MarkReady();
4028bf80f4bSopenharmony_ci                                                    }
4038bf80f4bSopenharmony_ci                                                }
4048bf80f4bSopenharmony_ci                                                return false;
4058bf80f4bSopenharmony_ci                                            }),
4068bf80f4bSopenharmony_ci                                            false);
4078bf80f4bSopenharmony_ci                                    }
4088bf80f4bSopenharmony_ci                                }
4098bf80f4bSopenharmony_ci                            }
4108bf80f4bSopenharmony_ci                        }
4118bf80f4bSopenharmony_ci                        return false;
4128bf80f4bSopenharmony_ci                    }),
4138bf80f4bSopenharmony_ci                false);
4148bf80f4bSopenharmony_ci            return ret;
4158bf80f4bSopenharmony_ci        }
4168bf80f4bSopenharmony_ci        return SCENE_NS::IRayCastResult::Ptr();
4178bf80f4bSopenharmony_ci    }
4188bf80f4bSopenharmony_ci
4198bf80f4bSopenharmony_ci    SCENE_NS::IRayCastResult::Ptr RayCastFromCamera(
4208bf80f4bSopenharmony_ci        const BASE_NS::Math::Vec2& screenPos, uint64_t layerMask) const override
4218bf80f4bSopenharmony_ci    {
4228bf80f4bSopenharmony_ci        auto ret = objectRegistry_->Create<SCENE_NS::IRayCastResult>(SCENE_NS::ClassId::PendingDistanceRequest);
4238bf80f4bSopenharmony_ci        if (ret && SceneHolder()) {
4248bf80f4bSopenharmony_ci            SceneHolder()->QueueEngineTask(
4258bf80f4bSopenharmony_ci                META_NS::MakeCallback<META_NS::ITaskQueueTask>(
4268bf80f4bSopenharmony_ci                    [pos = screenPos, weakRet = BASE_NS::weak_ptr(ret), weakSh = sceneHolder_, layerMask,
4278bf80f4bSopenharmony_ci                        weakSelf = BASE_NS::weak_ptr(ecsObject_), weakScene = BASE_NS::weak_ptr(GetScene())]() {
4288bf80f4bSopenharmony_ci                        if (auto sh = weakSh.lock()) {
4298bf80f4bSopenharmony_ci                            if (auto ret = weakRet.lock()) {
4308bf80f4bSopenharmony_ci                                if (auto self = weakSelf.lock()) {
4318bf80f4bSopenharmony_ci                                    if (sh->RayCastFromCamera(ret, self->GetEntity(), pos, layerMask)) {
4328bf80f4bSopenharmony_ci                                        sh->QueueApplicationTask(
4338bf80f4bSopenharmony_ci                                            META_NS::MakeCallback<META_NS::ITaskQueueTask>([weakRet, weakScene]() {
4348bf80f4bSopenharmony_ci                                                if (auto writable = interface_pointer_cast<
4358bf80f4bSopenharmony_ci                                                        SCENE_NS::IPendingRequestData<SCENE_NS::NodeDistance>>(
4368bf80f4bSopenharmony_ci                                                        weakRet)) {
4378bf80f4bSopenharmony_ci                                                    if (auto scene = weakScene.lock()) {
4388bf80f4bSopenharmony_ci                                                        // resolve proxy nodes
4398bf80f4bSopenharmony_ci                                                        for (size_t ii = writable->MetaData().size(); ii > 0;) {
4408bf80f4bSopenharmony_ci                                                            --ii;
4418bf80f4bSopenharmony_ci                                                            writable->MutableData().at(ii).node =
4428bf80f4bSopenharmony_ci                                                                scene->GetNode(writable->MetaData().at(ii));
4438bf80f4bSopenharmony_ci                                                        }
4448bf80f4bSopenharmony_ci                                                        writable->MarkReady();
4458bf80f4bSopenharmony_ci                                                    }
4468bf80f4bSopenharmony_ci                                                }
4478bf80f4bSopenharmony_ci                                                return false;
4488bf80f4bSopenharmony_ci                                            }),
4498bf80f4bSopenharmony_ci                                            false);
4508bf80f4bSopenharmony_ci                                    }
4518bf80f4bSopenharmony_ci                                }
4528bf80f4bSopenharmony_ci                            }
4538bf80f4bSopenharmony_ci                        }
4548bf80f4bSopenharmony_ci                        return false;
4558bf80f4bSopenharmony_ci                    }),
4568bf80f4bSopenharmony_ci                false);
4578bf80f4bSopenharmony_ci            return ret;
4588bf80f4bSopenharmony_ci        }
4598bf80f4bSopenharmony_ci        return SCENE_NS::IRayCastResult::Ptr();
4608bf80f4bSopenharmony_ci    }
4618bf80f4bSopenharmony_ci
4628bf80f4bSopenharmony_ci    SCENE_NS::IPickingResult::Ptr RayFromCamera(const BASE_NS::Math::Vec2& screenPos) const override
4638bf80f4bSopenharmony_ci    {
4648bf80f4bSopenharmony_ci        auto ret = objectRegistry_->Create<SCENE_NS::IPickingResult>(SCENE_NS::ClassId::PendingVec3Request);
4658bf80f4bSopenharmony_ci        if (ret && SceneHolder()) {
4668bf80f4bSopenharmony_ci            SceneHolder()->QueueEngineTask(
4678bf80f4bSopenharmony_ci                META_NS::MakeCallback<META_NS::ITaskQueueTask>(
4688bf80f4bSopenharmony_ci                    [pos = screenPos, weakRet = BASE_NS::weak_ptr(ret), weakSh = sceneHolder_,
4698bf80f4bSopenharmony_ci                        weakSelf = BASE_NS::weak_ptr(ecsObject_), weakScene = BASE_NS::weak_ptr(GetScene())]() {
4708bf80f4bSopenharmony_ci                        if (auto sh = weakSh.lock()) {
4718bf80f4bSopenharmony_ci                            if (auto ret = weakRet.lock()) {
4728bf80f4bSopenharmony_ci                                if (auto self = weakSelf.lock()) {
4738bf80f4bSopenharmony_ci                                    if (sh->RayFromCamera(ret, self->GetEntity(), pos)) {
4748bf80f4bSopenharmony_ci                                        sh->QueueApplicationTask(
4758bf80f4bSopenharmony_ci                                            META_NS::MakeCallback<META_NS::ITaskQueueTask>([weakRet, weakScene]() {
4768bf80f4bSopenharmony_ci                                                if (auto writable = interface_pointer_cast<
4778bf80f4bSopenharmony_ci                                                        SCENE_NS::IPendingRequestData<SCENE_NS::NodeDistance>>(
4788bf80f4bSopenharmony_ci                                                        weakRet)) {
4798bf80f4bSopenharmony_ci                                                    if (auto scene = weakScene.lock()) {
4808bf80f4bSopenharmony_ci                                                        // resolve proxy nodes
4818bf80f4bSopenharmony_ci                                                        for (size_t ii = writable->MetaData().size(); ii > 0;) {
4828bf80f4bSopenharmony_ci                                                            --ii;
4838bf80f4bSopenharmony_ci                                                            writable->MutableData().at(ii).node =
4848bf80f4bSopenharmony_ci                                                                scene->GetNode(writable->MetaData().at(ii));
4858bf80f4bSopenharmony_ci                                                        }
4868bf80f4bSopenharmony_ci                                                        writable->MarkReady();
4878bf80f4bSopenharmony_ci                                                    }
4888bf80f4bSopenharmony_ci                                                }
4898bf80f4bSopenharmony_ci                                                return false;
4908bf80f4bSopenharmony_ci                                            }),
4918bf80f4bSopenharmony_ci                                            false);
4928bf80f4bSopenharmony_ci                                    }
4938bf80f4bSopenharmony_ci                                }
4948bf80f4bSopenharmony_ci                            }
4958bf80f4bSopenharmony_ci                        }
4968bf80f4bSopenharmony_ci                        return false;
4978bf80f4bSopenharmony_ci                    }),
4988bf80f4bSopenharmony_ci                false);
4998bf80f4bSopenharmony_ci            return ret;
5008bf80f4bSopenharmony_ci        }
5018bf80f4bSopenharmony_ci        return SCENE_NS::IPickingResult::Ptr();
5028bf80f4bSopenharmony_ci    }
5038bf80f4bSopenharmony_ci
5048bf80f4bSopenharmony_ci    void SetDefaultRenderTargetSize(uint64_t width, uint64_t height) override
5058bf80f4bSopenharmony_ci    {
5068bf80f4bSopenharmony_ci        RenderTargetSize()->SetDefaultValue(BASE_NS::Math::UVec2(width, height));
5078bf80f4bSopenharmony_ci    }
5088bf80f4bSopenharmony_ci};
5098bf80f4bSopenharmony_ci
5108bf80f4bSopenharmony_ci} // namespace
5118bf80f4bSopenharmony_ci
5128bf80f4bSopenharmony_ciSCENE_BEGIN_NAMESPACE()
5138bf80f4bSopenharmony_ci
5148bf80f4bSopenharmony_civoid RegisterCameraImpl()
5158bf80f4bSopenharmony_ci{
5168bf80f4bSopenharmony_ci    auto& registry = META_NS::GetObjectRegistry();
5178bf80f4bSopenharmony_ci    registry.RegisterObjectType<CameraImpl>();
5188bf80f4bSopenharmony_ci}
5198bf80f4bSopenharmony_ci
5208bf80f4bSopenharmony_civoid UnregisterCameraImpl()
5218bf80f4bSopenharmony_ci{
5228bf80f4bSopenharmony_ci    auto& registry = META_NS::GetObjectRegistry();
5238bf80f4bSopenharmony_ci    registry.UnregisterObjectType<CameraImpl>();
5248bf80f4bSopenharmony_ci}
5258bf80f4bSopenharmony_ci
5268bf80f4bSopenharmony_ciSCENE_END_NAMESPACE()
527