[NUI] Add Skybox in SceneView
[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         /// Set/Get the ImageBasedLight ScaleFactor.
111         /// Scale factor controls light source intensity in [0.0f, 1.0f]
112         /// </summary>
113         /// <since_tizen> 10 </since_tizen>
114         public float ImageBasedLightScaleFactor
115         {
116             set
117             {
118                 SetImageBasedLightScaleFactor(value);
119             }
120             get
121             {
122                 return GetImageBasedLightScaleFactor();
123             }
124         }
125
126         /// <summary>
127         /// Set/Get the UseFramebuffer.
128         /// If this property is true, rendering result of SceneView is drawn on FBO and it is mapping on this SceneView plane.
129         /// If this property is false, each item in SceneView is rendered on window directly.
130         /// Default is false.
131         /// </summary>
132         /// <remarks>
133         /// If UseFramebuffer is true, it could decrease performance but entire rendering order is satisfied.
134         /// If UseFramebuffer is false, the performance becomes better but SceneView is rendered on the top of the other 2D components regardless tree order.
135         /// </remarks>
136         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
137         [EditorBrowsable(EditorBrowsableState.Never)]
138         public bool UseFramebuffer
139         {
140             set
141             {
142                 SetUseFramebuffer(value);
143             }
144             get
145             {
146                 return IsUsingFramebuffer();
147             }
148         }
149
150         /// <summary>
151         /// Set/Get SkyboxUrl.
152         /// If SkyboxUrl is set, the cube map image is loaded and skybox is attached on scene.
153         /// Skybox texture is asynchronously loaded. When loading is finished, ResourcesLoaded is emitted.
154         /// </summary>
155         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
156         [EditorBrowsable(EditorBrowsableState.Never)]
157         public string SkyboxUrl
158         {
159             set
160             {
161                 SetSkybox(value);
162             }
163             get
164             {
165                 return skyboxUrl;
166             }
167         }
168
169         /// <summary>
170         /// Set/Get Skybox intensity.
171         /// The skybox intensity is multiplied to the color of skybox texture.
172         /// Default value is 1.0f.
173         /// </summary>
174         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
175         [EditorBrowsable(EditorBrowsableState.Never)]
176         public float SkyboxIntensity
177         {
178             set
179             {
180                 SetSkyboxIntensity(value);
181             }
182             get
183             {
184                 return GetSkyboxIntensity();
185             }
186         }
187
188         /// <summary>
189         /// Set/Get angle of orientation of the skybox.
190         /// If orientation is set, the skybox will be rotate by the Radian orientation along YAxis.
191         /// Default value is 0.0f.
192         /// </summary>
193         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
194         [EditorBrowsable(EditorBrowsableState.Never)]
195         public Rotation SkyboxOrientation
196         {
197             set
198             {
199                 SetSkyboxOrientation(value);
200             }
201             get
202             {
203                 return GetSkyboxOrientation();
204             }
205         }
206
207         /// <summary>
208         /// Adds a Camera to the SceneView at the end of the camera list of SceneView.
209         /// The Camera can be used as a selected camera to render the scene by using <see cref="SelectCamera(uint)"/> or <see cref="SelectCamera(string)"/>
210         /// </summary>
211         /// <param name="camera">Camera added on this SceneView.</param>
212         /// <remarks>
213         /// Some properties of the Camera will be change depending on the Size of this SceneView.
214         /// Those properties are as follows:
215         /// AspectRatio, LeftPlaneDistance, RightPlaneDistance, TopPlaneDistance, and BottomPlaneDistance.
216         ///
217         /// The FieldOfView of Camera is for vertical fov.
218         /// When the size of the SceneView is changed, the vertical fov is maintained
219         /// and the horizontal fov is automatically calculated according to the SceneView's AspectRatio.
220         /// </remarks>
221         /// <since_tizen> 10 </since_tizen>
222         public void AddCamera(Camera camera)
223         {
224             if(camera != null)
225             {
226                 Interop.SceneView.AddCamera(SwigCPtr, camera.SwigCPtr);
227                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
228             }
229         }
230
231         /// <summary>
232         /// Removes a Camera from this SceneView.
233         /// If removed Camera is selected Camera,
234         /// first camera in the list becomes the selected Camera.
235         /// </summary>
236         /// <param name="camera"> camera Camera to be removed from this Camera.</param>
237         /// <remarks>
238         /// When Camera.Dispose() is called, the NUI object is disposed, but camera information is maintained internally.
239         /// Therefore, even if Camera.Dispose() is called, RemoveCamera() or RemoveCamera() methods can be used.
240         /// If RemoveCamera() is called too, all information is deleted together.
241         /// </remarks>
242         /// <since_tizen> 10 </since_tizen>
243         public void RemoveCamera(Camera camera)
244         {
245             if(camera != null)
246             {
247                 Interop.SceneView.RemoveCamera(SwigCPtr, camera.SwigCPtr);
248                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
249             }
250         }
251
252         /// <summary>
253         /// Retrieves the number of cameras.
254         /// </summary>
255         /// <returns>The number of Cameras.</returns>
256         /// <since_tizen> 10 </since_tizen>
257         public uint GetCameraCount()
258         {
259             uint count = Interop.SceneView.GetCameraCount(SwigCPtr);
260             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
261             return count;
262         }
263
264         /// <summary>
265         /// Retrieves a Camera of the index.
266         /// </summary>
267         /// <param name="index"> Index of Camera to be retrieved.</param>
268         /// <returns>Camera of the index.</returns>
269         /// <since_tizen> 10 </since_tizen>
270         public Camera GetCamera(uint index)
271         {
272             global::System.IntPtr cPtr = Interop.SceneView.GetCamera(SwigCPtr, index);
273             Camera camera = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Camera;
274             if(camera == null)
275             {
276                 // Register new camera into Registry.
277                 camera = new Camera(cPtr, true);
278             }
279             else
280             {
281                 // We found matched NUI camera. Reduce cPtr reference count.
282                 HandleRef handle = new HandleRef(this, cPtr);
283                 Interop.Camera.DeleteCameraProperty(handle);
284                 handle = new HandleRef(null, IntPtr.Zero);
285             }
286             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
287             return camera;
288         }
289
290         /// <summary>
291         /// Retrieves a Camera of the input name.
292         /// </summary>
293         /// <param name="name"> string keyword of Camera to be retrieved.</param>
294         /// <returns>Camera that has the name as a View.Name property</returns>
295         /// <since_tizen> 10 </since_tizen>
296         public Camera GetCamera(string name)
297         {
298             global::System.IntPtr cPtr = Interop.SceneView.GetCamera(SwigCPtr, name);
299             Camera camera = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Camera;
300             if(camera == null)
301             {
302                 // Register new camera into Registry.
303                 camera = new Camera(cPtr, true);
304             }
305             else
306             {
307                 // We found matched NUI camera. Reduce cPtr reference count.
308                 HandleRef handle = new HandleRef(this, cPtr);
309                 Interop.Camera.DeleteCameraProperty(handle);
310                 handle = new HandleRef(null, IntPtr.Zero);
311             }
312             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
313             return camera;
314         }
315
316         /// <summary>
317         /// Makes SceneView use a Camera of index as a selected camera.
318         /// </summary>
319         /// <param name="index"> Index of Camera to be used as a selected camera.</param>
320         /// <since_tizen> 10 </since_tizen>
321         public void SelectCamera(uint index)
322         {
323             if(inCameraTransition)
324             {
325                 return;
326             }
327             Interop.SceneView.SelectCamera(SwigCPtr, index);
328             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
329         }
330
331         /// <summary>
332         /// Makes SceneView use a Camera of a name as a selected camera.
333         /// </summary>
334         /// <param name="name"> string keyword of Camera to be used as a selected camera.</param>
335         /// <since_tizen> 10 </since_tizen>
336         public void SelectCamera(string name)
337         {
338             if(inCameraTransition)
339             {
340                 return;
341             }
342             Interop.SceneView.SelectCamera(SwigCPtr, name);
343             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
344         }
345
346         /// <summary>
347         /// Starts camera transition from currently selected camera to a camera of index.
348         /// Camera Position, Orientation and FieldOfView are smoothly animated.
349         /// </summary>
350         /// <remarks>
351         /// The selected camera is switched when the transition is started.
352         /// During camera transition, Selected Camera cannot be changed by using SelectCamera() or CameraTransition() method.
353         /// </remarks>
354         /// <param name="index"> Index of destination Camera of Camera transition.</param>
355         /// <param name="durationMilliSeconds">The duration in milliseconds.</param>
356         /// <param name="alphaFunction">The alpha function to apply.</param>
357         /// <since_tizen> 10 </since_tizen>
358         public void CameraTransition(uint index, int durationMilliSeconds, AlphaFunction alphaFunction = null)
359         {
360             if(inCameraTransition)
361             {
362                 return;
363             }
364             Camera source = GetSelectedCamera();
365             SelectCamera(index);
366             Camera destination = GetSelectedCamera();
367             CameraTransition(source, destination, durationMilliSeconds, alphaFunction);
368             source.Dispose();
369             destination.Dispose();
370         }
371
372         /// <summary>
373         /// Starts camera transition from currently selected camera to a camera of input name.
374         /// Camera Position, Orientation and FieldOfView are smoothly animated.
375         /// </summary>
376         /// <remarks>
377         /// The selected camera is switched when the transition is started.
378         /// During camera transition, Selected Camera cannot be changed by using SelectCamera() or CameraTransition() method.
379         /// </remarks>
380         /// <param name="name"> string keyword of destination Camera of Camera transition.</param>
381         /// <param name="durationMilliSeconds">The duration in milliseconds.</param>
382         /// <param name="alphaFunction">The alpha function to apply.</param>
383         /// <since_tizen> 10 </since_tizen>
384         public void CameraTransition(string name, int durationMilliSeconds, AlphaFunction alphaFunction = null)
385         {
386             if(inCameraTransition)
387             {
388                 return;
389             }
390             Camera source = GetSelectedCamera();
391             SelectCamera(name);
392             Camera destination = GetSelectedCamera();
393             CameraTransition(source, destination, durationMilliSeconds, alphaFunction);
394             source.Dispose();
395             destination.Dispose();
396         }
397
398         /// <summary>
399         /// Retrieves selected Camera.
400         /// </summary>
401         /// <returns> Camera currently used in SceneView as a selected Camera.</returns>
402         /// <since_tizen> 10 </since_tizen>
403         public Camera GetSelectedCamera()
404         {
405             global::System.IntPtr cPtr = Interop.SceneView.GetSelectedCamera(SwigCPtr);
406             Camera camera = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Camera;
407             if(camera == null)
408             {
409                 // Register new camera into Registry.
410                 camera = new Camera(cPtr, true);
411             }
412             else
413             {
414                 // We found matched NUI camera. Reduce cPtr reference count.
415                 HandleRef handle = new HandleRef(this, cPtr);
416                 Interop.Camera.DeleteCameraProperty(handle);
417                 handle = new HandleRef(null, IntPtr.Zero);
418             }
419             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
420             return camera;
421         }
422
423         /// <summary>
424         /// Changes Image Based Light as the input textures.
425         /// </summary>
426         /// <param name="diffuseUrl">The path of Cube map image that can be used as a diffuse IBL source.</param>
427         /// <param name="specularUrl">The path of Cube map image that can be used as a specular IBL source.</param>
428         /// <param name="scaleFactor">Scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f.</param>
429         /// <remarks>
430         /// http://tizen.org/privilege/mediastorage for local files in media storage.
431         /// http://tizen.org/privilege/externalstorage for local files in external storage.
432         /// </remarks>
433         /// <since_tizen> 10 </since_tizen>
434         public void SetImageBasedLightSource(string diffuseUrl, string specularUrl, float scaleFactor = 1.0f)
435         {
436             Interop.SceneView.SetImageBasedLightSource(SwigCPtr, diffuseUrl, specularUrl, scaleFactor);
437             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
438         }
439
440         internal void SetUseFramebuffer(bool useFramebuffer)
441         {
442             Interop.SceneView.UseFramebuffer(SwigCPtr, useFramebuffer);
443             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
444         }
445
446         internal bool IsUsingFramebuffer()
447         {
448             bool result = Interop.SceneView.IsUsingFramebuffer(SwigCPtr);
449             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
450             return result;
451         }
452
453         /// <summary>
454         /// Set the ImageBasedLight ScaleFactor.
455         /// </summary>
456         /// <param name="scaleFactor">Scale factor that controls light source intensity in [0.0f, 1.0f].</param>
457         private void SetImageBasedLightScaleFactor(float scaleFactor)
458         {
459             Interop.SceneView.SetImageBasedLightScaleFactor(SwigCPtr, scaleFactor);
460             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
461         }
462
463         /// <summary>
464         /// Get the ImageBasedLight ScaleFactor.
465         /// </summary>
466         /// <returns>ImageBasedLightScaleFactor that controls light source intensity.</returns>
467         private float GetImageBasedLightScaleFactor()
468         {
469             float scaleFactor = Interop.SceneView.GetImageBasedLightScaleFactor(SwigCPtr);
470             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
471             return scaleFactor;
472         }
473
474         /// <summary>
475         /// Set the Skybox from cube map image.
476         /// Skybox texture is asynchronously loaded. When loading is finished, ResourcesLoaded is emitted.
477         /// </summary>
478         /// <param name="skyboxUrl">Cube map image url for skybox.</param>
479         private void SetSkybox(string skyboxUrl)
480         {
481             this.skyboxUrl = skyboxUrl;
482             Interop.SceneView.SetSkybox(SwigCPtr, skyboxUrl);
483             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
484         }
485
486         /// <summary>
487         /// Sets Skybox intensity.
488         /// The skybox intensity is multiplied to the color of skybox texture.
489         /// Default value is 1.0f.
490         /// </summary>
491         /// <param name="intensity">Intensity value to be multiplied to the cube map color.</param>
492         private void SetSkyboxIntensity(float intensity)
493         {
494             Interop.SceneView.SetSkyboxIntensity(SwigCPtr, intensity);
495             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
496         }
497
498         /// <summary>
499         /// Gets Skybox intensity.
500         /// Default value is 1.0f.
501         /// </summary>
502         /// <returns>skybox intensity.</returns>
503         private float GetSkyboxIntensity()
504         {
505             float intensity = Interop.SceneView.GetSkyboxIntensity(SwigCPtr);
506             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
507             return intensity;
508         }
509
510         /// <summary>
511         /// Sets orientation of the skybox.
512         /// </summary>
513         /// <param name="orientation">Rotation angle of the skybox along YAxis.</param>
514         private void SetSkyboxOrientation(Rotation orientation)
515         {
516             Interop.SceneView.SetSkyboxOrientation(SwigCPtr, Rotation.getCPtr(orientation));
517             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
518         }
519
520         /// <summary>
521         /// Gets Skybox orientation.
522         /// </summary>
523         /// <returns>skybox orientation.</returns>
524         private Rotation GetSkyboxOrientation()
525         {
526             global::System.IntPtr cPtr = Interop.SceneView.GetSkyboxOrientation(SwigCPtr);
527             Rotation ret = (cPtr == global::System.IntPtr.Zero) ? null : new Rotation(cPtr, false);
528             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
529             return ret;
530         }
531
532         private void CameraTransition(Camera sourceCamera, Camera destinationCamera, int durationMilliSeconds, AlphaFunction alphaFunction)
533         {
534             inCameraTransition = true;
535
536             Position sourcePosition = sourceCamera.Position;
537             Rotation sourceOrientation = sourceCamera.Orientation;
538             Radian   sourceFieldOfView = sourceCamera.FieldOfView;
539
540             Position destinationPosition = destinationCamera.Position;
541             Rotation destinationOrientation = destinationCamera.Orientation;
542             Radian   destinationFieldOfView = destinationCamera.FieldOfView;
543
544             // If ProjectionDirection is not equal, match the value.
545             if (sourceCamera.ProjectionDirection != destinationCamera.ProjectionDirection)
546             {
547                 float aspect = destinationCamera.AspectRatio;
548                 if (destinationCamera.ProjectionDirection == Camera.ProjectionDirectionType.Vertical)
549                 {
550                     sourceFieldOfView = Camera.ConvertFovFromHorizontalToVertical(aspect, sourceFieldOfView);
551                 }
552                 else
553                 {
554                     sourceFieldOfView = Camera.ConvertFovFromVerticalToHorizontal(aspect, sourceFieldOfView);
555                 }
556             }
557
558             cameraTransition = new Animation(durationMilliSeconds);
559
560             KeyFrames positionKeyFrames = new KeyFrames();
561             positionKeyFrames.Add(0.0f, sourcePosition);
562             positionKeyFrames.Add(1.0f, destinationPosition);
563
564             KeyFrames orientationKeyFrames = new KeyFrames();
565             orientationKeyFrames.Add(0.0f, sourceOrientation);
566             orientationKeyFrames.Add(1.0f, destinationOrientation);
567
568             KeyFrames fieldOfViewKeyFrames = new KeyFrames();
569             fieldOfViewKeyFrames.Add(0.0f, sourceFieldOfView.ConvertToFloat());
570             fieldOfViewKeyFrames.Add(1.0f, destinationFieldOfView.ConvertToFloat());
571
572             cameraTransition.AnimateBetween(destinationCamera, "Position", positionKeyFrames, Animation.Interpolation.Linear, alphaFunction);
573             cameraTransition.AnimateBetween(destinationCamera, "Orientation", orientationKeyFrames, Animation.Interpolation.Linear, alphaFunction);
574             cameraTransition.AnimateBetween(destinationCamera, "FieldOfView", fieldOfViewKeyFrames, Animation.Interpolation.Linear, alphaFunction);
575
576             cameraTransition.Finished += (s, e) =>
577             {
578                 inCameraTransition = false;
579             };
580             cameraTransition.Play();
581
582             sourceFieldOfView.Dispose();
583             positionKeyFrames.Dispose();
584             orientationKeyFrames.Dispose();
585             orientationKeyFrames.Dispose();
586         }
587
588         /// <summary>
589         /// Release swigCPtr.
590         /// </summary>
591         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
592         [EditorBrowsable(EditorBrowsableState.Never)]
593         protected override void ReleaseSwigCPtr(global::System.Runtime.InteropServices.HandleRef swigCPtr)
594         {
595             Interop.SceneView.DeleteScene(swigCPtr);
596         }
597     }
598 }