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 "scene.h"
17
18 #include <scene/ext/util.h>
19
20 #include <render/intf_render_context.h>
21
22 #include "component_factory.h"
23 #include "core/internal_scene.h"
24 #include "render_configuration.h"
25
SCENE_BEGIN_NAMESPACE()26 SCENE_BEGIN_NAMESPACE()
27
28 SceneObject::~SceneObject()
29 {
30 if (internal_) {
31 if (updateTask_) {
32 internal_->GetContext()->GetRenderQueue()->CancelTask(updateTask_);
33 }
34 // we attach asset loader to the scene, so destroy the attachments in engine thread
35 BASE_NS::vector<META_NS::IObject::Ptr> attachments = GetAttachments({}, false);
36 for (auto&& v : attachments) {
37 Detach(v);
38 }
39 internal_
40 ->AddTask([&, atts = BASE_NS::move(attachments)]() mutable {
41 atts.clear();
42 internal_->Uninitialize();
43 internal_.reset();
44 })
45 .Wait();
46 }
47 }
48
Build(const META_NS::IMetadata::Ptr & d)49 bool SceneObject::Build(const META_NS::IMetadata::Ptr& d)
50 {
51 bool res = Super::Build(d);
52 if (res) {
53 auto context = GetInterfaceBuildArg<IRenderContext>(d, "RenderContext");
54 if (!context) {
55 CORE_LOG_E("Invalid parameters to construct Scene");
56 return false;
57 }
58 auto opts = GetBuildArg<SceneOptions>(d, "Options");
59 auto in = CreateShared<InternalScene>(GetSelf<IScene>(), BASE_NS::move(context), BASE_NS::move(opts));
60
61 internal_ = in;
62 in->SetSelf(internal_);
63 AddBuiltinComponentFactories(internal_);
64 res = internal_->Initialize();
65 }
66 return res;
67 }
68
InitDynamicProperty(const META_NS::IProperty::Ptr & p,BASE_NS::string_view path)69 bool SceneObject::InitDynamicProperty(const META_NS::IProperty::Ptr& p, BASE_NS::string_view path)
70 {
71 if (p->GetName() == "RenderConfiguration") {
72 auto obj = CreateObject<IRenderConfiguration>(ClassId::RenderConfiguration).GetResult();
73 if (META_NS::Property<IRenderConfiguration::Ptr> t { p }) {
74 return t->SetValue(obj);
75 }
76 }
77 return false;
78 }
79
AttachEngineProperty(const META_NS::IProperty::Ptr & p,BASE_NS::string_view path)80 bool SceneObject::AttachEngineProperty(const META_NS::IProperty::Ptr& p, BASE_NS::string_view path)
81 {
82 return false;
83 }
84
StartAutoUpdate(META_NS::TimeSpan interval)85 void SceneObject::StartAutoUpdate(META_NS::TimeSpan interval)
86 {
87 if (updateTask_) {
88 internal_->GetContext()->GetRenderQueue()->CancelTask(updateTask_);
89 }
90 updateTask_ =
91 internal_->GetContext()->GetRenderQueue()->AddTask(META_NS::MakeCallback<META_NS::ITaskQueueTask>([&] {
92 internal_->Update();
93 return true;
94 }),
95 interval);
96 }
97
GetRootNode() const98 Future<INode::Ptr> SceneObject::GetRootNode() const
99 {
100 return internal_->AddTask([=] { return internal_->FindNode("", {}); });
101 }
102
CreateNode(const BASE_NS::string_view uri,META_NS::ObjectId id)103 Future<INode::Ptr> SceneObject::CreateNode(const BASE_NS::string_view uri, META_NS::ObjectId id)
104 {
105 return internal_->AddTask([=, path = BASE_NS::string(uri)] { return internal_->CreateNode(path, id); });
106 }
107
FindNode(BASE_NS::string_view uri,META_NS::ObjectId id) const108 Future<INode::Ptr> SceneObject::FindNode(BASE_NS::string_view uri, META_NS::ObjectId id) const
109 {
110 return internal_->AddTask([=, path = BASE_NS::string(uri)] { return internal_->FindNode(path, id); });
111 }
112
CreateObject(META_NS::ObjectId id)113 Future<META_NS::IObject::Ptr> SceneObject::CreateObject(META_NS::ObjectId id)
114 {
115 return internal_->AddTask([=] { return internal_->CreateObject(id); });
116 }
117
ReleaseNode(INode::Ptr && node,bool recursive)118 Future<bool> SceneObject::ReleaseNode(INode::Ptr&& node, bool recursive)
119 {
120 return internal_->AddTask(
121 [=, n = BASE_NS::move(node)]() mutable { return internal_->ReleaseNode(BASE_NS::move(n), recursive); });
122 }
123
RemoveNode(const INode::Ptr & node)124 Future<bool> SceneObject::RemoveNode(const INode::Ptr& node)
125 {
126 return internal_->AddTask([=] { return internal_->RemoveNode(node); });
127 }
128
GetCameras() const129 Future<BASE_NS::vector<ICamera::Ptr>> SceneObject::GetCameras() const
130 {
131 return internal_->AddTask([=] { return internal_->GetCameras(); });
132 }
133
GetAnimations() const134 Future<BASE_NS::vector<META_NS::IAnimation::Ptr>> SceneObject::GetAnimations() const
135 {
136 return internal_->AddTask([=] { return internal_->GetAnimations(); });
137 }
138
GetInternalScene() const139 IInternalScene::Ptr SceneObject::GetInternalScene() const
140 {
141 return internal_;
142 }
143
SetRenderMode(RenderMode mode)144 Future<bool> SceneObject::SetRenderMode(RenderMode mode)
145 {
146 return internal_->AddTask([=] { return internal_->SetRenderMode(mode); });
147 }
GetRenderMode() const148 Future<RenderMode> SceneObject::GetRenderMode() const
149 {
150 return internal_->AddTask([=] { return internal_->GetRenderMode(); });
151 }
GetComponent(const INode::Ptr & node,BASE_NS::string_view componentName) const152 IComponent::Ptr SceneObject::GetComponent(const INode::Ptr& node, BASE_NS::string_view componentName) const
153 {
154 if (const auto attach = interface_cast<META_NS::IAttach>(node)) {
155 if (auto container = attach->GetAttachmentContainer(false)) {
156 if (auto component = container->FindAny<IComponent>(componentName, META_NS::TraversalType::NO_HIERARCHY)) {
157 return component;
158 }
159 }
160 }
161 return {};
162 }
CreateComponent(const INode::Ptr & node,BASE_NS::string_view componentName)163 Future<IComponent::Ptr> SceneObject::CreateComponent(const INode::Ptr& node, BASE_NS::string_view componentName)
164 {
165 return internal_->AddTask(
166 [=, name = BASE_NS::string(componentName)] { return internal_->CreateEcsComponent(node, name); });
167 }
CastRay(const BASE_NS::Math::Vec3 & pos,const BASE_NS::Math::Vec3 & dir,const RayCastOptions & options) const168 Future<NodeHits> SceneObject::CastRay(
169 const BASE_NS::Math::Vec3& pos, const BASE_NS::Math::Vec3& dir, const RayCastOptions& options) const
170 {
171 return internal_->AddTask([=] {
172 RayCastOptions ops;
173 if (ops.layerMask == NONE_LAYER_MASK) {
174 ops.layerMask = ALL_LAYER_MASK;
175 }
176 NodeHits result;
177 if (auto ir = interface_cast<IInternalRayCast>(internal_)) {
178 result = ir->CastRay(pos, dir, ops);
179 }
180 return result;
181 });
182 }
183
184 SCENE_END_NAMESPACE()
185