1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include <scene_plugin/api/camera_uid.h> 16#include <scene_plugin/api/postprocess_uid.h> 17 18#include <meta/ext/concrete_base_object.h> 19 20#include "bind_templates.inl" 21#include "intf_postprocess_private.h" 22#include "node_impl.h" 23#include "task_utils.h" 24 25using SCENE_NS::MakeTask; 26 27namespace { 28class CameraImpl 29 : public META_NS::ConcreteBaseMetaObjectFwd<CameraImpl, NodeImpl, SCENE_NS::ClassId::Camera, SCENE_NS::ICamera> { 30 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, FoV, 60.f * BASE_NS::Math::DEG2RAD) 31 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, AspectRatio, -1.f) 32 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, NearPlane, 0.3f) 33 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, FarPlane, 1000.f) 34 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, XMagnification, 0.f) 35 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, YMagnification, 0.f) 36 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, XOffset, 1.f) 37 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, YOffset, 1.f) 38 META_IMPLEMENT_INTERFACE_PROPERTY( 39 SCENE_NS::ICamera, uint8_t, Projection, SCENE_NS::ICamera::SCENE_CAM_PROJECTION_PERSPECTIVE) 40 META_IMPLEMENT_INTERFACE_PROPERTY( 41 SCENE_NS::ICamera, uint8_t, Culling, SCENE_NS::ICamera::SCENE_CAM_CULLING_VIEW_FRUSTUM) 42 META_IMPLEMENT_INTERFACE_PROPERTY( 43 SCENE_NS::ICamera, uint8_t, RenderingPipeline, SCENE_NS::ICamera::SCENE_CAM_PIPELINE_FORWARD) 44 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, uint32_t, SceneFlags, 0) 45 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, uint32_t, PipelineFlags, (1 << 3)) 46 META_IMPLEMENT_INTERFACE_PROPERTY( 47 SCENE_NS::ICamera, BASE_NS::Math::Vec4, Viewport, BASE_NS::Math::Vec4(0.f, 0.f, 1.f, 1.f)) 48 META_IMPLEMENT_INTERFACE_PROPERTY( 49 SCENE_NS::ICamera, BASE_NS::Math::Vec4, Scissor, BASE_NS::Math::Vec4(0.f, 0.f, 1.f, 1.f)) 50 META_IMPLEMENT_INTERFACE_PROPERTY( 51 SCENE_NS::ICamera, BASE_NS::Math::UVec2, RenderTargetSize, BASE_NS::Math::UVec2(0, 0)) 52 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, SCENE_NS::Color, ClearColor, SCENE_NS::Colors::TRANSPARENT) 53 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, float, ClearDepth, 1.f) 54 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, BASE_NS::string, RenderNodeGraphFile, {}) 55 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ICamera, SCENE_NS::IPostProcess::Ptr, PostProcess, {}) 56 57 static constexpr BASE_NS::string_view CAMERA_COMPONENT_NAME = "CameraComponent"; 58 static constexpr size_t CAMERA_COMPONENT_NAME_LEN = CAMERA_COMPONENT_NAME.size() + 1; 59 static constexpr BASE_NS::string_view CAMERA_FOV = "CameraComponent.yFov"; 60 static constexpr BASE_NS::string_view CAMERA_ASPECT = "CameraComponent.aspect"; 61 static constexpr BASE_NS::string_view CAMERA_ZNEAR = "CameraComponent.zNear"; 62 static constexpr BASE_NS::string_view CAMERA_ZFAR = "CameraComponent.zFar"; 63 static constexpr BASE_NS::string_view CAMERA_XMAG = "CameraComponent.xMag"; 64 static constexpr BASE_NS::string_view CAMERA_YMAG = "CameraComponent.yMag"; 65 static constexpr BASE_NS::string_view CAMERA_XOFFSET = "CameraComponent.xOffset"; 66 static constexpr BASE_NS::string_view CAMERA_YOFFSET = "CameraComponent.yOffset"; 67 static constexpr BASE_NS::string_view CAMERA_PROJECTION = "CameraComponent.projection"; 68 static constexpr BASE_NS::string_view CAMERA_CULLING = "CameraComponent.culling"; 69 static constexpr BASE_NS::string_view CAMERA_RENDERINGPIPELINE = "CameraComponent.renderingPipeline"; 70 static constexpr BASE_NS::string_view CAMERA_SCENEFLAGS = "CameraComponent.sceneFlags"; 71 static constexpr BASE_NS::string_view CAMERA_PIPELINEFLAGS = "CameraComponent.pipelineFlags"; 72 static constexpr BASE_NS::string_view CAMERA_SCISSOR = "CameraComponent.scissor"; 73 static constexpr BASE_NS::string_view CAMERA_VIEWPORT = "CameraComponent.viewport"; 74 static constexpr BASE_NS::string_view CAMERA_CLEARCOLORVALUE = "CameraComponent.clearColorValue"; 75 static constexpr BASE_NS::string_view CAMERA_CLEARDEPTHVALUE = "CameraComponent.clearDepthValue"; 76 static constexpr BASE_NS::string_view CAMERA_LAYERMASK = "CameraComponent.layerMask"; 77 static constexpr BASE_NS::string_view CAMERA_RENDERRESOLUTION = "CameraComponent.renderResolution"; 78 static constexpr BASE_NS::string_view CAMERA_POSTPROCESS = "CameraComponent.postProcess"; 79 80 bool Build(const IMetadata::Ptr& data) override 81 { 82 bool ret = false; 83 if (ret = NodeImpl::Build(data); ret) { 84 PropertyNameMask()[CAMERA_COMPONENT_NAME] = { CAMERA_FOV.substr(CAMERA_COMPONENT_NAME_LEN), 85 CAMERA_ASPECT.substr(CAMERA_COMPONENT_NAME_LEN), CAMERA_ZNEAR.substr(CAMERA_COMPONENT_NAME_LEN), 86 CAMERA_ZFAR.substr(CAMERA_COMPONENT_NAME_LEN), CAMERA_XMAG.substr(CAMERA_COMPONENT_NAME_LEN), 87 CAMERA_YMAG.substr(CAMERA_COMPONENT_NAME_LEN), CAMERA_XOFFSET.substr(CAMERA_COMPONENT_NAME_LEN), 88 CAMERA_YOFFSET.substr(CAMERA_COMPONENT_NAME_LEN), CAMERA_PROJECTION.substr(CAMERA_COMPONENT_NAME_LEN), 89 CAMERA_CULLING.substr(CAMERA_COMPONENT_NAME_LEN), 90 CAMERA_RENDERINGPIPELINE.substr(CAMERA_COMPONENT_NAME_LEN), 91 CAMERA_SCENEFLAGS.substr(CAMERA_COMPONENT_NAME_LEN), 92 CAMERA_PIPELINEFLAGS.substr(CAMERA_COMPONENT_NAME_LEN), 93 CAMERA_SCISSOR.substr(CAMERA_COMPONENT_NAME_LEN), CAMERA_VIEWPORT.substr(CAMERA_COMPONENT_NAME_LEN), 94 CAMERA_CLEARCOLORVALUE.substr(CAMERA_COMPONENT_NAME_LEN), 95 CAMERA_CLEARDEPTHVALUE.substr(CAMERA_COMPONENT_NAME_LEN), 96 CAMERA_LAYERMASK.substr(CAMERA_COMPONENT_NAME_LEN), 97 CAMERA_POSTPROCESS.substr(CAMERA_COMPONENT_NAME_LEN), 98 CAMERA_RENDERRESOLUTION.substr(CAMERA_COMPONENT_NAME_LEN) }; 99 } 100 return ret; 101 } 102 103 bool CompleteInitialization(const BASE_NS::string& path) override 104 { 105 if (!NodeImpl::CompleteInitialization(path)) { 106 return false; 107 } 108 109 auto meta = interface_pointer_cast<META_NS::IMetadata>(ecsObject_); 110 BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(FoV), meta, CAMERA_FOV); 111 BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(AspectRatio), meta, CAMERA_ASPECT); 112 BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(NearPlane), meta, CAMERA_ZNEAR); 113 BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(FarPlane), meta, CAMERA_ZFAR); 114 BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(XMagnification), meta, CAMERA_XMAG); 115 BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(YMagnification), meta, CAMERA_YMAG); 116 BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(XOffset), meta, CAMERA_XOFFSET); 117 BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(YOffset), meta, CAMERA_YOFFSET); 118 BindChanges<uint8_t>(propHandler_, META_ACCESS_PROPERTY(Projection), meta, CAMERA_PROJECTION); 119 BindChanges<uint8_t>(propHandler_, META_ACCESS_PROPERTY(Culling), meta, CAMERA_CULLING); 120 BindChanges<uint8_t>(propHandler_, META_ACCESS_PROPERTY(RenderingPipeline), meta, CAMERA_RENDERINGPIPELINE); 121 BindChanges<uint32_t>(propHandler_, META_ACCESS_PROPERTY(SceneFlags), meta, CAMERA_SCENEFLAGS); 122 BindChanges<uint32_t>(propHandler_, META_ACCESS_PROPERTY(PipelineFlags), meta, CAMERA_PIPELINEFLAGS); 123 BindChanges<BASE_NS::Math::Vec4>(propHandler_, META_ACCESS_PROPERTY(Scissor), meta, CAMERA_SCISSOR); 124 BindChanges<BASE_NS::Math::Vec4>(propHandler_, META_ACCESS_PROPERTY(Viewport), meta, CAMERA_VIEWPORT); 125 ConvertBindChanges<SCENE_NS::Color, BASE_NS::Math::Vec4>( 126 propHandler_, META_ACCESS_PROPERTY(ClearColor), meta, CAMERA_CLEARCOLORVALUE); 127 BindChanges<float>(propHandler_, META_ACCESS_PROPERTY(ClearDepth), meta, CAMERA_CLEARDEPTHVALUE); 128 129 // override INode default handling for LayerMask 130 BindChanges<uint64_t>(propHandler_, NodeImpl::META_ACCESS_PROPERTY(LayerMask), meta, CAMERA_LAYERMASK); 131 132 if (auto scene = GetScene()) { 133 propHandler_.NewHandler(nullptr, nullptr) 134 .Subscribe(META_ACCESS_PROPERTY(RenderTargetSize), 135 META_NS::MakeCallback<META_NS::IOnChanged>( 136 [this](const auto& scene) { 137 if (auto ecsObject = EcsObject(); scene && ecsObject) { 138 auto renderSize = META_NS::GetValue(RenderTargetSize()); 139 if (renderSize.x != 0 && renderSize.y != 0) { 140 SceneHolder()->SetRenderSize(renderSize.x, renderSize.y, ecsObject->GetEntity().id); 141 } 142 } 143 }, 144 scene)); 145 } else { 146 // Engine side does not automatically resize camera resources even the size changes 147 BindChanges<BASE_NS::Math::UVec2>( 148 propHandler_, META_ACCESS_PROPERTY(RenderTargetSize), meta, CAMERA_RENDERRESOLUTION); 149 } 150 151 if (auto postProcess = meta->GetPropertyByName(CAMERA_POSTPROCESS)) { 152 // To quickly test / verify post-process bindings 153 // callback to carry out when toolkit side changes 154 auto metaCallback = [this](META_NS::IProperty::Ptr postProcessEntity, 155 SCENE_NS::IPostProcess::Ptr postProcessBridge) { 156 auto typed = META_NS::Property<CORE_NS::Entity>(postProcessEntity); 157 auto entity = META_NS::GetValue(typed); 158 auto sh = SceneHolder(); 159 auto ecs = sh->GetEcs(); 160 if (!CORE_NS::EntityUtil::IsValid(entity)) { 161 // engine does not have existing entity, create new one 162 entity = sh->CreatePostProcess(); 163 META_NS::SetValue(typed, entity); 164 } 165 // values from toolkit dominate initialization 166 interface_cast<IPostProcessPrivate>(postProcessBridge)->SetEntity(entity, sh, false); 167 }; 168 169 // callback to carry out if the engine side drives the change 170 auto engineCallback = [this](META_NS::IProperty::Ptr postProcessEntity) { 171 auto entity = META_NS::GetValue(META_NS::Property<CORE_NS::Entity>(postProcessEntity)); 172 auto sh = SceneHolder(); 173 auto ecs = sh->GetEcs(); 174 if (!CORE_NS::EntityUtil::IsValid(entity)) { 175 META_NS::SetValue(PostProcess(), SCENE_NS::IPostProcess::Ptr {}); 176 } else { 177 auto ppo = META_NS::GetObjectRegistry().Create<IPostProcessPrivate>(SCENE_NS::ClassId::PostProcess); 178 // values from ecs dominate initialization 179 ppo->SetEntity(entity, sh, true); 180 META_NS::SetValue(PostProcess(), interface_pointer_cast<SCENE_NS::IPostProcess>(ppo)); 181 } 182 }; 183 184 if (auto bridge = META_NS::GetValue(PostProcess())) { 185 metaCallback(postProcess, bridge); 186 } else { 187 engineCallback(postProcess); 188 } 189 190 // setup subscription for toolkit changes 191 PostProcess()->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>([this, metaCallback]() { 192 if (auto bridge = META_NS::GetValue(PostProcess())) { 193 if (auto meta = interface_pointer_cast<META_NS::IMetadata>(ecsObject_)) { 194 if (auto postProcess = meta->GetPropertyByName(CAMERA_POSTPROCESS)) { 195 metaCallback(postProcess, bridge); 196 } 197 } 198 } else { 199 if (auto meta = interface_pointer_cast<META_NS::IMetadata>(ecsObject_)) { 200 if (auto postProcess = meta->GetPropertyByName(CAMERA_POSTPROCESS)) { 201 if (auto typed = META_NS::Property<CORE_NS::Entity>(postProcess)) { 202 META_NS::SetValue(typed, CORE_NS::Entity()); 203 } 204 } 205 } 206 } 207 }), 208 reinterpret_cast<uint64_t>(this)); 209 210 // setup subscription to ecs changes 211 postProcess->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>([this, engineCallback]() { 212 if (auto meta = this->GetSelf<META_NS::IMetadata>()) { 213 if (auto postProcess = meta->GetPropertyByName(CAMERA_POSTPROCESS)) { 214 engineCallback(postProcess); 215 } 216 } 217 }), 218 reinterpret_cast<uint64_t>(this)); 219 ConvertBindChanges<SCENE_NS::IPostProcess::Ptr, CORE_NS::Entity, EntityConverter<SCENE_NS::IPostProcess>>( 220 propHandler_, PostProcess(), meta, "CameraComponent.postProcess", ONE_WAY_TO_ECS); 221 } 222 223 auto updateCustom = [this]() { 224 auto pipeline = RenderingPipeline()->GetValue(); 225 if (pipeline == SCENE_NS::ICamera::SceneCameraPipeline::SCENE_CAM_PIPELINE_FORWARD) { 226 auto ecs0 = interface_cast<SCENE_NS::IEcsObject>(GetSelf()); 227 auto ecs = ecs0->GetEcs(); 228 auto ent = ecs0->GetEntity(); 229 if (auto cameraManager = CORE_NS::GetManager<CORE3D_NS::ICameraComponentManager>(*ecs)) { 230 if (cameraManager->HasComponent(ent)) { 231 auto data = cameraManager->Get(ent); 232 data.colorTargetCustomization.clear(); 233 data.colorTargetCustomization.push_back({ BASE_NS::BASE_FORMAT_R16G16B16A16_SFLOAT, {} }); 234 cameraManager->Set(ent, data); 235 } 236 } 237 }; 238 }; 239 updateCustom(); 240 RenderingPipeline()->OnChanged()->AddHandler( 241 META_NS::MakeCallback<META_NS::IOnChanged>(updateCustom), reinterpret_cast<uint64_t>(this)); 242 return true; 243 } 244 245 void Destroy() override {} 246 247 BASE_NS::vector<SCENE_NS::ICamera::Ptr> multiviewCameras_; 248 249 // ToDo: Should someday listen to flags (or even entity changes from engine in case multiview is set up there) 250 void AddMultiviewCamera(ICamera::Ptr camera) override 251 { 252 if (camera) { 253 // add render bit 254 auto flags = META_NS::GetValue(camera->PipelineFlags()) | CORE3D_NS::CameraComponent::MULTI_VIEW_ONLY_BIT; 255 camera->PipelineFlags()->SetValue(flags); 256 // store to array and ecs 257 if (auto sh = SceneHolder()) { 258 sh->QueueEngineTask(MakeTask( 259 [source = interface_cast<SCENE_NS::IEcsObject>(camera)->GetEntity(), 260 target = GetSelf<SCENE_NS::IEcsObject>()->GetEntity()](auto sh) { 261 sh->SetMultiviewCamera(target, source); 262 return false; 263 }, 264 sh), 265 false); 266 } 267 // hold strong ref (allow adding multiple times) 268 multiviewCameras_.push_back(camera); 269 } 270 } 271 272 void RemoveMultiviewCamera(const ICamera::Ptr& camera) override 273 { 274 if (!camera) { 275 return; 276 } 277 size_t count = 0; 278 // release refs 279 for (size_t ii = 0; ii < multiviewCameras_.size();) { 280 if (multiviewCameras_[ii] == camera) // assuming shared ptr compares the object it points 281 { 282 if (++count == 1) { 283 multiviewCameras_.erase(multiviewCameras_.cbegin() + ii); 284 } else { 285 break; 286 } 287 } else { 288 ii++; 289 } 290 } 291 292 if (count == 1) { 293 // remove render-bit 294 auto flags = META_NS::GetValue(camera->PipelineFlags()) & ~CORE3D_NS::CameraComponent::MULTI_VIEW_ONLY_BIT; 295 camera->PipelineFlags()->SetValue(flags); 296 297 // tell ecs 298 if (auto sh = SceneHolder()) { 299 sh->QueueEngineTask(MakeTask( 300 [source = interface_cast<SCENE_NS::IEcsObject>(camera)->GetEntity(), 301 target = GetSelf<SCENE_NS::IEcsObject>()->GetEntity()](auto sh) { 302 sh->RemoveMultiviewCamera(target, source); 303 return false; 304 }, 305 sh), 306 false); 307 } 308 } 309 } 310 SCENE_NS::IPickingResult::Ptr ScreenToWorld(BASE_NS::Math::Vec3 screenCoordinate) const override 311 { 312 auto ret = objectRegistry_->Create<SCENE_NS::IPickingResult>(SCENE_NS::ClassId::PendingVec3Request); 313 if (ret && SceneHolder()) { 314 SceneHolder()->QueueEngineTask( 315 META_NS::MakeCallback<META_NS::ITaskQueueTask>( 316 [screenCoordinate, weakRet = BASE_NS::weak_ptr(ret), weakSh = sceneHolder_, 317 weakSelf = BASE_NS::weak_ptr(ecsObject_)]() { 318 if (auto sh = weakSh.lock()) { 319 if (auto ret = weakRet.lock()) { 320 if (auto self = weakSelf.lock()) { 321 if (sh->ScreenToWorld(ret, self->GetEntity(), screenCoordinate)) { 322 sh->QueueApplicationTask( 323 META_NS::MakeCallback<META_NS::ITaskQueueTask>([weakRet]() { 324 if (auto writable = interface_pointer_cast< 325 SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>(weakRet)) { 326 writable->MarkReady(); 327 } 328 return false; 329 }), 330 false); 331 } 332 } 333 } 334 } 335 return false; 336 }), 337 false); 338 return ret; 339 } 340 return SCENE_NS::IPickingResult::Ptr(); 341 } 342 343 SCENE_NS::IPickingResult::Ptr WorldToScreen(BASE_NS::Math::Vec3 worldCoordinate) const override 344 { 345 auto ret = objectRegistry_->Create<SCENE_NS::IPickingResult>(SCENE_NS::ClassId::PendingVec3Request); 346 if (ret && SceneHolder()) { 347 SceneHolder()->QueueEngineTask( 348 META_NS::MakeCallback<META_NS::ITaskQueueTask>( 349 [worldCoordinate, weakRet = BASE_NS::weak_ptr(ret), weakSh = sceneHolder_, 350 weakSelf = BASE_NS::weak_ptr(ecsObject_)]() { 351 if (auto sh = weakSh.lock()) { 352 if (auto ret = weakRet.lock()) { 353 if (auto self = weakSelf.lock()) { 354 if (sh->WorldToScreen(ret, self->GetEntity(), worldCoordinate)) { 355 sh->QueueApplicationTask( 356 META_NS::MakeCallback<META_NS::ITaskQueueTask>([weakRet]() { 357 if (auto writable = interface_pointer_cast< 358 SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>(weakRet)) { 359 writable->MarkReady(); 360 } 361 return false; 362 }), 363 false); 364 } 365 } 366 } 367 } 368 return false; 369 }), 370 false); 371 return ret; 372 } 373 return SCENE_NS::IPickingResult::Ptr(); 374 } 375 376 SCENE_NS::IRayCastResult::Ptr RayCastFromCamera(const BASE_NS::Math::Vec2& screenPos) const override 377 { 378 auto ret = 379 META_NS::GetObjectRegistry().Create<SCENE_NS::IRayCastResult>(SCENE_NS::ClassId::PendingDistanceRequest); 380 if (ret && SceneHolder()) { 381 SceneHolder()->QueueEngineTask( 382 META_NS::MakeCallback<META_NS::ITaskQueueTask>( 383 [pos = screenPos, weakRet = BASE_NS::weak_ptr(ret), weakSh = sceneHolder_, 384 weakSelf = BASE_NS::weak_ptr(ecsObject_), weakScene = BASE_NS::weak_ptr(GetScene())]() { 385 if (auto sh = weakSh.lock()) { 386 if (auto ret = weakRet.lock()) { 387 if (auto self = weakSelf.lock()) { 388 if (sh->RayCastFromCamera(ret, self->GetEntity(), pos)) { 389 sh->QueueApplicationTask( 390 META_NS::MakeCallback<META_NS::ITaskQueueTask>([weakRet, weakScene]() { 391 if (auto writable = interface_pointer_cast< 392 SCENE_NS::IPendingRequestData<SCENE_NS::NodeDistance>>( 393 weakRet)) { 394 if (auto scene = weakScene.lock()) { 395 // resolve proxy nodes 396 for (size_t ii = writable->MetaData().size(); ii > 0;) { 397 --ii; 398 writable->MutableData().at(ii).node = 399 scene->GetNode(writable->MetaData().at(ii)); 400 } 401 writable->MarkReady(); 402 } 403 } 404 return false; 405 }), 406 false); 407 } 408 } 409 } 410 } 411 return false; 412 }), 413 false); 414 return ret; 415 } 416 return SCENE_NS::IRayCastResult::Ptr(); 417 } 418 419 SCENE_NS::IRayCastResult::Ptr RayCastFromCamera( 420 const BASE_NS::Math::Vec2& screenPos, uint64_t layerMask) const override 421 { 422 auto ret = objectRegistry_->Create<SCENE_NS::IRayCastResult>(SCENE_NS::ClassId::PendingDistanceRequest); 423 if (ret && SceneHolder()) { 424 SceneHolder()->QueueEngineTask( 425 META_NS::MakeCallback<META_NS::ITaskQueueTask>( 426 [pos = screenPos, weakRet = BASE_NS::weak_ptr(ret), weakSh = sceneHolder_, layerMask, 427 weakSelf = BASE_NS::weak_ptr(ecsObject_), weakScene = BASE_NS::weak_ptr(GetScene())]() { 428 if (auto sh = weakSh.lock()) { 429 if (auto ret = weakRet.lock()) { 430 if (auto self = weakSelf.lock()) { 431 if (sh->RayCastFromCamera(ret, self->GetEntity(), pos, layerMask)) { 432 sh->QueueApplicationTask( 433 META_NS::MakeCallback<META_NS::ITaskQueueTask>([weakRet, weakScene]() { 434 if (auto writable = interface_pointer_cast< 435 SCENE_NS::IPendingRequestData<SCENE_NS::NodeDistance>>( 436 weakRet)) { 437 if (auto scene = weakScene.lock()) { 438 // resolve proxy nodes 439 for (size_t ii = writable->MetaData().size(); ii > 0;) { 440 --ii; 441 writable->MutableData().at(ii).node = 442 scene->GetNode(writable->MetaData().at(ii)); 443 } 444 writable->MarkReady(); 445 } 446 } 447 return false; 448 }), 449 false); 450 } 451 } 452 } 453 } 454 return false; 455 }), 456 false); 457 return ret; 458 } 459 return SCENE_NS::IRayCastResult::Ptr(); 460 } 461 462 SCENE_NS::IPickingResult::Ptr RayFromCamera(const BASE_NS::Math::Vec2& screenPos) const override 463 { 464 auto ret = objectRegistry_->Create<SCENE_NS::IPickingResult>(SCENE_NS::ClassId::PendingVec3Request); 465 if (ret && SceneHolder()) { 466 SceneHolder()->QueueEngineTask( 467 META_NS::MakeCallback<META_NS::ITaskQueueTask>( 468 [pos = screenPos, weakRet = BASE_NS::weak_ptr(ret), weakSh = sceneHolder_, 469 weakSelf = BASE_NS::weak_ptr(ecsObject_), weakScene = BASE_NS::weak_ptr(GetScene())]() { 470 if (auto sh = weakSh.lock()) { 471 if (auto ret = weakRet.lock()) { 472 if (auto self = weakSelf.lock()) { 473 if (sh->RayFromCamera(ret, self->GetEntity(), pos)) { 474 sh->QueueApplicationTask( 475 META_NS::MakeCallback<META_NS::ITaskQueueTask>([weakRet, weakScene]() { 476 if (auto writable = interface_pointer_cast< 477 SCENE_NS::IPendingRequestData<SCENE_NS::NodeDistance>>( 478 weakRet)) { 479 if (auto scene = weakScene.lock()) { 480 // resolve proxy nodes 481 for (size_t ii = writable->MetaData().size(); ii > 0;) { 482 --ii; 483 writable->MutableData().at(ii).node = 484 scene->GetNode(writable->MetaData().at(ii)); 485 } 486 writable->MarkReady(); 487 } 488 } 489 return false; 490 }), 491 false); 492 } 493 } 494 } 495 } 496 return false; 497 }), 498 false); 499 return ret; 500 } 501 return SCENE_NS::IPickingResult::Ptr(); 502 } 503 504 void SetDefaultRenderTargetSize(uint64_t width, uint64_t height) override 505 { 506 RenderTargetSize()->SetDefaultValue(BASE_NS::Math::UVec2(width, height)); 507 } 508}; 509 510} // namespace 511 512SCENE_BEGIN_NAMESPACE() 513 514void RegisterCameraImpl() 515{ 516 auto& registry = META_NS::GetObjectRegistry(); 517 registry.RegisterObjectType<CameraImpl>(); 518} 519 520void UnregisterCameraImpl() 521{ 522 auto& registry = META_NS::GetObjectRegistry(); 523 registry.UnregisterObjectType<CameraImpl>(); 524} 525 526SCENE_END_NAMESPACE() 527