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
16 #include "camera_component.h"
17
18 #include <scene/ext/util.h>
19
20 #include <3d/ecs/components/camera_component.h>
21
22 #include <meta/interface/intf_event.h>
23 #include <meta/interface/resource/intf_dynamic_resource.h>
24 #include "../core/camera.h"
25 #include "../core/intf_internal_raycast.h"
26 #include "../entity_converting_value.h"
27 #include "../postprocess/postprocess.h"
28
29 META_TYPE(CORE3D_NS::CameraComponent::TargetUsage)
30
31 SCENE_BEGIN_NAMESPACE()
32
33 namespace {
34 struct FormatConverter {
35 using SourceType = ColorFormat;
36 using TargetType = CORE3D_NS::CameraComponent::TargetUsage;
37
ConvertToSource__anon09d2bbb60111::FormatConverter38 static SourceType ConvertToSource(META_NS::IAny&, const TargetType& v)
39 {
40 return ColorFormat { v.format, v.usageFlags };
41 }
ConvertToTarget__anon09d2bbb60111::FormatConverter42 static TargetType ConvertToTarget(const SourceType& v)
43 {
44 return CORE3D_NS::CameraComponent::TargetUsage { v.format, v.usageFlags };
45 }
46 };
47 } // namespace
48
Build(const META_NS::IMetadata::Ptr & d)49 bool CameraComponent::Build(const META_NS::IMetadata::Ptr& d)
50 {
51 return Super::Build(d);
52 }
InitDynamicProperty(const META_NS::IProperty::Ptr & p,BASE_NS::string_view path)53 bool CameraComponent::InitDynamicProperty(const META_NS::IProperty::Ptr& p, BASE_NS::string_view path)
54 {
55 if (p->GetName() == "PostProcess") {
56 auto ep = object_->CreateEngineProperty(path).GetResult();
57 auto i = interface_cast<META_NS::IStackProperty>(p);
58 return ep && i &&
59 i->PushValue(META_NS::IValue::Ptr(
60 new InterfacePtrEntityValue<IPostProcess>(ep, { object_->GetScene(), ClassId::PostProcess })));
61 }
62 if (p->GetName() == "ColorTargetCustomization") {
63 auto ep = object_->CreateEngineProperty(path).GetResult();
64 auto i = interface_cast<META_NS::IStackProperty>(p);
65 return ep && i && i->PushValue(META_NS::IValue::Ptr(new ConvertingArrayValue<FormatConverter>(ep)));
66 }
67 return false;
68 }
GetName() const69 BASE_NS::string CameraComponent::GetName() const
70 {
71 return "CameraComponent";
72 }
SetActive(bool active)73 Future<bool> CameraComponent::SetActive(bool active)
74 {
75 auto flags = SceneFlags()->GetValue();
76 if (active) {
77 flags |= static_cast<uint32_t>(CameraSceneFlag::ACTIVE_RENDER_BIT);
78 } else {
79 flags &= ~static_cast<uint32_t>(CameraSceneFlag::ACTIVE_RENDER_BIT | CameraSceneFlag::MAIN_CAMERA_BIT);
80 }
81 SceneFlags()->SetValue(flags);
82 return SyncProperty(object_->GetScene(), SceneFlags());
83 }
SetRenderTarget(const IRenderTarget::Ptr & target)84 Future<bool> CameraComponent::SetRenderTarget(const IRenderTarget::Ptr& target)
85 {
86 auto scene = object_->GetScene();
87 return scene->AddTask([=] {
88 bool res = UpdateCameraRenderTarget(object_, target);
89 if (res) {
90 if (target) {
91 if (interface_cast<META_NS::IDynamicResource>(target)) {
92 scene->AddRenderingCamera(GetSelf<IInternalCamera>());
93 }
94 } else {
95 scene->RemoveRenderingCamera(GetSelf<IInternalCamera>());
96 }
97 renderTarget_ = target;
98 }
99 return res;
100 });
101 }
IsActive() const102 bool CameraComponent::IsActive() const
103 {
104 return SceneFlags()->GetValue() & static_cast<uint32_t>(CameraSceneFlag::ACTIVE_RENDER_BIT);
105 }
NotifyRenderTargetChanged()106 void CameraComponent::NotifyRenderTargetChanged()
107 {
108 if (renderTarget_ && IsActive()) {
109 auto scene = object_->GetScene();
110 if (auto dr = interface_pointer_cast<META_NS::IDynamicResource>(renderTarget_)) {
111 if (dr->EventOnResourceChanged(META_NS::MetadataQuery::EXISTING)) {
112 scene->AddTask(
113 [dr] { META_NS::Invoke<META_NS::IOnChanged>(dr->OnResourceChanged()); }, scene->GetAppTaskQueue());
114 }
115 }
116 }
117 }
118
CastRay(const BASE_NS::Math::Vec2 & pos,const RayCastOptions & options) const119 Future<NodeHits> CameraComponent::CastRay(const BASE_NS::Math::Vec2& pos, const RayCastOptions& options) const
120 {
121 auto scene = object_->GetScene();
122 return scene->AddTask([=] {
123 RayCastOptions ops = options;
124 if (ops.layerMask == NONE_LAYER_MASK) {
125 ops.layerMask = LayerMask()->GetValue();
126 }
127 NodeHits result;
128 if (auto ir = interface_cast<IInternalRayCast>(scene)) {
129 result = ir->CastRay(object_, pos, ops);
130 }
131 return result;
132 });
133 }
ScreenPositionToWorld(const BASE_NS::Math::Vec3 & pos) const134 Future<BASE_NS::Math::Vec3> CameraComponent::ScreenPositionToWorld(const BASE_NS::Math::Vec3& pos) const
135 {
136 auto scene = object_->GetScene();
137 return scene->AddTask([=] {
138 BASE_NS::Math::Vec3 result;
139 if (auto ir = interface_cast<IInternalRayCast>(scene)) {
140 result = ir->ScreenPositionToWorld(object_, pos);
141 }
142 return result;
143 });
144 }
WorldPositionToScreen(const BASE_NS::Math::Vec3 & pos) const145 Future<BASE_NS::Math::Vec3> CameraComponent::WorldPositionToScreen(const BASE_NS::Math::Vec3& pos) const
146 {
147 auto scene = object_->GetScene();
148 return scene->AddTask([=] {
149 BASE_NS::Math::Vec3 result;
150 if (auto ir = interface_cast<IInternalRayCast>(scene)) {
151 result = ir->WorldPositionToScreen(object_, pos);
152 }
153 return result;
154 });
155 }
156 SCENE_END_NAMESPACE()