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