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
25 #include "core/camera.h"
26 #include "core/intf_internal_raycast.h"
27 #include "entity_converting_value.h"
28 #include "postprocess/postprocess.h"
29
30 META_TYPE(CORE3D_NS::CameraComponent::TargetUsage)
31
32 SCENE_BEGIN_NAMESPACE()
33
34 namespace {
35 struct FormatConverter {
36 using SourceType = ColorFormat;
37 using TargetType = CORE3D_NS::CameraComponent::TargetUsage;
38
ConvertToSource__anon5a911c580111::FormatConverter39 static SourceType ConvertToSource(META_NS::IAny&, const TargetType& v)
40 {
41 return ColorFormat { v.format, v.usageFlags };
42 }
ConvertToTarget__anon5a911c580111::FormatConverter43 static TargetType ConvertToTarget(const SourceType& v)
44 {
45 return CORE3D_NS::CameraComponent::TargetUsage { v.format, v.usageFlags };
46 }
47 };
48 } // namespace
49
Build(const META_NS::IMetadata::Ptr & d)50 bool CameraComponent::Build(const META_NS::IMetadata::Ptr& d)
51 {
52 return Super::Build(d);
53 }
InitDynamicProperty(const META_NS::IProperty::Ptr & p,BASE_NS::string_view path)54 bool CameraComponent::InitDynamicProperty(const META_NS::IProperty::Ptr& p, BASE_NS::string_view path)
55 {
56 if (p->GetName() == "PostProcess") {
57 auto ep = object_->CreateProperty(path).GetResult();
58 auto i = interface_cast<META_NS::IStackProperty>(p);
59 return ep && i &&
60 i->PushValue(META_NS::IValue::Ptr(
61 new InterfacePtrEntityValue<IPostProcess>(ep, { object_->GetScene(), ClassId::PostProcess })));
62 }
63 if (p->GetName() == "ColorTargetCustomization") {
64 auto ep = object_->CreateProperty(path).GetResult();
65 auto i = interface_cast<META_NS::IStackProperty>(p);
66 return ep && i && i->PushValue(META_NS::IValue::Ptr(new ConvertingArrayValue<FormatConverter>(ep)));
67 }
68 return false;
69 }
GetName() const70 BASE_NS::string CameraComponent::GetName() const
71 {
72 return "CameraComponent";
73 }
SetActive(bool active)74 Future<bool> CameraComponent::SetActive(bool active)
75 {
76 auto flags = SceneFlags()->GetValue();
77 if (active) {
78 flags |= uint32_t(CameraSceneFlag::ACTIVE_RENDER_BIT);
79 } else {
80 flags &= ~uint32_t(CameraSceneFlag::ACTIVE_RENDER_BIT | CameraSceneFlag::MAIN_CAMERA_BIT);
81 }
82 SceneFlags()->SetValue(flags);
83 return SyncProperty(object_->GetScene(), SceneFlags());
84 }
SetRenderTarget(const IRenderTarget::Ptr & target)85 Future<bool> CameraComponent::SetRenderTarget(const IRenderTarget::Ptr& target)
86 {
87 auto scene = object_->GetScene();
88 return scene->AddTask([=] {
89 bool res = UpdateCameraRenderTarget(object_, target);
90 if (res) {
91 if (target) {
92 if (interface_cast<META_NS::IDynamicResource>(target)) {
93 scene->AddRenderingCamera(GetSelf<IInternalCamera>());
94 }
95 } else {
96 scene->RemoveRenderingCamera(GetSelf<IInternalCamera>());
97 }
98 renderTarget_ = target;
99 }
100 return res;
101 });
102 }
IsActive() const103 bool CameraComponent::IsActive() const
104 {
105 return uint32_t(SceneFlags()->GetValue()) & uint32_t(CameraSceneFlag::ACTIVE_RENDER_BIT);
106 }
NotifyRenderTargetChanged()107 void CameraComponent::NotifyRenderTargetChanged()
108 {
109 if (renderTarget_ && IsActive()) {
110 auto scene = object_->GetScene();
111 if (auto dr = interface_pointer_cast<META_NS::IDynamicResource>(renderTarget_)) {
112 // anyone listening?
113 if (dr->EventOnResourceChanged(META_NS::MetadataQuery::EXISTING)) {
114 scene->AddTask([dr] { META_NS::Invoke<META_NS::IOnChanged>(dr->OnResourceChanged()); },
115 scene->GetContext()->GetApplicationQueue());
116 }
117 }
118 }
119 }
120
Attaching(const IAttach::Ptr & target,const IObject::Ptr & dataContext)121 bool CameraComponent::Attaching(const IAttach::Ptr& target, const IObject::Ptr& dataContext)
122 {
123 if (target) {
124 META_NS::IContainer::FindOptions options;
125 options.behavior = META_NS::TraversalType::NO_HIERARCHY;
126 options.uids = { IInputReceiver::UID };
127 options.strict = false;
128 inputReceivers_.SetTarget(target->GetAttachmentContainer(), options);
129 }
130 return true;
131 }
132
Detaching(const IAttach::Ptr & target)133 bool CameraComponent::Detaching(const IAttach::Ptr& target)
134 {
135 inputReceivers_.Reset();
136 return true;
137 }
138
SendInputEvent(PointerEvent & event)139 void CameraComponent::SendInputEvent(PointerEvent& event)
140 {
141 if (inputReceivers_.HasTarget() && !event.handled) {
142 for (auto&& receiver : inputReceivers_.FindAll()) {
143 receiver->OnInput(event);
144 if (event.handled) {
145 // Stop iteration if event.handled = true
146 return;
147 }
148 }
149 }
150 }
151
CastRay(const BASE_NS::Math::Vec2 & pos,const RayCastOptions & options) const152 Future<NodeHits> CameraComponent::CastRay(const BASE_NS::Math::Vec2& pos, const RayCastOptions& options) const
153 {
154 auto scene = object_->GetScene();
155 return scene->AddTask([=] {
156 RayCastOptions ops = options;
157 if (ops.layerMask == NONE_LAYER_MASK) {
158 ops.layerMask = LayerMask()->GetValue();
159 }
160 NodeHits result;
161 if (auto ir = interface_cast<IInternalRayCast>(scene)) {
162 result = ir->CastRay(object_, pos, ops);
163 }
164 return result;
165 });
166 }
ScreenPositionToWorld(const BASE_NS::Math::Vec3 & pos) const167 Future<BASE_NS::Math::Vec3> CameraComponent::ScreenPositionToWorld(const BASE_NS::Math::Vec3& pos) const
168 {
169 auto scene = object_->GetScene();
170 return scene->AddTask([=] {
171 BASE_NS::Math::Vec3 result;
172 if (auto ir = interface_cast<IInternalRayCast>(scene)) {
173 result = ir->ScreenPositionToWorld(object_, pos);
174 }
175 return result;
176 });
177 }
WorldPositionToScreen(const BASE_NS::Math::Vec3 & pos) const178 Future<BASE_NS::Math::Vec3> CameraComponent::WorldPositionToScreen(const BASE_NS::Math::Vec3& pos) const
179 {
180 auto scene = object_->GetScene();
181 return scene->AddTask([=] {
182 BASE_NS::Math::Vec3 result;
183 if (auto ir = interface_cast<IInternalRayCast>(scene)) {
184 result = ir->WorldPositionToScreen(object_, pos);
185 }
186 return result;
187 });
188 }
189
190 SCENE_END_NAMESPACE()
191