f84af373028c971c281648c783f32a3449c09531
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Scene3D / src / public / Controls / SceneView.cs
1 /*
2  * Copyright(c) 2022 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.Runtime.InteropServices;
20 using System.ComponentModel;
21 using Tizen.NUI;
22 using Tizen.NUI.Binding;
23 using Tizen.NUI.BaseComponents;
24
25 namespace Tizen.NUI.Scene3D
26 {
27     /// <summary>
28     /// SceneView is a Class to show multiple 3D objects in a single 2D screen.
29     /// Each SceneView has its own 3D space, and 3D objects added to SceneView are positioned in the space.
30     /// SceneView uses left-handed coordinate system same as NUI. X as right, Y as down, and Z as forward.
31     ///
32     /// SceneView has internal root container to control inner rendering process like depth test.
33     /// When a View is added to the SceneView with <see cref="View.Add(View)"/> method, it is actually added on the root container.
34     /// Therefore, the added Views exist in the sub tree of SceneView, but are not direct children.
35     /// The sub tree of Views will be rendered with the SceneView's own Camera.
36     ///
37     /// SceneView has one built-in camera by default.
38     /// The default Camera is not removed by using <see cref="RemoveCamera(Camera)"/> method.
39     /// <see cref="GetCamera(uint)"/> method with index "0" returns the default camera,
40     /// and the minimum value returned by <see cref="GetCameraCount()"/> method is 1.
41     ///
42     /// SceneView also provides multiple Camera and one of them can be used to render multiple objects.
43     /// <see cref="AddCamera(Camera)"/>, <see cref="RemoveCamera(Camera)"/>, <see cref="GetCamera(uint)"/>,
44     /// and <see cref="SelectCamera(uint)"/> are methods to manage Cameras of the SceneView.
45     /// User can place multiple cameras in a scene to display the entire scene or to display individual objects.
46     /// User can use the <see cref="SelectCamera(uint)"/> method to select the currently required camera.
47     ///
48     /// When the SceneView's size changes, some camera properties that depend on its size may also change.
49     /// The changing properties are as follows: AspectRatio, LeftPlaneDistance, RightPlaneDistance, TopPlaneDistance, and BottomPlaneDistance.
50     /// The Camera's FieldOfView is vertical fov. The horizontal fov is updated internally according to the SceneView size.
51     ///
52     /// The <see cref="SetImageBasedLightSource(string, string, float)"/> method sets the same IBL to all Model objects added to the SceneView.
53     /// For the IBL, two cube map textures(diffuse and specular) are required.
54     /// SceneView supports 4 types layout for Cube Map: Vertical/Horizontal Cross layouts, and Vertical/Horizontal Array layouts.
55     /// And also, ktx format with cube map is supported.
56     /// If a model already has an IBL, it is batch overridden with the IBL of the SceneView.
57     /// If the SceneView has IBL, the IBL of newly added models is also overridden.
58     ///
59     /// The IBL textures start to be loaded asynchronously when <see cref="SetImageBasedLightSource(string, string, float)"/> method is called.
60     /// ResourcesLoaded signal notifies that the loading of the IBL resources have been completed.
61     ///
62     /// If FBO is used, the rendering result of SceneView is drawn on the FBO and it is mapped on the plane of the SceneView.
63     /// It could decreases performance slightly, but it is useful to show SceneView according to the rendering order with other Views.
64     ///
65     /// And since SceneView is a View, it can be placed together with other 2D UI components in the NUI window.
66     /// </summary>
67     /// <since_tizen> 10 </since_tizen>
68     public class SceneView : View
69     {
70         private bool inCameraTransition = false;
71         private Animation cameraTransition;
72         private string skyboxUrl;
73
74         internal SceneView(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
75         {
76         }
77
78         /// <summary>
79         /// Create an initialized SceneView.
80         /// </summary>
81         /// <since_tizen> 10 </since_tizen>
82         public SceneView() : this(Interop.SceneView.SceneNew(), true)
83         {
84             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
85         }
86
87         /// <summary>
88         /// Copy constructor.
89         /// </summary>
90         /// <param name="sceneView">The source object.</param>
91         /// <since_tizen> 10 </since_tizen>
92         public SceneView(SceneView sceneView) : this(Interop.SceneView.NewScene(SceneView.getCPtr(sceneView)), true)
93         {
94             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
95         }
96
97         /// <summary>
98         /// Assignment operator.
99         /// </summary>
100         /// <param name="sceneView">Handle to an object.</param>
101         /// <returns>Reference to this.</returns>
102         internal SceneView Assign(SceneView sceneView)
103         {
104             SceneView ret = new SceneView(Interop.SceneView.SceneAssign(SwigCPtr, SceneView.getCPtr(sceneView)), false);
105             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
106             return ret;
107         }
108
109         /// <summary>
110         /// An event emitted when Camera Transition is finished.
111         /// </summary>
112         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
113         [EditorBrowsable(EditorBrowsableState.Never)]
114         public event EventHandler CameraTransitionFinished;
115
116         /// <summary>
117         /// Set/Get the ImageBasedLight ScaleFactor.
118         /// Scale factor controls light source intensity in [0.0f, 1.0f]
119         /// </summary>
120         /// <since_tizen> 10 </since_tizen>
121         public float ImageBasedLightScaleFactor
122         {
123             set
124             {
125                 SetImageBasedLightScaleFactor(value);
126             }
127             get
128             {
129                 return GetImageBasedLightScaleFactor();
130             }
131         }
132
133         /// <summary>
134         /// Set/Get the UseFramebuffer.
135         /// If this property is true, rendering result of SceneView is drawn on FBO and it is mapping on this SceneView plane.
136         /// If this property is false, each item in SceneView is rendered on window directly.
137         /// Default is false.
138         /// </summary>
139         /// <remarks>
140         /// If UseFramebuffer is true, it could decrease performance but entire rendering order is satisfied.
141         /// If UseFramebuffer is false, the performance becomes better but SceneView is rendered on the top of the other 2D components regardless tree order.
142         /// </remarks>
143         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
144         [EditorBrowsable(EditorBrowsableState.Never)]
145         public bool UseFramebuffer
146         {
147             set
148             {
149                 SetUseFramebuffer(value);
150             }
151             get
152             {
153                 return IsUsingFramebuffer();
154             }
155         }
156
157         /// <summary>
158         /// Set/Get the Framebuffer's MultiSamplingLevel.
159         /// Only has effects if UseFramebuffer is true, and Framebuffer MultiSampling is supported.
160         /// Default is 0.
161         /// </summary>
162         /// <remarks>
163         /// Getter didn't consider Framebuffer MultiSampling is supported or not.
164         /// </remarks>
165         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
166         [EditorBrowsable(EditorBrowsableState.Never)]
167         public uint FramebufferMultiSamplingLevel
168         {
169             set
170             {
171                 SetFramebufferMultiSamplingLevel(value);
172             }
173             get
174             {
175                 return GetFramebufferMultiSamplingLevel();
176             }
177         }
178
179         /// <summary>
180         /// Set/Get SkyboxUrl.
181         /// If SkyboxUrl is set, the cube map image is loaded and skybox is attached on scene.
182         /// Skybox texture is asynchronously loaded. When loading is finished, ResourcesLoaded is emitted.
183         /// </summary>
184         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
185         [EditorBrowsable(EditorBrowsableState.Never)]
186         public string SkyboxUrl
187         {
188             set
189             {
190                 SetSkybox(value);
191             }
192             get
193             {
194                 return skyboxUrl;
195             }
196         }
197
198         /// <summary>
199         /// Set/Get Skybox intensity.
200         /// The skybox intensity is multiplied to the color of skybox texture.
201         /// Default value is 1.0f.
202         /// </summary>
203         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
204         [EditorBrowsable(EditorBrowsableState.Never)]
205         public float SkyboxIntensity
206         {
207             set
208             {
209                 SetSkyboxIntensity(value);
210             }
211             get
212             {
213                 return GetSkyboxIntensity();
214             }
215         }
216
217         /// <summary>
218         /// Set/Get angle of orientation of the skybox.
219         /// If orientation is set, the skybox will be rotate by the Radian orientation along YAxis.
220         /// Default value is 0.0f.
221         /// </summary>
222         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
223         [EditorBrowsable(EditorBrowsableState.Never)]
224         public Rotation SkyboxOrientation
225         {
226             set
227             {
228                 SetSkyboxOrientation(value);
229             }
230             get
231             {
232                 return GetSkyboxOrientation();
233             }
234         }
235
236         /// <summary>
237         /// Adds a Camera to the SceneView at the end of the camera list of SceneView.
238         /// The Camera can be used as a selected camera to render the scene by using <see cref="SelectCamera(uint)"/> or <see cref="SelectCamera(string)"/>
239         /// </summary>
240         /// <param name="camera">Camera added on this SceneView.</param>
241         /// <remarks>
242         /// Some properties of the Camera will be change depending on the Size of this SceneView.
243         /// Those properties are as follows:
244         /// AspectRatio, LeftPlaneDistance, RightPlaneDistance, TopPlaneDistance, and BottomPlaneDistance.
245         ///
246         /// The FieldOfView of Camera is for vertical fov.
247         /// When the size of the SceneView is changed, the vertical fov is maintained
248         /// and the horizontal fov is automatically calculated according to the SceneView's AspectRatio.
249         /// </remarks>
250         /// <since_tizen> 10 </since_tizen>
251         public void AddCamera(Camera camera)
252         {
253             if(camera != null)
254             {
255                 Interop.SceneView.AddCamera(SwigCPtr, camera.SwigCPtr);
256                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
257             }
258         }
259
260         /// <summary>
261         /// Removes a Camera from this SceneView.
262         /// If removed Camera is selected Camera,
263         /// first camera in the list becomes the selected Camera.
264         /// </summary>
265         /// <param name="camera"> camera Camera to be removed from this Camera.</param>
266         /// <remarks>
267         /// When Camera.Dispose() is called, the NUI object is disposed, but camera information is maintained internally.
268         /// Therefore, even if Camera.Dispose() is called, RemoveCamera() or RemoveCamera() methods can be used.
269         /// If RemoveCamera() is called too, all information is deleted together.
270         /// </remarks>
271         /// <since_tizen> 10 </since_tizen>
272         public void RemoveCamera(Camera camera)
273         {
274             if(camera != null)
275             {
276                 Interop.SceneView.RemoveCamera(SwigCPtr, camera.SwigCPtr);
277                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
278             }
279         }
280
281         /// <summary>
282         /// Retrieves the number of cameras.
283         /// </summary>
284         /// <returns>The number of Cameras.</returns>
285         /// <since_tizen> 10 </since_tizen>
286         public uint GetCameraCount()
287         {
288             uint count = Interop.SceneView.GetCameraCount(SwigCPtr);
289             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
290             return count;
291         }
292
293         /// <summary>
294         /// Retrieves a Camera of the index.
295         /// </summary>
296         /// <param name="index"> Index of Camera to be retrieved.</param>
297         /// <returns>Camera of the index.</returns>
298         /// <since_tizen> 10 </since_tizen>
299         public Camera GetCamera(uint index)
300         {
301             global::System.IntPtr cPtr = Interop.SceneView.GetCamera(SwigCPtr, index);
302             Camera camera = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Camera;
303             if(camera == null)
304             {
305                 // Register new camera into Registry.
306                 camera = new Camera(cPtr, true);
307             }
308             else
309             {
310                 // We found matched NUI camera. Reduce cPtr reference count.
311                 HandleRef handle = new HandleRef(this, cPtr);
312                 Interop.Camera.DeleteCameraProperty(handle);
313                 handle = new HandleRef(null, IntPtr.Zero);
314             }
315             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
316             return camera;
317         }
318
319         /// <summary>
320         /// Retrieves a Camera of the input name.
321         /// </summary>
322         /// <param name="name"> string keyword of Camera to be retrieved.</param>
323         /// <returns>Camera that has the name as a View.Name property</returns>
324         /// <since_tizen> 10 </since_tizen>
325         public Camera GetCamera(string name)
326         {
327             global::System.IntPtr cPtr = Interop.SceneView.GetCamera(SwigCPtr, name);
328             Camera camera = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Camera;
329             if(camera == null)
330             {
331                 // Register new camera into Registry.
332                 camera = new Camera(cPtr, true);
333             }
334             else
335             {
336                 // We found matched NUI camera. Reduce cPtr reference count.
337                 HandleRef handle = new HandleRef(this, cPtr);
338                 Interop.Camera.DeleteCameraProperty(handle);
339                 handle = new HandleRef(null, IntPtr.Zero);
340             }
341             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
342             return camera;
343         }
344
345         /// <summary>
346         /// Makes SceneView use a Camera of index as a selected camera.
347         /// </summary>
348         /// <param name="index"> Index of Camera to be used as a selected camera.</param>
349         /// <since_tizen> 10 </since_tizen>
350         public void SelectCamera(uint index)
351         {
352             if(inCameraTransition)
353             {
354                 return;
355             }
356             Interop.SceneView.SelectCamera(SwigCPtr, index);
357             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
358         }
359
360         /// <summary>
361         /// Makes SceneView use a Camera of a name as a selected camera.
362         /// </summary>
363         /// <param name="name"> string keyword of Camera to be used as a selected camera.</param>
364         /// <since_tizen> 10 </since_tizen>
365         public void SelectCamera(string name)
366         {
367             if(inCameraTransition)
368             {
369                 return;
370             }
371             Interop.SceneView.SelectCamera(SwigCPtr, name);
372             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
373         }
374
375         /// <summary>
376         /// Starts camera transition from currently selected camera to a camera of index.
377         /// Camera Position, Orientation and FieldOfView are smoothly animated.
378         /// </summary>
379         /// <remarks>
380         /// The selected camera is switched to the Camera of the index when the transition is started.
381         /// During camera transition, Selected Camera should not be changed by using SelectCamera() or CameraTransition() method.
382         /// During camera transition, Camera properties of Selected Camera should not be changed.
383         /// </remarks>
384         /// <param name="index"> Index of destination Camera of Camera transition.</param>
385         /// <param name="durationMilliSeconds">The duration in milliseconds.</param>
386         /// <param name="alphaFunction">The alpha function to apply.</param>
387         /// <since_tizen> 10 </since_tizen>
388         public void CameraTransition(uint index, int durationMilliSeconds, AlphaFunction alphaFunction = null)
389         {
390             if(inCameraTransition || GetSelectedCamera() == GetCamera(index))
391             {
392                 return;
393             }
394             Camera source = GetSelectedCamera();
395             SelectCamera(index);
396             Camera destination = GetSelectedCamera();
397             CameraTransition(source, destination, durationMilliSeconds, alphaFunction);
398             source.Dispose();
399             destination.Dispose();
400         }
401
402         /// <summary>
403         /// Starts camera transition from currently selected camera to a camera of input name.
404         /// Camera Position, Orientation and FieldOfView are smoothly animated.
405         /// </summary>
406         /// <remarks>
407         /// The selected camera is switched to the Camera of the input name when the transition is started.
408         /// During camera transition, Selected Camera should not be changed by using SelectCamera() or CameraTransition() method.
409         /// During camera transition, Camera properties of Selected Camera should not be changed.
410         /// </remarks>
411         /// <param name="name"> string keyword of destination Camera of Camera transition.</param>
412         /// <param name="durationMilliSeconds">The duration in milliseconds.</param>
413         /// <param name="alphaFunction">The alpha function to apply.</param>
414         /// <since_tizen> 10 </since_tizen>
415         public void CameraTransition(string name, int durationMilliSeconds, AlphaFunction alphaFunction = null)
416         {
417             if(inCameraTransition || GetSelectedCamera() == GetCamera(name))
418             {
419                 return;
420             }
421             Camera source = GetSelectedCamera();
422             SelectCamera(name);
423             Camera destination = GetSelectedCamera();
424             CameraTransition(source, destination, durationMilliSeconds, alphaFunction);
425             source.Dispose();
426             destination.Dispose();
427         }
428
429         /// <summary>
430         /// Retrieves selected Camera.
431         /// </summary>
432         /// <returns> Camera currently used in SceneView as a selected Camera.</returns>
433         /// <since_tizen> 10 </since_tizen>
434         public Camera GetSelectedCamera()
435         {
436             global::System.IntPtr cPtr = Interop.SceneView.GetSelectedCamera(SwigCPtr);
437             Camera camera = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Camera;
438             if(camera == null)
439             {
440                 // Register new camera into Registry.
441                 camera = new Camera(cPtr, true);
442             }
443             else
444             {
445                 // We found matched NUI camera. Reduce cPtr reference count.
446                 HandleRef handle = new HandleRef(this, cPtr);
447                 Interop.Camera.DeleteCameraProperty(handle);
448                 handle = new HandleRef(null, IntPtr.Zero);
449             }
450             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
451             return camera;
452         }
453
454         /// <summary>
455         /// Changes Image Based Light as the input textures.
456         /// </summary>
457         /// <param name="diffuseUrl">The path of Cube map image that can be used as a diffuse IBL source.</param>
458         /// <param name="specularUrl">The path of Cube map image that can be used as a specular IBL source.</param>
459         /// <param name="scaleFactor">Scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f.</param>
460         /// <remarks>
461         /// http://tizen.org/privilege/mediastorage for local files in media storage.
462         /// http://tizen.org/privilege/externalstorage for local files in external storage.
463         /// </remarks>
464         /// <since_tizen> 10 </since_tizen>
465         public void SetImageBasedLightSource(string diffuseUrl, string specularUrl, float scaleFactor = 1.0f)
466         {
467             Interop.SceneView.SetImageBasedLightSource(SwigCPtr, diffuseUrl, specularUrl, scaleFactor);
468             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
469         }
470
471         internal void SetUseFramebuffer(bool useFramebuffer)
472         {
473             Interop.SceneView.UseFramebuffer(SwigCPtr, useFramebuffer);
474             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
475         }
476
477         internal bool IsUsingFramebuffer()
478         {
479             bool result = Interop.SceneView.IsUsingFramebuffer(SwigCPtr);
480             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
481             return result;
482         }
483
484         internal void SetFramebufferMultiSamplingLevel(uint multiSamplingLevel)
485         {
486             Interop.SceneView.SetFramebufferMultiSamplingLevel(SwigCPtr, multiSamplingLevel);
487             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
488         }
489
490         internal uint GetFramebufferMultiSamplingLevel()
491         {
492             uint result = Interop.SceneView.GetFramebufferMultiSamplingLevel(SwigCPtr);
493             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
494             return result;
495         }
496
497         /// <summary>
498         /// Set the ImageBasedLight ScaleFactor.
499         /// </summary>
500         /// <param name="scaleFactor">Scale factor that controls light source intensity in [0.0f, 1.0f].</param>
501         private void SetImageBasedLightScaleFactor(float scaleFactor)
502         {
503             Interop.SceneView.SetImageBasedLightScaleFactor(SwigCPtr, scaleFactor);
504             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
505         }
506
507         /// <summary>
508         /// Get the ImageBasedLight ScaleFactor.
509         /// </summary>
510         /// <returns>ImageBasedLightScaleFactor that controls light source intensity.</returns>
511         private float GetImageBasedLightScaleFactor()
512         {
513             float scaleFactor = Interop.SceneView.GetImageBasedLightScaleFactor(SwigCPtr);
514             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
515             return scaleFactor;
516         }
517
518         /// <summary>
519         /// Set the Skybox from cube map image.
520         /// Skybox texture is asynchronously loaded. When loading is finished, ResourcesLoaded is emitted.
521         /// </summary>
522         /// <param name="skyboxUrl">Cube map image url for skybox.</param>
523         private void SetSkybox(string skyboxUrl)
524         {
525             this.skyboxUrl = skyboxUrl;
526             Interop.SceneView.SetSkybox(SwigCPtr, skyboxUrl);
527             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
528         }
529
530         /// <summary>
531         /// Sets Skybox intensity.
532         /// The skybox intensity is multiplied to the color of skybox texture.
533         /// Default value is 1.0f.
534         /// </summary>
535         /// <param name="intensity">Intensity value to be multiplied to the cube map color.</param>
536         private void SetSkyboxIntensity(float intensity)
537         {
538             Interop.SceneView.SetSkyboxIntensity(SwigCPtr, intensity);
539             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
540         }
541
542         /// <summary>
543         /// Gets Skybox intensity.
544         /// Default value is 1.0f.
545         /// </summary>
546         /// <returns>skybox intensity.</returns>
547         private float GetSkyboxIntensity()
548         {
549             float intensity = Interop.SceneView.GetSkyboxIntensity(SwigCPtr);
550             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
551             return intensity;
552         }
553
554         /// <summary>
555         /// Sets orientation of the skybox.
556         /// </summary>
557         /// <param name="orientation">Rotation angle of the skybox along YAxis.</param>
558         private void SetSkyboxOrientation(Rotation orientation)
559         {
560             Interop.SceneView.SetSkyboxOrientation(SwigCPtr, Rotation.getCPtr(orientation));
561             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
562         }
563
564         /// <summary>
565         /// Gets Skybox orientation.
566         /// </summary>
567         /// <returns>skybox orientation.</returns>
568         private Rotation GetSkyboxOrientation()
569         {
570             global::System.IntPtr cPtr = Interop.SceneView.GetSkyboxOrientation(SwigCPtr);
571             Rotation ret = (cPtr == global::System.IntPtr.Zero) ? null : new Rotation(cPtr, true);
572             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
573             return ret;
574         }
575
576         private void CameraTransition(Camera sourceCamera, Camera destinationCamera, int durationMilliSeconds, AlphaFunction alphaFunction)
577         {
578             inCameraTransition = true;
579
580             Position sourcePosition = sourceCamera.Position;
581             Rotation sourceOrientation = sourceCamera.Orientation;
582
583             Position destinationPosition = destinationCamera.Position;
584             Rotation destinationOrientation = destinationCamera.Orientation;
585
586             cameraTransition = new Animation(durationMilliSeconds);
587
588             KeyFrames positionKeyFrames = new KeyFrames();
589             positionKeyFrames.Add(0.0f, sourcePosition);
590             positionKeyFrames.Add(1.0f, destinationPosition);
591
592             KeyFrames orientationKeyFrames = new KeyFrames();
593             orientationKeyFrames.Add(0.0f, sourceOrientation);
594             orientationKeyFrames.Add(1.0f, destinationOrientation);
595
596             cameraTransition.AnimateBetween(destinationCamera, "Position", positionKeyFrames, Animation.Interpolation.Linear, alphaFunction);
597             cameraTransition.AnimateBetween(destinationCamera, "Orientation", orientationKeyFrames, Animation.Interpolation.Linear, alphaFunction);
598
599             if(destinationCamera.ProjectionMode == Camera.ProjectionModeType.Perspective)
600             {
601                 Radian sourceFieldOfView = sourceCamera.FieldOfView;
602                 Radian destinationFieldOfView = destinationCamera.FieldOfView;
603
604                 // If ProjectionDirection is not equal, match the value.
605                 if (sourceCamera.ProjectionDirection != destinationCamera.ProjectionDirection)
606                 {
607                     float aspect = destinationCamera.AspectRatio;
608                     if (destinationCamera.ProjectionDirection == Camera.ProjectionDirectionType.Vertical)
609                     {
610                         sourceFieldOfView = Camera.ConvertFovFromHorizontalToVertical(aspect, sourceFieldOfView);
611                     }
612                     else
613                     {
614                         sourceFieldOfView = Camera.ConvertFovFromVerticalToHorizontal(aspect, sourceFieldOfView);
615                     }
616                 }
617
618                 KeyFrames fieldOfViewKeyFrames = new KeyFrames();
619                 fieldOfViewKeyFrames.Add(0.0f, sourceFieldOfView.ConvertToFloat());
620                 fieldOfViewKeyFrames.Add(1.0f, destinationFieldOfView.ConvertToFloat());
621                 cameraTransition.AnimateBetween(destinationCamera, "FieldOfView", fieldOfViewKeyFrames, Animation.Interpolation.Linear, alphaFunction);
622
623                 sourceFieldOfView.Dispose();
624                 destinationFieldOfView.Dispose();
625                 fieldOfViewKeyFrames.Dispose();
626             }
627             else
628             {
629                 float sourceOrthographicSize = sourceCamera.OrthographicSize;
630                 float destinationOrthographicSize = destinationCamera.OrthographicSize;
631
632                 // If ProjectionDirection is not equal, match the value.
633                 if (sourceCamera.ProjectionDirection != destinationCamera.ProjectionDirection)
634                 {
635                     float aspect = destinationCamera.AspectRatio;
636                     if (destinationCamera.ProjectionDirection == Camera.ProjectionDirectionType.Vertical)
637                     {
638                         sourceOrthographicSize = sourceOrthographicSize / aspect;
639                     }
640                     else
641                     {
642                         sourceOrthographicSize = sourceOrthographicSize * aspect;
643                     }
644                 }
645
646                 KeyFrames orthographicSizeKeyFrames = new KeyFrames();
647                 orthographicSizeKeyFrames.Add(0.0f, sourceOrthographicSize);
648                 orthographicSizeKeyFrames.Add(1.0f, destinationOrthographicSize);
649                 cameraTransition.AnimateBetween(destinationCamera, "OrthographicSize", orthographicSizeKeyFrames, Animation.Interpolation.Linear, alphaFunction);
650
651                 orthographicSizeKeyFrames.Dispose();
652             }
653
654             float destinationNearPlaneDistance = destinationCamera.NearPlaneDistance;
655             float destinationFarPlaneDistance = destinationCamera.FarPlaneDistance;
656             destinationCamera.NearPlaneDistance = Math.Min(sourceCamera.NearPlaneDistance, destinationCamera.NearPlaneDistance);
657             destinationCamera.FarPlaneDistance = Math.Max(sourceCamera.FarPlaneDistance, destinationCamera.FarPlaneDistance);
658
659             cameraTransition.Finished += (s, e) =>
660             {
661                 this.GetSelectedCamera().NearPlaneDistance = destinationNearPlaneDistance;
662                 this.GetSelectedCamera().FarPlaneDistance = destinationFarPlaneDistance;
663                 inCameraTransition = false;
664                 CameraTransitionFinished?.Invoke(this, EventArgs.Empty);
665             };
666             cameraTransition.Play();
667
668             positionKeyFrames.Dispose();
669             orientationKeyFrames.Dispose();
670         }
671
672         /// <summary>
673         /// Release swigCPtr.
674         /// </summary>
675         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
676         [EditorBrowsable(EditorBrowsableState.Never)]
677         protected override void ReleaseSwigCPtr(global::System.Runtime.InteropServices.HandleRef swigCPtr)
678         {
679             Interop.SceneView.DeleteScene(swigCPtr);
680         }
681     }
682 }