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_exporter.h"
16
17 #include <scene/ext/intf_component.h>
18 #include <scene/ext/intf_internal_scene.h>
19 #include <scene/interface/intf_external_node.h>
20 #include <scene/interface/intf_mesh.h>
21
22 #include <meta/api/metadata_util.h>
23 #include <meta/interface/property/construct_array_property.h>
24 #include <meta/interface/resource/intf_resource.h>
25 #include <meta/interface/serialization/intf_exporter.h>
26
27 #include "scene_ser.h"
28 #include "util.h"
29
30 SCENE_BEGIN_NAMESPACE()
31
32 static void AddObjectProperties(const META_NS::IObject& node, const BASE_NS::string& head, META_NS::IMetadata& out);
33
HandleReadOnlyProperty(const META_NS::IProperty::ConstPtr & p,const BASE_NS::string & head,META_NS::IMetadata & out)34 static void HandleReadOnlyProperty(
35 const META_NS::IProperty::ConstPtr& p, const BASE_NS::string& head, META_NS::IMetadata& out)
36 {
37 if (META_NS::ArrayPropertyLock arr { p }) {
38 for (size_t i = 0; i != arr->GetSize(); ++i) {
39 if (auto obj = interface_cast<META_NS::IObject>(META_NS::GetConstPointer(arr->GetAnyAt(i)))) {
40 AddObjectProperties(
41 *obj, head + "." + EscapeSerName(p->GetName()) + "[" + BASE_NS::to_string(i) + "]", out);
42 }
43 }
44 } else {
45 if (auto obj = META_NS::GetConstPointer<META_NS::IObject>(p)) {
46 AddObjectProperties(*obj, head + "." + EscapeSerName(p->GetName()), out);
47 }
48 }
49 }
50
AddObjectProperties(const META_NS::IObject & obj,const BASE_NS::string & head,META_NS::IMetadata & out)51 static void AddObjectProperties(const META_NS::IObject& obj, const BASE_NS::string& head, META_NS::IMetadata& out)
52 {
53 if (auto i = interface_cast<META_NS::IMetadata>(&obj)) {
54 for (auto&& p : GetAllProperties(*i)) {
55 if (i->GetMetadata(META_NS::MetadataType::PROPERTY, p->GetName()).readOnly) {
56 HandleReadOnlyProperty(p, head, out);
57 } else {
58 META_NS::CloneToDefaultIfSet(p, out, head + "." + EscapeSerName(p->GetName()));
59 }
60 }
61 }
62 }
63
AddObjectProperties(const META_NS::IObject & obj,META_NS::IMetadata & out)64 void AddObjectProperties(const META_NS::IObject& obj, META_NS::IMetadata& out)
65 {
66 AddObjectProperties(obj, "", out);
67 }
68
AddObjectAttachments(const META_NS::IObject & node,ISceneNodeSer & out)69 static void AddObjectAttachments(const META_NS::IObject& node, ISceneNodeSer& out)
70 {
71 if (auto i = interface_cast<META_NS::IAttach>(&node)) {
72 BASE_NS::vector<META_NS::IObject::Ptr> vec;
73 for (auto&& att : i->GetAttachments()) {
74 if (!interface_cast<META_NS::IEvent>(att) && !interface_cast<META_NS::IFunction>(att) &&
75 !interface_cast<META_NS::IProperty>(att) && !interface_cast<IComponent>(att) &&
76 !interface_cast<IExternalNode>(att)) {
77 vec.push_back(att);
78 }
79 }
80 out.SetAttachments(BASE_NS::move(vec));
81 }
82 }
83
AddExternalAttachments(const META_NS::IObject & node,const BASE_NS::string & path,ISceneExternalNodeSer & out)84 static void AddExternalAttachments(
85 const META_NS::IObject& node, const BASE_NS::string& path, ISceneExternalNodeSer& out)
86 {
87 if (auto i = interface_cast<META_NS::IAttach>(&node)) {
88 BASE_NS::vector<META_NS::IObject::Ptr> vec;
89 for (auto&& att : i->GetAttachments()) {
90 if (!interface_cast<META_NS::IEvent>(att) && !interface_cast<META_NS::IFunction>(att) &&
91 !interface_cast<META_NS::IProperty>(att) && !interface_cast<IComponent>(att) &&
92 !interface_cast<IExternalNode>(att)) {
93 out.AddAttachment(path, att);
94 }
95 }
96 }
97 }
98
AddObjectData(const META_NS::IObject & node,const BASE_NS::string & head,META_NS::IMetadata & out)99 static void AddObjectData(const META_NS::IObject& node, const BASE_NS::string& head, META_NS::IMetadata& out)
100 {
101 if (auto ext = interface_cast<ISceneExternalNodeSer>(&out)) {
102 AddExternalAttachments(node, head, *ext);
103 }
104 AddObjectProperties(node, head, out);
105 }
106
AddObjectDataRecursive(const META_NS::IObject & obj,const BASE_NS::string & head,META_NS::IMetadata & out)107 static void AddObjectDataRecursive(const META_NS::IObject& obj, const BASE_NS::string& head, META_NS::IMetadata& out)
108 {
109 AddObjectData(obj, head, out);
110
111 META_NS::Internal::ConstIterate(
112 interface_cast<META_NS::IIterable>(&obj),
113 [&](META_NS::IObject::Ptr nodeObj) {
114 AddObjectDataRecursive(*nodeObj, head + "/" + EscapeSerName(nodeObj->GetName()), out);
115 return true;
116 },
117 META_NS::IterateStrategy { META_NS::TraversalType::NO_HIERARCHY });
118 }
119
AddObjectDataRecursive(const META_NS::IObject & obj,META_NS::IMetadata & out)120 static void AddObjectDataRecursive(const META_NS::IObject& obj, META_NS::IMetadata& out)
121 {
122 AddObjectDataRecursive(obj, "", out);
123 }
124
SetObjectData(const META_NS::IObject & node,ISceneNodeSer & out)125 static void SetObjectData(const META_NS::IObject& node, ISceneNodeSer& out)
126 {
127 if (auto outMeta = interface_cast<META_NS::IMetadata>(&out)) {
128 out.SetName(node.GetName());
129 out.SetId(node.GetClassId());
130 AddObjectAttachments(node, out);
131 AddObjectData(node, "", *outMeta);
132 }
133 }
134
BuildExternalNode(const META_NS::IObject & node,const IExternalNode & ext)135 static META_NS::IObject::Ptr BuildExternalNode(const META_NS::IObject& node, const IExternalNode& ext)
136 {
137 auto obj = META_NS::GetObjectRegistry().Create<ISceneExternalNodeSer>(ClassId::SceneExternalNodeSer);
138 if (obj) {
139 obj->SetName(node.GetName());
140 obj->SetResourceId(ext.GetResourceId());
141 if (auto mout = interface_cast<META_NS::IMetadata>(obj)) {
142 AddObjectDataRecursive(node, *mout);
143 }
144 }
145 return interface_pointer_cast<META_NS::IObject>(obj);
146 }
147
BuildObjectNode(const META_NS::IObject & node)148 static META_NS::IObject::Ptr BuildObjectNode(const META_NS::IObject& node)
149 {
150 auto cont = META_NS::GetObjectRegistry().Create<META_NS::IContainer>(ClassId::SceneNodeSer);
151 if (auto i = interface_cast<ISceneNodeSer>(cont)) {
152 SetObjectData(node, *i);
153 }
154 META_NS::Internal::ConstIterate(
155 interface_cast<META_NS::IIterable>(&node),
156 [&](META_NS::IObject::Ptr nodeObj) {
157 META_NS::IObject::Ptr obj;
158 if (auto att = interface_cast<META_NS::IAttach>(nodeObj)) {
159 auto ext = att->GetAttachments<IExternalNode>();
160 if (!ext.empty()) {
161 obj = BuildExternalNode(*nodeObj, *ext.front());
162 }
163 }
164 if (!obj) {
165 obj = BuildObjectNode(*nodeObj);
166 }
167 cont->Add(obj);
168 return true;
169 },
170 META_NS::IterateStrategy { META_NS::TraversalType::NO_HIERARCHY });
171
172 return interface_pointer_cast<META_NS::IObject>(cont);
173 }
174
BuildObjectHierarchy(const IScene & scene)175 static META_NS::IObject::Ptr BuildObjectHierarchy(const IScene& scene)
176 {
177 META_NS::IObject::Ptr res = META_NS::GetObjectRegistry().Create(ClassId::SceneNodeSer);
178 if (res) {
179 if (auto obj = interface_cast<META_NS::IObject>(&scene)) {
180 if (auto ser = interface_cast<ISceneNodeSer>(res)) {
181 SetObjectData(*obj, *ser);
182 if (auto i = interface_cast<META_NS::IContainer>(res)) {
183 if (auto root = interface_pointer_cast<META_NS::IObject>(scene.GetRootNode().GetResult())) {
184 i->Add(BuildObjectNode(*root));
185 }
186 }
187 }
188 }
189 }
190 return res;
191 }
192
CreateExporter(const IRenderContext::Ptr & r)193 static META_NS::IFileExporter::Ptr CreateExporter(const IRenderContext::Ptr& r)
194 {
195 META_NS::IFileExporter::Ptr exporter;
196 if (r) {
197 exporter = META_NS::GetObjectRegistry().Create<META_NS::IFileExporter>(META_NS::ClassId::JsonExporter);
198 exporter->SetResourceManager(r->GetResources());
199 exporter->SetMetadata(
200 META_NS::SerMetadataValues().SetVersion(SCENE_EXPORTER_VERSION).SetType(SCENE_EXPORTER_TYPE));
201 }
202 return exporter;
203 }
204
ExportScene(CORE_NS::IFile & out,const IScene::ConstPtr & p)205 META_NS::ReturnError SceneExporter::ExportScene(CORE_NS::IFile& out, const IScene::ConstPtr& p)
206 {
207 META_NS::ReturnError res = META_NS::GenericError::FAIL;
208 if (auto scene = interface_cast<IScene>(p)) {
209 if (auto obj = BuildObjectHierarchy(*scene)) {
210 auto exporter = CreateExporter(scene->GetInternalScene()->GetContext());
211 res = exporter->Export(out, obj);
212 }
213 }
214 return res;
215 }
ExportNode(CORE_NS::IFile & out,const INode::ConstPtr & p)216 META_NS::ReturnError SceneExporter::ExportNode(CORE_NS::IFile& out, const INode::ConstPtr& p)
217 {
218 META_NS::ReturnError res = META_NS::GenericError::FAIL;
219 if (auto obj = BuildObjectNode(*interface_cast<META_NS::IObject>(p))) {
220 auto exporter = CreateExporter(p->GetScene()->GetInternalScene()->GetContext());
221 res = exporter->Export(out, obj);
222 }
223 return res;
224 }
225
226 SCENE_END_NAMESPACE()
227