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
25 using SCENE_NS::MakeTask;
26
27 namespace {
28 class 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
Build(const IMetadata::Ptr & data)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
CompleteInitialization(const BASE_NS::string & path)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
Destroy()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)
AddMultiviewCamera(ICamera::Ptr camera)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
RemoveMultiviewCamera(const ICamera::Ptr & camera)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 }
ScreenToWorld(BASE_NS::Math::Vec3 screenCoordinate) const310 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
WorldToScreen(BASE_NS::Math::Vec3 worldCoordinate) const343 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
RayCastFromCamera(const BASE_NS::Math::Vec2 & screenPos) const376 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
RayCastFromCamera(const BASE_NS::Math::Vec2 & screenPos,uint64_t layerMask) const419 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
RayFromCamera(const BASE_NS::Math::Vec2 & screenPos) const462 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
SetDefaultRenderTargetSize(uint64_t width,uint64_t height)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
SCENE_BEGIN_NAMESPACE()512 SCENE_BEGIN_NAMESPACE()
513
514 void RegisterCameraImpl()
515 {
516 auto& registry = META_NS::GetObjectRegistry();
517 registry.RegisterObjectType<CameraImpl>();
518 }
519
UnregisterCameraImpl()520 void UnregisterCameraImpl()
521 {
522 auto& registry = META_NS::GetObjectRegistry();
523 registry.UnregisterObjectType<CameraImpl>();
524 }
525
526 SCENE_END_NAMESPACE()
527