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 #ifndef API_3D_ECS_SYSTEMS_INODE_SYSTEM_H
17 #define API_3D_ECS_SYSTEMS_INODE_SYSTEM_H
18 
19 #include <3d/namespace.h>
20 #include <base/containers/array_view.h>
21 #include <base/containers/string.h>
22 #include <base/containers/string_view.h>
23 #include <base/containers/vector.h>
24 #include <base/math/quaternion.h>
25 #include <base/math/vector.h>
26 #include <core/ecs/entity.h>
27 #include <core/ecs/intf_system.h>
28 
29 CORE_BEGIN_NAMESPACE()
30 class IComponentManager;
31 CORE_END_NAMESPACE()
32 
CORE3D_BEGIN_NAMESPACE()33 CORE3D_BEGIN_NAMESPACE()
34 /** @ingroup group_ecs_systems_inode */
35 /**
36  * Scene Node.
37  * Scene node has components automatically for:
38  * NodeComponent, NameComponent, LocalMatrixComponent, TransformComponent, WorldMatrixComponent
39  */
40 class ISceneNode {
41 public:
42     virtual ~ISceneNode() = default;
43 
44     /** Retrieve name of this node.
45      */
46     virtual BASE_NS::string GetName() const = 0;
47 
48     /** Set name of this node.
49      *  @param name String to be set as a name for this node.
50      */
51     virtual void SetName(BASE_NS::string_view name) = 0;
52 
53     /** Set node enabled or disabled, Disabled node is excluded from rendering and logic that is run by ECS systems.
54      *  @param isEnabled Boolean value that defines whether this node is enabled or disabled.
55      */
56     virtual void SetEnabled(bool isEnabled) = 0;
57 
58     /** Check whether node is enabled or disabled.
59      */
60     virtual bool GetEnabled() const = 0;
61 
62     /** Check whether node and all its parent nodes are enabled or disabled.
63      */
64     virtual bool GetEffectivelyEnabled() const = 0;
65 
66     /** Retrieve parent of this node.
67      */
68     virtual ISceneNode* GetParent() const = 0;
69 
70     /** Set parent of this node.
71      *  @param node Parent to be set for this node.
72      */
73     virtual void SetParent(ISceneNode const& node) = 0;
74 
75     /** Check if given node is this node or descendant of this node.
76      *  @param node a Node which against parenthood is checked
77      */
78     virtual bool IsAncestorOf(ISceneNode const& node) = 0;
79 
80     /** Retrieve children of this node.
81      */
82     virtual BASE_NS::array_view<ISceneNode* const> GetChildren() const = 0;
83 
84     /** Retrieve children of this node.
85      */
86     virtual BASE_NS::array_view<ISceneNode*> GetChildren() = 0;
87 
88     /** Retrieve Entity that is associated to this node.
89      */
90     virtual CORE_NS::Entity GetEntity() const = 0;
91 
92     /** Get child node of given parent node by name.
93      *  @param name Name which is used to find children.
94      */
95     virtual const ISceneNode* GetChild(BASE_NS::string_view const& name) const = 0;
96 
97     /** Get child node of given parent node by name.
98      *  @param name Name which is used to find children.
99      */
100     virtual ISceneNode* GetChild(BASE_NS::string_view const& name) = 0;
101 
102     /** Add the given node as a child of this node. The node will be placed last in the child list.
103      * @param node Node to add
104      * @return true if node could be added
105      */
106     virtual bool AddChild(ISceneNode& node) = 0;
107 
108     /** Add the given node as a child of this node. The node will be inserted to the given index, or last if the index
109      * is out of bounds.
110      * @param index Insert location.
111      * @param node Node to add.
112      * @return true if node could be added.
113      */
114     virtual bool InsertChild(size_t index, ISceneNode& node) = 0;
115 
116     /** Remove the given node from this node.
117      * @param node Node to add
118      * @return true if node could be removed.
119      */
120     virtual bool RemoveChild(ISceneNode& node) = 0;
121 
122     /** Remove the node at the given index from this node.
123      * @param index Location to remove.
124      * @return true if node could be removed, false if index is out of bounds.
125      */
126     virtual bool RemoveChild(size_t index) = 0;
127 
128     /** Remove all child nodes.
129      * @return true if nodes could be removed.
130      */
131     virtual bool RemoveChildren() = 0;
132 
133     /** Get child node of given parent node by path.
134      *  @param path String of a path which is then used like (ie. path/to/child).
135      */
136     virtual const ISceneNode* LookupNodeByPath(BASE_NS::string_view const& path) const = 0;
137 
138     /** Get child node of given parent node by path.
139      *  @param path String of a path which is then used like (ie. path/to/child).
140      */
141     virtual ISceneNode* LookupNodeByPath(BASE_NS::string_view const& path) = 0;
142 
143     /** Recursively look up node by name (returns the first node with given name assigned).
144      *  @param name Name of the node.
145      */
146     virtual const ISceneNode* LookupNodeByName(BASE_NS::string_view const& name) const = 0;
147 
148     /** Recursively look up node by name (returns the first node with given name assigned).
149      *  @param name Name of the node.
150      */
151     virtual ISceneNode* LookupNodeByName(BASE_NS::string_view const& name) = 0;
152 
153     /** Recursively look up node by component type (returns the first node that has given component assigned).
154      *  @param componentManager Component manager that defines the type of the component.
155      */
156     virtual const ISceneNode* LookupNodeByComponent(const CORE_NS::IComponentManager& componentManager) const = 0;
157 
158     /** Recursively look up node by component type (returns the first node that has given component assigned).
159      *  @param componentManager Component manager that defines the type of the component.
160      */
161     virtual ISceneNode* LookupNodeByComponent(const CORE_NS::IComponentManager& componentManager) = 0;
162 
163     /** Recursively look up multiple nodes in hierarchy by component type (returns all nodes with given component
164      * assigned).
165      *  @param componentManager Component manager that defines the type of the component.
166      */
167     virtual BASE_NS::vector<const ISceneNode*> LookupNodesByComponent(
168         const CORE_NS::IComponentManager& componentManager) const = 0;
169 
170     /** Recursively look up multiple nodes in hierarchy by component type (returns all nodes with given component
171      * assigned).
172      *  @param componentManager Component manager that defines the type of the component.
173      */
174     virtual BASE_NS::vector<ISceneNode*> LookupNodesByComponent(const CORE_NS::IComponentManager& componentManager) = 0;
175 
176     // Convenience methods for accessing node transform data.
177     /** Get nodes position data
178      */
179     virtual BASE_NS::Math::Vec3 GetPosition() const = 0;
180 
181     /** Get nodes rotation data
182      */
183     virtual BASE_NS::Math::Quat GetRotation() const = 0;
184 
185     /** Get nodes scale data
186      */
187     virtual BASE_NS::Math::Vec3 GetScale() const = 0;
188 
189     /** Set nodes scale data
190      */
191     virtual void SetScale(const BASE_NS::Math::Vec3& scale) = 0;
192 
193     /** Set nodes position data
194      */
195     virtual void SetPosition(const BASE_NS::Math::Vec3& position) = 0;
196 
197     /** Set nodes rotation data
198      */
199     virtual void SetRotation(const BASE_NS::Math::Quat& rotation) = 0;
200 };
201 
202 /** @ingroup group_ecs_systems_inode */
203 class INodeSystem : public CORE_NS::ISystem {
204 public:
205     static constexpr BASE_NS::Uid UID { "b564d740-3d39-41e7-9add-0bdbdbdf23a8" };
206 
207     /** Retrieve root node of the scene graph.
208      */
209     virtual ISceneNode& GetRootNode() const = 0;
210 
211     /** Get node from entity.
212      *  @param entity Entity object where we get node from
213      */
214     virtual ISceneNode* GetNode(CORE_NS::Entity entity) const = 0;
215 
216     /** Create new scene node.
217      * Creates components for LocalMatrixComponent, NodeComponent, NameComponent, TransformComponent,
218      * WorldMatrixComponent.
219      */
220     virtual ISceneNode* CreateNode() = 0;
221 
222     /* Create a clone of a node. Clones all components that the node has.
223      * @param node Node to be cloned.
224      * @param recursive Set to true to also clone all children of the node recursively.
225      */
226     virtual ISceneNode* CloneNode(const ISceneNode& node, bool recursive) = 0;
227 
228     /** Destroy the scene node and its children.
229      * @param node Node to destroy.
230      */
231     virtual void DestroyNode(ISceneNode& node) = 0;
232 
233     /** Listener for changes in SceneNode children. */
234     class SceneNodeListener {
235     public:
236         enum class EventType : uint8_t {
237             /** Child added */
238             ADDED,
239             /** Child removed */
240             REMOVED,
241         };
242         /** Signals a change in a node's children.
243          * @param parent Node where change happened.
244          * @param type Type of the change.
245          * @param child Child node.
246          * @param index Index where node was added or removed.
247          */
248         virtual void OnChildChanged(
249             const ISceneNode& parent, EventType type, const ISceneNode& child, size_t index) = 0;
250 
251     protected:
252         virtual ~SceneNodeListener() = default;
253     };
254 
255     /** Add listener for SceneNode events.
256      */
257     virtual void AddListener(SceneNodeListener& listener) = 0;
258 
259     /** Remove SceneNode event listener.
260      */
261     virtual void RemoveListener(SceneNodeListener& listener) = 0;
262 
263 protected:
264     INodeSystem() = default;
265     INodeSystem(const INodeSystem&) = delete;
266     INodeSystem(INodeSystem&&) = delete;
267     INodeSystem& operator=(const INodeSystem&) = delete;
268     INodeSystem& operator=(INodeSystem&&) = delete;
269 };
270 
271 /** @ingroup group_ecs_systems_inode */
272 /** Return name of this system
273  */
GetName(const INodeSystem *)274 inline constexpr BASE_NS::string_view GetName(const INodeSystem*)
275 {
276     return "NodeSystem";
277 }
278 CORE3D_END_NAMESPACE()
279 
280 #endif // API_3D_ECS_SYSTEMS_INODE_SYSTEM_H
281