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 #ifndef SCENEPLUGIN_INTF_SCENE_H
16 #define SCENEPLUGIN_INTF_SCENE_H
17 
18 #include <scene_plugin/interface/intf_camera.h>
19 #include <scene_plugin/interface/intf_ecs_animation.h>
20 #include <scene_plugin/interface/intf_ecs_object.h>
21 #include <scene_plugin/interface/intf_material.h>
22 #include <scene_plugin/interface/intf_mesh.h>
23 #include <scene_plugin/interface/intf_node.h>
24 #include <scene_plugin/interface/intf_render_configuration.h>
25 #include <scene_plugin/interface/mesh_arrays.h>
26 
27 #include <core/ecs/intf_ecs.h>
28 
29 #include <meta/api/animation/animation.h>
30 #include <meta/base/types.h>
31 
32 SCENE_BEGIN_NAMESPACE()
33 
34 /**
35  * @brief Scene interface, implemented by SCENE_NS::ClassId::Scene
36  */
37 REGISTER_INTERFACE(IScene, "49df31df-eea6-4d61-a8f1-46aa1f516a18")
38 class IScene : public META_NS::INamed {
39     META_INTERFACE(META_NS::INamed, IScene, InterfaceId::IScene)
40 public:
41     /**
42      * @brief The SCENE_STATE enum
43      */
44     enum SCENE_STATE {
45         SCENE_STATUS_UNINITIALIZED = 0,
46         SCENE_STATUS_LOADING = 1,
47         SCENE_STATUS_READY = 2,
48         SCENE_STATUS_LOADING_FAILED = 3,
49     };
50 
51     /**
52      * @brief Status of the scene. Reflects to main scene file, not prefabs and such.
53      * @return Pointer to the property.
54      */
55     META_READONLY_PROPERTY(uint32_t, Status)
56 
57     /**
58      * @brief Root node of 3D scene. Populated asynchronously when scene loads.
59      * @return Pointer to the property.
60      */
61     META_READONLY_PROPERTY(INode::Ptr, RootNode)
62 
63     /**
64      * @brief Default camera of the scene. Populated asynchronously when scene loads.
65      * @return Pointer to the property.
66      */
67     META_PROPERTY(ICamera::Ptr, DefaultCamera)
68 
69     /**
70      * @brief Scene Uri, refers to the main scene file.
71      * @return Pointer to the property.
72      */
73     META_PROPERTY(BASE_NS::string, Uri)
74 
75     /**
76      * @brief Render configuration.
77      * @return
78      */
79     META_PROPERTY(IRenderConfiguration::Ptr, RenderConfiguration)
80 
81     /**
82      * @brief Operation mode. If set true, all communication towards scene takes place through task queues.
83      * In practice this means that when ever the new elements are introduced on the scene, yield of some sort
84      * needs to take place in order to scene set up the bindings. Multithreading requires this to be on.
85      * Changing the operation mode is possible only before the main scene is loaded, otherwise the behavior is undefined
86      * @return Pointer to the property.
87      */
88     META_PROPERTY(bool, Asynchronous)
89 
90     /**
91      * @brief Access to all user-created materials in the scene.
92      * @return Pointer to the property.
93      */
94     META_ARRAY_PROPERTY(IMaterial::Ptr, Materials)
95 
96     /**
97      * @brief Event which is invoked once the scene has been successfully loaded.
98      * @return Event that is used to add handlers for the scene loading.
99      */
100     META_EVENT(META_NS::IOnChanged, OnLoaded)
101 
102 
103     /**
104      * @brief Create an empty scene.
105      */
106     virtual void CreateEmpty() = 0;
107 
108     /**
109      * @brief Load the scene from a file. It is possible to extend the scene after it has been loaded.
110      * @param file The file defining the scene.
111      * @return Synchronous reply if the loading was started. Use OnLoaded event and Status property for better control.
112      */
113     virtual bool Load(const BASE_NS::string_view file) = 0;
114 
115     /**
116      * @brief Returns a node from the scene with a given path (e.g. something like "view/camera_1"). Uses flat cache,
117      * but creates a new node if the previous instance does not exist.
118      * @param path Path defining the node on 3d scene.
119      * @param classId Optional, if the creation type of the node instance is known, it should be provided. Otherwise the
120      * system tries to guess it.
121      * @return Returns always a node. If the respective 3d element does not exists yet, holds the values but does not
122      * post OnLoaded event.
123      */
124     virtual INode::Ptr GetNode(const BASE_NS::string_view path, BASE_NS::Uid classId = META_NS::IObject::UID,
125         INode::BuildBehavior buildBehavior = INode::BuildBehavior::NODE_BUILD_CHILDREN_GRADUAL) = 0;
126 
127     /**
128      * @brief Add material to scene, this makes scene to take ownership of the material.
129      * @param material Material instance
130      */
131     virtual void AddMaterial(IMaterial::Ptr) = 0;
132 
133     /**
134      * @brief Remove material from scene, after this scene no longer owns the material.
135      * @param material Material instance
136      */
137     virtual void RemoveMaterial(IMaterial::Ptr) = 0;
138 
139     /**
140      * @brief Returns all materials from the scene.
141      * @return Returns a vector of material objects.
142      */
143     virtual BASE_NS::vector<IMaterial::Ptr> GetMaterials() const = 0;
144 
145     /**
146      * @brief Returns a material from the scene with a given name. Materials are typically nodeless elements, and thus
147      * the path is flat. Uses flat cache, but creates a new material if the previous instance does not exist.
148      * @param name Name of the material entity.
149      * @return Returns always an instance. If the respective material does not exists yet, holds the set values but does
150      * not complete OnLoaded.
151      */
152     virtual IMaterial::Ptr GetMaterial(const BASE_NS::string_view name) = 0;
153 
154     /**
155      * @brief Loads a material from uri.
156      * @param uri Uri to the material file.
157      * @return Deserializes material from URI and returns the material instance if successful.
158      */
159     virtual IMaterial::Ptr LoadMaterial(const BASE_NS::string_view uri) = 0;
160 
161     /**
162      * @brief Returns all meshes from the scene.
163      * @return Returns a vector of mesh objects.
164      */
165     virtual BASE_NS::vector<IMesh::Ptr> GetMeshes() const = 0;
166 
167     /**
168      * @brief Returns a mesh from the scene with a given name. Meshes are typically nodeless elements, and thus
169      * the path is flat. Uses flat cache, but creates a new mesh if the previous instance does not exist.
170      * @param name Name of the mesh entity.
171      * @return Returns always an instance. If the respective mesh does not exists yet, holds the set values but does
172      * not complete OnLoaded.
173      */
174     virtual IMesh::Ptr GetMesh(const BASE_NS::string_view name) = 0;
175 
176     /**
177      * @brief Returns a new mesh constructed from the arrays. 16 bit indices.
178      * @param name of the mesh instance to be created. Should be unique.
179      * @param arrays defining the mesh, see MeshGeometryArray.
180      * @return Returns always an instance. if the creation fails, the engine side may not be accessible.
181      */
182     virtual IMesh::Ptr CreateMeshFromArraysI16(
183         const BASE_NS::string_view name, MeshGeometryArrayPtr<uint16_t> arrays) = 0;
184 
185     /**
186      * @brief Returns a new mesh constructed from the arrays. 32 bit indices.
187      * @param name of the mesh instance to be created. Should be unique.
188      * @param arrays defining the mesh, see MeshGeometryArray.
189      * @return Returns always an instance. if the creation fails, the engine side may not be accessible.
190      */
191     virtual IMesh::Ptr CreateMeshFromArraysI32(
192         const BASE_NS::string_view name, MeshGeometryArrayPtr<uint32_t> arrays) = 0;
193 
194     /**
195      * @brief Create an empty node.
196      * @param path Path to which add or find the engine component.
197      * @param createEngineObject The boolean defining whether the 3d element should exist or be created by us.
198      * @param classId The type of the node implementation, should be provided if known.
199      * @return Newly created instance.
200      */
201     virtual INode::Ptr CreateNode(const BASE_NS::string_view path, bool createEngineObject = true,
202         META_NS::ObjectId classId = META_NS::IObject::UID,
203         INode::BuildBehavior buildBehavior = INode::BuildBehavior::NODE_BUILD_CHILDREN_GRADUAL) = 0;
204 
205     /**
206      * @brief Release INode reference from flat cache. It is possible that someone else will hold a reference and the
207      * resource is not freed.
208      * @param name or path of the node.
209      * @return The strong pointer to the resource that was removed from cache.
210      */
211     virtual INode::Ptr ReleaseNode(const BASE_NS::string_view name) = 0;
212 
213     /**
214      * @brief Release INode reference from flat cache. caller will still own the reference.
215      * @param node to be released.
216      */
217     virtual void ReleaseNode(const INode::Ptr& node) = 0;
218 
219     /**
220      * @brief Release IMaterial reference from flat cache. It is possible that someone else will hold a reference and
221      * the resource is not freed.
222      * @param name or path of the material.
223      * @return The strong pointer to the resource that was removed from cache.
224      */
225     virtual IMaterial::Ptr ReleaseMaterial(const BASE_NS::string_view name) = 0;
226 
227     /**
228      * @brief Release IMesh reference from flat cache. It is possible that someone else will hold a reference and
229      * the resource is not freed.
230      * @param name or path of the mesh.
231      * @return The strong pointer to the resource that was removed from cache.
232      */
233     virtual IMesh::Ptr ReleaseMesh(const BASE_NS::string_view name) = 0;
234 
235     /**
236      * @brief Release IAnimation reference from flat cache. It is possible that someone else will hold a reference and
237      * the resource is not freed.
238      * @param name or path of the animation.
239      * @return The strong pointer to the resource that was removed from cache.
240      */
241     virtual META_NS::IAnimation::Ptr ReleaseAnimation(const BASE_NS::string_view name) = 0;
242 
243     /**
244      * @brief Returns all animations from the scene.
245      * @return Returns a vector of animation objects.
246      */
247     virtual BASE_NS::vector<META_NS::IAnimation::Ptr> GetAnimations() = 0;
248 
249     /**
250      * @brief Returns the ecs animation from the scene with the given path.
251      * @param name The name of the animation.
252      * @return The strong pointer to an animation.
253      */
254     virtual META_NS::IAnimation::Ptr GetAnimation(const BASE_NS::string_view name) = 0;
255 
256     /**
257      * @brief Controls the 3d scene System Graph Uri. Changing the value resets the loaded scene completely.
258      * @return Pointer to the property.
259      */
META_PROPERTY(BASE_NS::string,SystemGraphUri)260     META_PROPERTY(BASE_NS::string, SystemGraphUri)
261 
262     static constexpr BASE_NS::string_view MATERIALS_PREFIX { "materials" };
263     static constexpr BASE_NS::string_view MESHES_PREFIX { "meshes" };
264     static constexpr BASE_NS::string_view ANIMATIONS_PREFIX { "animations" };
265 
266     /**
267      * @brief Update INode cache reference when node is moved to another parent or renamed.
268      * @param node that has changed.
269      */
270     virtual void UpdateCachedReference(const INode::Ptr& node) = 0;
271 
272     virtual void UpdateCachedNodePath(const SCENE_NS::INode::Ptr& node) = 0;
273     virtual void SetCacheEnabled(const SCENE_NS::INode::Ptr& node, bool enabled) = 0;
274 
275     /**
276      * @brief Helper for returning a node with a given type.
277      * @param path The path of the 3D element.
278      * @return Returns always an instance. Use INode::Status and INode::OnLoaded to check the status of the node before
279      * reading the 3d values.
280      */
281     template<class T>
GetNode(const BASE_NS::string_view path)282     typename T::Ptr GetNode(const BASE_NS::string_view path)
283     {
284         const auto uid = T::UID;
285         return interface_pointer_cast<T>(GetNode(path, uid));
286     }
287 
288     /**
289      * @brief Create an empty node.
290      * @param path Path to which add or find the engine component.
291      * @param createEngineObject The boolean defining whether the 3d element should exist or be created by us.
292      * @return Newly created instance.
293      */
294     template<class T>
295     typename T::Ptr CreateNode(const BASE_NS::string_view path, bool createEngineObject = true)
296     {
297         const auto uid = T::UID;
298         return interface_pointer_cast<T>(CreateNode(path, createEngineObject, uid));
299     }
300 
301     /**
302      * @brief Create an empty material instance.
303      * @param name Name of the new material.
304      * @return Newly created instance.
305      */
CreateMaterial(const BASE_NS::string_view name)306     IMaterial::Ptr CreateMaterial(const BASE_NS::string_view name)
307     {
308         return CreateNode<IMaterial>(name);
309     }
310 
311     // Internals, to be forked to some other interface
312 
313     /** This can be used to access the scene default camera without known handle*/
314     static constexpr uint64_t DEFAULT_CAMERA { 0 };
315 
316     /**
317      * @brief Get the latest bitmap from the engine. If the bitmap for the camera handle does not exist, it will be
318      * created.
319      * @param notifyFrameDrawn Tell engine that a frame was consumed.
320      * @param cameraHandle Specify if we are interested on some specific camera.
321      * @return Pointer to bitmap
322      */
323     virtual SCENE_NS::IBitmap::Ptr GetBitmap(bool notifyFrameDrawn, const ICamera::Ptr& camera) = 0;
324 
325     /**
326      * @brief Set bitmap for the engine updates.
327      * @param bitmap
328      * @param cameraHandle Specify if we are interested on some specific camera.
329      */
330     virtual void SetBitmap(const SCENE_NS::IBitmap::Ptr& bitmap, const ICamera::Ptr& camera) = 0;
331 
332     /**
333      * @brief Set Render Size for target bitmap in pixels. Subject of redesign to use the property in ICamera instead.
334      * @param width The width of the image.
335      * @param height The height of the image.
336      * @param cameraHandle Specify if we are interested on some specific camera, 0 is system default.
337      */
338     virtual void SetRenderSize(uint32_t width, uint32_t height, const ICamera::Ptr& camera) = 0;
339 
340     /**
341      *  Load all material proxies on the current scene.
342      */
343     virtual void InstantiateMaterialProxies() = 0;
344 
345     /**
346      *  Load all material proxies on the current scene.
347      */
348     virtual void InstantiateMeshProxies() = 0;
349 
350     /** Calculates a world space AABB from local min max values. */
351     virtual IPickingResult::Ptr GetWorldAABB(
352         const BASE_NS::Math::Mat4X4& world, const BASE_NS::Math::Vec3& aabbMin, const BASE_NS::Math::Vec3& aabbMax) = 0;
353 
354     /**
355      * Get all nodes hit by ray.
356      * @param start Starting point of the ray.
357      * @param direction Direction of the ray.
358      * @return Array of raycast results that describe node that was hit and distance to intersection (ordered by
359      * distance).
360      */
361     virtual IRayCastResult::Ptr RayCast(const BASE_NS::Math::Vec3& start, const BASE_NS::Math::Vec3& direction) = 0;
362 
363     /**
364      * Get nodes hit by ray. Only entities included in the given layer mask are in the result. Entities without
365      * LayerComponent default to LayerConstants::DEFAULT_LAYER_MASK.
366      * @param start Starting point of the ray.
367      * @param direction Direction of the ray.
368      * @param layerMask Layer mask for limiting the returned result.
369      * @return Array of raycast results that describe node that was hit and distance to intersection (ordered by
370      * distance).
371      */
372     virtual IRayCastResult::Ptr RayCast(
373         const BASE_NS::Math::Vec3& start, const BASE_NS::Math::Vec3& direction, uint64_t layerMask) = 0;
374 
375     /**
376      * Activate rendering of camera in scene.
377      * @param camera The camera to be used in rendering
378      */
379     virtual void ActivateCamera(const ICamera::Ptr& camera) = 0;
380 
381     /**
382      * Deactivates rendering of camera in scene.
383      * @param camera The camera to be deactivated.
384      */
385     virtual void DeactivateCamera(const ICamera::Ptr& camera) = 0;
386 
387     virtual bool IsCameraActive(const ICamera::Ptr& camera) = 0;
388 
389     /**
390      * @brief Returns all cameras from the scene.
391      * @return Returns a vector of camera objects.
392      */
393     virtual BASE_NS::vector<ICamera::Ptr> GetCameras() const = 0;
394 
395     // returns a list of camera entities that were updated.
396     virtual BASE_NS::vector<CORE_NS::Entity> RenderCameras() = 0;
397 };
398 
399 SCENE_END_NAMESPACE()
400 
401 META_TYPE(SCENE_NS::IScene::WeakPtr);
402 META_TYPE(SCENE_NS::IScene::Ptr);
403 
404 #endif // SCENEPLUGIN_INTF_SCENE_H
405