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/mesh_uid.h>
16 #include <scene_plugin/interface/intf_material.h>
17
18 #include <meta/ext/concrete_base_object.h>
19
20 #include "bind_templates.inl"
21 #include "intf_submesh_bridge.h"
22 #include "node_impl.h"
23 #include "submesh_handler_uid.h"
24 #include "task_utils.h"
25
26 using SCENE_NS::MakeTask;
27
28 namespace {
29 class SubMeshImpl : public META_NS::ObjectFwd<SubMeshImpl, SCENE_NS::ClassId::SubMesh, META_NS::ClassId::Object,
30 SCENE_NS::ISubMesh, SCENE_NS::ISubMeshPrivate> {
31 META_IMPLEMENT_INTERFACE_PROPERTY(META_NS::INamed, BASE_NS::string, Name, {})
32 META_IMPLEMENT_INTERFACE_PROPERTY(
33 SCENE_NS::ISubMesh, SCENE_NS::IMaterial::Ptr, Material, {})
34 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ISubMesh, uint64_t, Handle, {}, META_NS::ObjectFlagBits::INTERNAL)
35 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ISubMesh, BASE_NS::Math::Vec3, AABBMin,
36 BASE_NS::Math::Vec3(0.f, 0.f, 0.f), META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
37 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::ISubMesh, BASE_NS::Math::Vec3, AABBMax,
38 BASE_NS::Math::Vec3(0.f, 0.f, 0.f), META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
39 META_IMPLEMENT_INTERFACE_PROPERTY(
40 SCENE_NS::ISubMesh, uint8_t, RenderSortLayerOrder, 0u, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
41 META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(SCENE_NS::ISubMesh, BASE_NS::string, MaterialUri, "",
42 META_NS::DEFAULT_PROPERTY_FLAGS | META_NS::ObjectFlagBits::INTERNAL)
43
44 public:
Build(const META_NS::IMetadata::Ptr & data)45 bool Build(const META_NS::IMetadata::Ptr& data) override
46 {
47 // subscribe to material changes.
48 Material()->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>([this]() {
49 // Material has changed.
50 auto material = Material()->GetValue();
51
52 // If this change was not triggered by us, we will store the value.
53 if (!isSettingDefaults_) {
54 SaveCurrentMaterial(material);
55 }
56
57 // Override material always overrides everything.
58 // This could use validator as well, but MetaObject Validate() function was not invoked properly.
59 if (overrideMaterial_) {
60 material = overrideMaterial_;
61 } else if (!material) {
62 // No material / case reset.
63 material = defaultMaterial_;
64 }
65
66 UpdateMaterialToScene(material);
67 }));
68
69 return true;
70 }
71
SetRenderSortLayerOrder(uint8_t order)72 void SetRenderSortLayerOrder(uint8_t order) override
73 {
74 for (auto& ite : submeshHandlers_) {
75 if (auto bridge = ite.lock()) {
76 bridge->SetRenderSortLayerOrder(META_NS::GetValue(Handle()), order);
77 }
78 }
79 }
80
SetAABBMin(BASE_NS::Math::Vec3 vec)81 void SetAABBMin(BASE_NS::Math::Vec3 vec) override
82 {
83 for (auto& ite : submeshHandlers_) {
84 if (auto bridge = ite.lock()) {
85 bridge->SetAABBMin(META_NS::GetValue(Handle()), vec);
86 }
87 }
88 }
89
SetAABBMax(BASE_NS::Math::Vec3 vec)90 void SetAABBMax(BASE_NS::Math::Vec3 vec) override
91 {
92 for (auto& ite : submeshHandlers_) {
93 if (auto bridge = ite.lock()) {
94 bridge->SetAABBMax(META_NS::GetValue(Handle()), vec);
95 }
96 }
97 }
98
SetMaterial(SCENE_NS::IMaterial::Ptr material)99 void SetMaterial(SCENE_NS::IMaterial::Ptr material) override
100 {
101 Material()->SetValue(material);
102 }
103
UpdateMaterialToScene(SCENE_NS::IMaterial::Ptr material)104 void UpdateMaterialToScene(SCENE_NS::IMaterial::Ptr material)
105 {
106 // Activate material to scene.
107 for (auto& ite : submeshHandlers_) {
108 if (auto bridge = ite.lock()) {
109 bridge->SetMaterialToEcs(META_NS::GetValue(Handle()), material);
110 }
111 }
112 }
113
114 public: // ISubMeshPrivate
AddSubmeshBrigde(SCENE_NS::ISubMeshBridge::Ptr bridge)115 void AddSubmeshBrigde(SCENE_NS::ISubMeshBridge::Ptr bridge) override
116 {
117 for (auto& existingBridge : submeshHandlers_) {
118 if (bridge == existingBridge.lock()) {
119 return;
120 }
121 }
122
123 submeshHandlers_.push_back(bridge);
124
125 // Store initial material that we have assigned right now.
126 currentMaterial_ = GetValue(Material());
127 if (currentMaterial_) {
128 bridge->SetMaterialToEcs(META_NS::GetValue(Handle()), currentMaterial_);
129 }
130 }
131
RemoveSubmeshBrigde(SCENE_NS::ISubMeshBridge::Ptr bridge)132 virtual void RemoveSubmeshBrigde(SCENE_NS::ISubMeshBridge::Ptr bridge) override
133 {
134 for (auto ite = submeshHandlers_.cbegin(); ite != submeshHandlers_.cend();) {
135 auto strong = ite->lock();
136 if (!strong || bridge == strong) {
137 ite = submeshHandlers_.erase(ite);
138 } else {
139 ite++;
140 }
141 }
142 }
143
GetEntity() const144 CORE_NS::Entity GetEntity() const override
145 {
146 if (!submeshHandlers_.empty()) {
147 if (auto first = submeshHandlers_.begin()->lock()) {
148 return first->GetEntity();
149 }
150 }
151
152 return {};
153 }
154
RestoreDefaultMaterial()155 void RestoreDefaultMaterial() override
156 {
157 Material()->SetValue(defaultMaterial_);
158 }
159
SetDefaultMaterial(SCENE_NS::IMaterial::Ptr material)160 void SetDefaultMaterial(SCENE_NS::IMaterial::Ptr material) override
161 {
162 isSettingDefaults_ = true;
163
164 if (!defaultMaterialIsSet_) {
165 // Store default material.
166 defaultMaterial_ = material;
167 defaultMaterialIsSet_ = true;
168
169 // also make it default to this property, so that Reset() will work.
170 // Currently this causes material (and its changes) not to be serialized to .ui
171 // auto* directAccess =
172 // interface_cast<META_NS::IPropertyDirectAccess<SCENE_NS::IMaterial::Ptr>>(Material()); if (directAccess) {
173 //}
174
175 // Activate default material if there is no current material.
176 if (!META_NS::GetValue(Material())) {
177 Material()->SetValue(material);
178 }
179 }
180
181 isSettingDefaults_ = false;
182 }
183
SetOverrideMaterial(SCENE_NS::IMaterial::Ptr material)184 void SetOverrideMaterial(SCENE_NS::IMaterial::Ptr material) override
185 {
186 isSettingDefaults_ = true;
187
188 // Store override material.
189 overrideMaterial_ = material;
190
191 // If override material, make it active.
192 if (overrideMaterial_) {
193 UpdateMaterialToScene(overrideMaterial_);
194 } else {
195 // Otherwise restore the current material / default material.
196 UpdateMaterialToScene(currentMaterial_ ? currentMaterial_ : defaultMaterial_);
197 }
198 isSettingDefaults_ = false;
199 }
200
SaveCurrentMaterial(SCENE_NS::IMaterial::Ptr material)201 void SaveCurrentMaterial(SCENE_NS::IMaterial::Ptr material)
202 {
203 // This material also becomes the "current" value.
204 currentMaterial_ = material;
205
206 if (!currentMaterial_) {
207 Material()->SetValue(defaultMaterial_);
208 }
209 }
210
211 bool defaultMaterialIsSet_ { false };
212 SCENE_NS::IMaterial::Ptr defaultMaterial_;
213 SCENE_NS::IMaterial::Ptr currentMaterial_;
214 SCENE_NS::IMaterial::Ptr overrideMaterial_;
215
216 bool isSettingDefaults_ { false };
217 BASE_NS::vector<SCENE_NS::ISubMeshBridge::WeakPtr> submeshHandlers_;
218 };
219 } // namespace
SCENE_BEGIN_NAMESPACE()220 SCENE_BEGIN_NAMESPACE()
221
222 void RegisterSubMeshImpl()
223 {
224 META_NS::GetObjectRegistry().RegisterObjectType<SubMeshImpl>();
225 }
UnregisterSubMeshImpl()226 void UnregisterSubMeshImpl()
227 {
228 META_NS::GetObjectRegistry().UnregisterObjectType<SubMeshImpl>();
229 }
230 SCENE_END_NAMESPACE()
231