224743604430e1b038d1ced9cb90bf7c6aa09a16
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Scene3D / src / public / ModelComponents / ModelNode.cs
1 /*
2  * Copyright(c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 using System;
19 using System.Collections.Generic;
20 using System.Runtime.InteropServices;
21 using System.ComponentModel;
22 using System.Collections.Generic;
23 using Tizen.NUI;
24 using Tizen.NUI.Binding;
25 using Tizen.NUI.BaseComponents;
26
27 namespace Tizen.NUI.Scene3D
28 {
29     /// <summary>
30     /// ModelNode is a class for representing the Node of Model in Scene3D.
31     /// </summary>
32     ///
33     /// <remarks>
34     /// ModelNode contains multiple ModelPrimitives and allows easy access and
35     /// modification of Material information that ModelPrimitive has. If a 3D
36     /// format file is loaded by Model, ModelNode is created internally to
37     /// construct the model. In addition, you can create a Custom ModelNode
38     /// using ModelPrimitive and Material directly and add it to Model.
39     ///
40     /// <code>
41     /// ModelNode modelNode = new ModelNode();
42     /// ModelPrimitive modelPrimitive = new ModelPrimitive();
43     /// modelNode.AddModelPrimitive(modelPrimitive);
44     ///
45     /// Material material = new Material;
46     /// modelPrimitive.Material = material;
47     /// </code>
48     /// </remarks>
49     [EditorBrowsable(EditorBrowsableState.Never)]
50     public class ModelNode : View
51     {
52         internal ModelNode(global::System.IntPtr cPtr, bool cMemoryOwn) : this(cPtr, cMemoryOwn, cMemoryOwn)
53         {
54         }
55
56         internal ModelNode(global::System.IntPtr cPtr, bool cMemoryOwn, bool cRegister) : base(cPtr, cMemoryOwn, true, cRegister)
57         {
58         }
59
60         /// <summary>
61         /// Create an initialized ModelNode.
62         /// </summary>
63         [EditorBrowsable(EditorBrowsableState.Never)]
64         public ModelNode() : this(Interop.ModelNode.ModelNodeNew(), true)
65         {
66             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
67             this.PositionUsesPivotPoint = true;
68         }
69
70         /// <summary>
71         /// Copy constructor.
72         /// </summary>
73         /// <param name="modelNode">Source object to copy.</param>
74         [EditorBrowsable(EditorBrowsableState.Never)]
75         public ModelNode(ModelNode modelNode) : this(Interop.ModelNode.NewModelNode(ModelNode.getCPtr(modelNode)), true, false)
76         {
77             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
78         }
79
80         /// <summary>
81         /// Assignment operator.
82         /// </summary>
83         /// <param name="modelNode">Source object to be assigned.</param>
84         /// <returns>Reference to this.</returns>
85         internal ModelNode Assign(ModelNode modelNode)
86         {
87             ModelNode ret = new ModelNode(Interop.ModelNode.ModelNodeAssign(SwigCPtr, ModelNode.getCPtr(modelNode)), false);
88             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
89             ret.PositionUsesPivotPoint = modelNode.PositionUsesPivotPoint;
90             return ret;
91         }
92
93         /// <summary>
94         /// Get the number of ModelPrimitive of this ModelNode.
95         /// </summary>
96         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
97         [EditorBrowsable(EditorBrowsableState.Never)]
98         public uint ModelPrimitiveCount
99         {
100             get
101             {
102                 return GetModelPrimitiveCount();
103             }
104         }
105
106         /// <summary>
107         /// Adds a ModelPrimitive object to the ModelNode object.
108         /// </summary>
109         /// <param name="modelPrimitive">The ModelPrimitive object to add.</param>
110         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
111         [EditorBrowsable(EditorBrowsableState.Never)]
112         public void AddModelPrimitive(ModelPrimitive modelPrimitive)
113         {
114             Interop.ModelNode.AddModelPrimitive(SwigCPtr, ModelPrimitive.getCPtr(modelPrimitive));
115             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
116         }
117
118         /// <summary>
119         /// Removes a ModelPrimitive object from the ModelNode object.
120         /// </summary>
121         /// <param name="modelPrimitive">The ModelPrimitive object to remove.</param>
122         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
123         [EditorBrowsable(EditorBrowsableState.Never)]
124         public void RemoveModelPrimitive(ModelPrimitive modelPrimitive)
125         {
126             Interop.ModelNode.RemoveModelPrimitive(SwigCPtr, ModelPrimitive.getCPtr(modelPrimitive));
127             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
128         }
129
130         /// <summary>
131         /// Removes a ModelPrimitive object from the ModelNode object at the specified index.
132         /// </summary>
133         /// <param name="index">The index of the ModelPrimitive object to remove.</param>
134         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
135         [EditorBrowsable(EditorBrowsableState.Never)]
136         public void RemoveModelPrimitive(uint index)
137         {
138             Interop.ModelNode.RemoveModelPrimitive(SwigCPtr, index);
139             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
140         }
141
142         /// <summary>
143         /// Gets the ModelPrimitive object at the specified index.
144         /// </summary>
145         /// <param name="index">The index of the ModelPrimitive object to get.</param>
146         /// <returns>The ModelPrimitive object at the specified index.</returns>
147         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
148         [EditorBrowsable(EditorBrowsableState.Never)]
149         public ModelPrimitive GetModelPrimitive(uint index)
150         {
151             global::System.IntPtr cPtr = Interop.ModelNode.GetModelPrimitive(SwigCPtr, index);
152             ModelPrimitive ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as ModelPrimitive;
153             if (ret == null)
154             {
155                 // Register new animatable into Registry.
156                 ret = new ModelPrimitive(cPtr, true);
157             }
158             else
159             {
160                 // We found matched NUI animatable. Reduce cPtr reference count.
161                 HandleRef handle = new HandleRef(this, cPtr);
162                 Tizen.NUI.Interop.BaseHandle.DeleteBaseHandle(handle);
163                 handle = new HandleRef(null, IntPtr.Zero);
164             }
165             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
166             return ret;
167         }
168
169         /// <summary>
170         /// Returns a child ModelNode object with a name that matches nodeName.
171         /// </summary>
172         /// <param name="nodeName">The name of the child ModelNode object you want to find.</param>
173         /// <returns>Child ModelNode that has nodeName as name.</returns>
174         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
175         [EditorBrowsable(EditorBrowsableState.Never)]
176         public ModelNode FindChildModelNodeByName(string nodeName)
177         {
178             global::System.IntPtr cPtr = Interop.Model.FindChildModelNodeByName(SwigCPtr, nodeName);
179             ModelNode ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as ModelNode;
180             if (ret == null)
181             {
182                 // Store the value of PositionUsesAnchorPoint from dali object (Since View object automatically change PositionUsesPivotPoint value as false, we need to keep value.)
183                 HandleRef handle = new HandleRef(this, cPtr);
184
185                 // Use original value as 'true' if we got invalid ModelNode.
186                 bool originalPositionUsesAnchorPoint = (cPtr == global::System.IntPtr.Zero || !Tizen.NUI.Interop.BaseHandle.HasBody(handle)) || Object.InternalGetPropertyBool(handle, View.Property.PositionUsesAnchorPoint);
187                 handle = new HandleRef(null, IntPtr.Zero);
188
189                 // Register new animatable into Registry.
190                 ret = new ModelNode(cPtr, true);
191                 if (ret != null)
192                 {
193                     ret.PositionUsesPivotPoint = originalPositionUsesAnchorPoint;
194                 }
195             }
196             else
197             {
198                 // We found matched NUI animatable. Reduce cPtr reference count.
199                 HandleRef handle = new HandleRef(this, cPtr);
200                 Tizen.NUI.Interop.BaseHandle.DeleteBaseHandle(handle);
201                 handle = new HandleRef(null, IntPtr.Zero);
202             }
203             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
204             return ret;
205         }
206         
207         /// <summary>
208         /// Sets collider mesh on current node
209         /// </summary>
210         /// <param name="vertexList">List of vertices</param>
211         /// <param name="normalList">List of vertex normals</param>
212         /// <param name="indexList">List of mesh indices</param>
213         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
214         [EditorBrowsable(EditorBrowsableState.Never)]
215         public void SetColliderMesh(List<Vector3> vertexList, List<Vector3> normalList, List<int> indexList)
216         {
217             var vertices = new Interop.ModelNode.Vec3[vertexList.Count];
218             var idx = 0;
219             foreach (var vertex in vertexList)
220             {
221                 vertices[idx].x = vertex.X;
222                 vertices[idx].y = vertex.Y;
223                 vertices[idx].z = vertex.Z;
224                 ++idx;
225             }
226             
227             var normals = new Interop.ModelNode.Vec3[normalList.Count];
228             idx = 0;
229             foreach (var normal in normalList)
230             {
231                 normals[idx].x = normal.X;
232                 normals[idx].y = normal.Y;
233                 normals[idx].z = normal.Z;
234                 ++idx;
235             }
236             
237             Interop.ModelNode.SetColliderMesh(SwigCPtr,vertices, normals, vertexList.Count, indexList.ToArray(), indexList.Count);
238             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
239         }
240
241         /// <summary>
242         /// Gets the number of ModelPrimitive objects in the ModelNode object.
243         /// </summary>
244         /// <returns>The number of ModelPrimitive objects in the ModelNode object.</returns>
245         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
246         [EditorBrowsable(EditorBrowsableState.Never)]
247         private uint GetModelPrimitiveCount()
248         {
249             uint ret = Interop.ModelNode.GetModelPrimitiveCount(SwigCPtr);
250             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
251             return ret;
252         }
253
254         /// <summary>
255         /// Build C# ModelNode Tree
256         /// </summary>
257         [EditorBrowsable(EditorBrowsableState.Never)]
258         internal void Build()
259         {
260             List<ModelNode> childModelNodes = new List<ModelNode>();
261             uint childModelNodeCount = GetChildModelNodeCount();
262             for (uint i = 0; i < childModelNodeCount; ++i)
263             {
264                 ModelNode modelNode = GetChildModelNodeAt(i);
265                 if (modelNode != null)
266                 {
267                     childModelNodes.Add(modelNode);
268                     modelNode.Build();
269                 }
270             }
271
272             foreach (ModelNode node in childModelNodes)
273             {
274                 this.Add(node);
275             }
276         }
277
278         /// <summary>
279         /// Gets the number of child objects in the ModelNode object.
280         /// </summary>
281         /// <returns>The number of childchild objects in the ModelNode object.</returns>
282         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
283         [EditorBrowsable(EditorBrowsableState.Never)]
284         private uint GetChildModelNodeCount()
285         {
286             uint ret = Interop.ModelNode.GetChildModelNodeCount(SwigCPtr);
287             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
288             return ret;
289         }
290
291         /// <summary>
292         /// Returns a child ModelNode object at the index.
293         /// </summary>
294         /// <param name="index">The index of child ModelNode object you want to find.</param>
295         /// <returns>Child ModelNode</returns>
296         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
297         [EditorBrowsable(EditorBrowsableState.Never)]
298         private ModelNode GetChildModelNodeAt(uint index)
299         {
300             global::System.IntPtr cPtr = Interop.ModelNode.GetChildModelNodeAt(SwigCPtr, index);
301             ModelNode ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as ModelNode;
302             if (ret == null)
303             {
304                 // Store the value of PositionUsesAnchorPoint from dali object (Since View object automatically change PositionUsesPivotPoint value as false, we need to keep value.)
305                 HandleRef handle = new HandleRef(this, cPtr);
306
307                 // Use original value as 'true' if we got invalid ModelNode.
308                 bool originalPositionUsesAnchorPoint = (cPtr == global::System.IntPtr.Zero || !Tizen.NUI.Interop.BaseHandle.HasBody(handle)) || Object.InternalGetPropertyBool(handle, View.Property.PositionUsesAnchorPoint);
309                 handle = new HandleRef(null, IntPtr.Zero);
310
311                 // Register new animatable into Registry.
312                 ret = new ModelNode(cPtr, true);
313                 if (ret != null)
314                 {
315                     ret.PositionUsesPivotPoint = originalPositionUsesAnchorPoint;
316                 }
317             }
318             else
319             {
320                 // We found matched NUI animatable. Reduce cPtr reference count.
321                 HandleRef handle = new HandleRef(this, cPtr);
322                 Tizen.NUI.Interop.BaseHandle.DeleteBaseHandle(handle);
323                 handle = new HandleRef(null, IntPtr.Zero);
324             }
325             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
326             return ret;
327         }
328
329         /// <summary>
330         /// Release swigCPtr.
331         /// </summary>
332         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
333         [EditorBrowsable(EditorBrowsableState.Never)]
334         protected override void ReleaseSwigCPtr(global::System.Runtime.InteropServices.HandleRef swigCPtr)
335         {
336             Interop.ModelNode.DeleteModelNode(swigCPtr);
337         }
338     }
339 }