[NUI] Add SetResolution method to 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 System.Diagnostics.CodeAnalysis;
22 using Tizen.NUI;
23 using Tizen.NUI.Binding;
24 using Tizen.NUI.BaseComponents;
25
26 namespace Tizen.NUI.Scene3D
27 {
28     /// <summary>
29     /// SceneView is a Class to show multiple 3D objects in a single 2D screen.
30     /// Each SceneView has its own 3D space, and 3D objects added to SceneView are positioned in the space.
31     /// SceneView uses left-handed coordinate system same as NUI. X as right, Y as down, and Z as forward.
32     ///
33     /// SceneView has internal root container to control inner rendering process like depth test.
34     /// When a View is added to the SceneView with <see cref="View.Add(View)"/> method, it is actually added on the root container.
35     /// Therefore, the added Views exist in the sub tree of SceneView, but are not direct children.
36     /// The sub tree of Views will be rendered with the SceneView's own Camera.
37     ///
38     /// SceneView has one built-in camera by default.
39     /// The default Camera is not removed by using <see cref="RemoveCamera(Camera)"/> method.
40     /// <see cref="GetCamera(uint)"/> method with index "0" returns the default camera,
41     /// and the minimum value returned by <see cref="GetCameraCount()"/> method is 1.
42     ///
43     /// SceneView also provides multiple Camera and one of them can be used to render multiple objects.
44     /// <see cref="AddCamera(Camera)"/>, <see cref="RemoveCamera(Camera)"/>, <see cref="GetCamera(uint)"/>,
45     /// and <see cref="SelectCamera(uint)"/> are methods to manage Cameras of the SceneView.
46     /// User can place multiple cameras in a scene to display the entire scene or to display individual objects.
47     /// User can use the <see cref="SelectCamera(uint)"/> method to select the currently required camera.
48     ///
49     /// When the SceneView's size changes, some camera properties that depend on its size may also change.
50     /// The changing properties are as follows: AspectRatio, LeftPlaneDistance, RightPlaneDistance, TopPlaneDistance, and BottomPlaneDistance.
51     /// The Camera's FieldOfView is vertical fov. The horizontal fov is updated internally according to the SceneView size.
52     ///
53     /// The <see cref="SetImageBasedLightSource(string, string, float)"/> method sets the same IBL to all Model objects added to the SceneView.
54     /// For the IBL, two cube map textures(diffuse and specular) are required.
55     /// SceneView supports 4 types layout for Cube Map: Vertical/Horizontal Cross layouts, and Vertical/Horizontal Array layouts.
56     /// And also, ktx format with cube map is supported.
57     /// If a model already has an IBL, it is batch overridden with the IBL of the SceneView.
58     /// If the SceneView has IBL, the IBL of newly added models is also overridden.
59     ///
60     /// The IBL textures start to be loaded asynchronously when <see cref="SetImageBasedLightSource(string, string, float)"/> method is called.
61     /// ResourcesLoaded signal notifies that the loading of the IBL resources have been completed.
62     ///
63     /// If FBO is used, the rendering result of SceneView is drawn on the FBO and it is mapped on the plane of the SceneView.
64     /// It could decreases performance slightly, but it is useful to show SceneView according to the rendering order with other Views.
65     ///
66     /// And since SceneView is a View, it can be placed together with other 2D UI components in the NUI window.
67     /// </summary>
68     /// <since_tizen> 10 </since_tizen>
69     public class SceneView : View
70     {
71         private bool inCameraTransition = false;
72         private Animation cameraTransition;
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         /// Adds a Camera to the SceneView at the end of the camera list of SceneView.
181         /// The Camera can be used as a selected camera to render the scene by using <see cref="SelectCamera(uint)"/> or <see cref="SelectCamera(string)"/>
182         /// </summary>
183         /// <param name="camera">Camera added on this SceneView.</param>
184         /// <remarks>
185         /// Some properties of the Camera will be change depending on the Size of this SceneView.
186         /// Those properties are as follows:
187         /// AspectRatio, LeftPlaneDistance, RightPlaneDistance, TopPlaneDistance, and BottomPlaneDistance.
188         ///
189         /// The FieldOfView of Camera is for vertical fov.
190         /// When the size of the SceneView is changed, the vertical fov is maintained
191         /// and the horizontal fov is automatically calculated according to the SceneView's AspectRatio.
192         /// </remarks>
193         /// <since_tizen> 10 </since_tizen>
194         public void AddCamera(Camera camera)
195         {
196             if(camera != null)
197             {
198                 Interop.SceneView.AddCamera(SwigCPtr, camera.SwigCPtr);
199                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
200             }
201         }
202
203         /// <summary>
204         /// Removes a Camera from this SceneView.
205         /// If removed Camera is selected Camera,
206         /// first camera in the list becomes the selected Camera.
207         /// </summary>
208         /// <param name="camera"> camera Camera to be removed from this Camera.</param>
209         /// <remarks>
210         /// When Camera.Dispose() is called, the NUI object is disposed, but camera information is maintained internally.
211         /// Therefore, even if Camera.Dispose() is called, RemoveCamera() or RemoveCamera() methods can be used.
212         /// If RemoveCamera() is called too, all information is deleted together.
213         /// </remarks>
214         /// <since_tizen> 10 </since_tizen>
215         public void RemoveCamera(Camera camera)
216         {
217             if(camera != null)
218             {
219                 Interop.SceneView.RemoveCamera(SwigCPtr, camera.SwigCPtr);
220                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
221             }
222         }
223
224         /// <summary>
225         /// Retrieves the number of cameras.
226         /// </summary>
227         /// <returns>The number of Cameras.</returns>
228         /// <since_tizen> 10 </since_tizen>
229         public uint GetCameraCount()
230         {
231             uint count = Interop.SceneView.GetCameraCount(SwigCPtr);
232             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
233             return count;
234         }
235
236         /// <summary>
237         /// Retrieves a Camera of the index.
238         /// </summary>
239         /// <param name="index"> Index of Camera to be retrieved.</param>
240         /// <returns>Camera of the index.</returns>
241         /// <since_tizen> 10 </since_tizen>
242         public Camera GetCamera(uint index)
243         {
244             global::System.IntPtr cPtr = Interop.SceneView.GetCamera(SwigCPtr, index);
245             Camera camera = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Camera;
246             if(camera == null)
247             {
248                 // Register new camera into Registry.
249                 camera = new Camera(cPtr, true);
250             }
251             else
252             {
253                 // We found matched NUI camera. Reduce cPtr reference count.
254                 HandleRef handle = new HandleRef(this, cPtr);
255                 Interop.Camera.DeleteCameraProperty(handle);
256                 handle = new HandleRef(null, IntPtr.Zero);
257             }
258             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
259             return camera;
260         }
261
262         /// <summary>
263         /// Retrieves a Camera of the input name.
264         /// </summary>
265         /// <param name="name"> string keyword of Camera to be retrieved.</param>
266         /// <returns>Camera that has the name as a View.Name property</returns>
267         /// <since_tizen> 10 </since_tizen>
268         public Camera GetCamera(string name)
269         {
270             global::System.IntPtr cPtr = Interop.SceneView.GetCamera(SwigCPtr, name);
271             Camera camera = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Camera;
272             if(camera == null)
273             {
274                 // Register new camera into Registry.
275                 camera = new Camera(cPtr, true);
276             }
277             else
278             {
279                 // We found matched NUI camera. Reduce cPtr reference count.
280                 HandleRef handle = new HandleRef(this, cPtr);
281                 Interop.Camera.DeleteCameraProperty(handle);
282                 handle = new HandleRef(null, IntPtr.Zero);
283             }
284             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
285             return camera;
286         }
287
288         /// <summary>
289         /// Makes SceneView use a Camera of index as a selected camera.
290         /// </summary>
291         /// <param name="index"> Index of Camera to be used as a selected camera.</param>
292         /// <since_tizen> 10 </since_tizen>
293         public void SelectCamera(uint index)
294         {
295             if(inCameraTransition)
296             {
297                 return;
298             }
299             Interop.SceneView.SelectCamera(SwigCPtr, index);
300             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
301         }
302
303         /// <summary>
304         /// Makes SceneView use a Camera of a name as a selected camera.
305         /// </summary>
306         /// <param name="name"> string keyword of Camera to be used as a selected camera.</param>
307         /// <since_tizen> 10 </since_tizen>
308         public void SelectCamera(string name)
309         {
310             if(inCameraTransition)
311             {
312                 return;
313             }
314             Interop.SceneView.SelectCamera(SwigCPtr, name);
315             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
316         }
317
318         /// <summary>
319         /// Starts camera transition from currently selected camera to a camera of index.
320         /// Camera Position, Orientation and FieldOfView are smoothly animated.
321         /// </summary>
322         /// <remarks>
323         /// The selected camera is switched to the Camera of the index when the transition is started.
324         /// During camera transition, Selected Camera should not be changed by using SelectCamera() or CameraTransition() method.
325         /// During camera transition, Camera properties of Selected Camera should not be changed.
326         /// </remarks>
327         /// <param name="index"> Index of destination Camera of Camera transition.</param>
328         /// <param name="durationMilliSeconds">The duration in milliseconds.</param>
329         /// <param name="alphaFunction">The alpha function to apply.</param>
330         /// <since_tizen> 10 </since_tizen>
331         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "The ownership of camera object is not owned by this class.")]
332         public void CameraTransition(uint index, int durationMilliSeconds, AlphaFunction alphaFunction = null)
333         {
334             if(inCameraTransition || GetSelectedCamera() == GetCamera(index))
335             {
336                 return;
337             }
338             Camera source = GetSelectedCamera();
339             SelectCamera(index);
340             Camera destination = GetSelectedCamera();
341             CameraTransition(source, destination, durationMilliSeconds, alphaFunction);
342         }
343
344         /// <summary>
345         /// Starts camera transition from currently selected camera to a camera of input name.
346         /// Camera Position, Orientation and FieldOfView are smoothly animated.
347         /// </summary>
348         /// <remarks>
349         /// The selected camera is switched to the Camera of the input name when the transition is started.
350         /// During camera transition, Selected Camera should not be changed by using SelectCamera() or CameraTransition() method.
351         /// During camera transition, Camera properties of Selected Camera should not be changed.
352         /// </remarks>
353         /// <param name="name"> string keyword of destination Camera of Camera transition.</param>
354         /// <param name="durationMilliSeconds">The duration in milliseconds.</param>
355         /// <param name="alphaFunction">The alpha function to apply.</param>
356         /// <since_tizen> 10 </since_tizen>
357         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "The ownership of camera object is not owned by this class.")]
358         public void CameraTransition(string name, int durationMilliSeconds, AlphaFunction alphaFunction = null)
359         {
360             if(inCameraTransition || GetSelectedCamera() == GetCamera(name))
361             {
362                 return;
363             }
364             Camera source = GetSelectedCamera();
365             SelectCamera(name);
366             Camera destination = GetSelectedCamera();
367             CameraTransition(source, destination, durationMilliSeconds, alphaFunction);
368         }
369
370         /// <summary>
371         /// Retrieves selected Camera.
372         /// </summary>
373         /// <returns> Camera currently used in SceneView as a selected Camera.</returns>
374         /// <since_tizen> 10 </since_tizen>
375         public Camera GetSelectedCamera()
376         {
377             global::System.IntPtr cPtr = Interop.SceneView.GetSelectedCamera(SwigCPtr);
378             Camera camera = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Camera;
379             if(camera == null)
380             {
381                 // Register new camera into Registry.
382                 camera = new Camera(cPtr, true);
383             }
384             else
385             {
386                 // We found matched NUI camera. Reduce cPtr reference count.
387                 HandleRef handle = new HandleRef(this, cPtr);
388                 Interop.Camera.DeleteCameraProperty(handle);
389                 handle = new HandleRef(null, IntPtr.Zero);
390             }
391             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
392             return camera;
393         }
394
395         /// <summary>
396         /// Changes Image Based Light as the input textures.
397         /// </summary>
398         /// <param name="diffuseUrl">The path of Cube map image that can be used as a diffuse IBL source.</param>
399         /// <param name="specularUrl">The path of Cube map image that can be used as a specular IBL source.</param>
400         /// <param name="scaleFactor">Scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f.</param>
401         /// <remarks>
402         /// http://tizen.org/privilege/mediastorage for local files in media storage.
403         /// http://tizen.org/privilege/externalstorage for local files in external storage.
404         /// </remarks>
405         /// <since_tizen> 10 </since_tizen>
406         public void SetImageBasedLightSource(string diffuseUrl, string specularUrl, float scaleFactor = 1.0f)
407         {
408             Interop.SceneView.SetImageBasedLightSource(SwigCPtr, diffuseUrl, specularUrl, scaleFactor);
409             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
410         }
411
412         /// <summary>
413         /// Sets SceneView's resolution manually.
414         /// </summary>
415         /// <param name="width">The input width.</param>
416         /// <param name="height">The input height.</param>
417         /// <remarks>
418         /// This manual resolution is only available when the SceneView uses FBO for rendering by using FBO (UseFrameBuffer is true).
419         /// If the aspect ratio of input width/height is different with SceneView's aspect ratio, the rendered result is stretched to fill SceneView's area.
420         /// </remarks>
421         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
422         [EditorBrowsable(EditorBrowsableState.Never)]
423         public void SetResolution(uint width, uint height)
424         {
425             Interop.SceneView.SetResolution(SwigCPtr, width, height);
426             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
427         }
428
429         /// <summary>
430         /// Retrieves width of resolution of the SceneView.
431         /// </summary>
432         /// <remarks>
433         ///  If the SceneView not uses FBO, this method returns SceneView's width.
434         /// </remarks>
435         /// <returns> Camera currently used in SceneView as a selected Camera.</returns>
436         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
437         [EditorBrowsable(EditorBrowsableState.Never)]
438         public uint GetResolutionWidth()
439         {
440             uint result = Interop.SceneView.GetResolutionWidth(SwigCPtr);
441             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
442             return result;
443         }
444
445         /// <summary>
446         /// Retrieves height of resolution of the SceneView.
447         /// </summary>
448         /// <remarks>
449         ///  If the SceneView not uses FBO, this method returns SceneView's height.
450         /// </remarks>
451         /// <returns> Camera currently used in SceneView as a selected Camera.</returns>
452         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
453         [EditorBrowsable(EditorBrowsableState.Never)]
454         public uint GetResolutionHeight()
455         {
456             uint result = Interop.SceneView.GetResolutionHeight(SwigCPtr);
457             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
458             return result;
459         }
460
461         /// <summary>
462         /// Resets SceneView's resolution to the current size of SceneView.
463         /// </summary>
464         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
465         [EditorBrowsable(EditorBrowsableState.Never)]
466         public void ResetResolution()
467         {
468             Interop.SceneView.ResetResolution(SwigCPtr);
469             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
470         }
471
472         internal void SetUseFramebuffer(bool useFramebuffer)
473         {
474             Interop.SceneView.UseFramebuffer(SwigCPtr, useFramebuffer);
475             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
476         }
477
478         internal bool IsUsingFramebuffer()
479         {
480             bool result = Interop.SceneView.IsUsingFramebuffer(SwigCPtr);
481             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
482             return result;
483         }
484
485         internal void SetFramebufferMultiSamplingLevel(uint multiSamplingLevel)
486         {
487             Interop.SceneView.SetFramebufferMultiSamplingLevel(SwigCPtr, multiSamplingLevel);
488             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
489         }
490
491         internal uint GetFramebufferMultiSamplingLevel()
492         {
493             uint result = Interop.SceneView.GetFramebufferMultiSamplingLevel(SwigCPtr);
494             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
495             return result;
496         }
497
498         /// <summary>
499         /// Set the ImageBasedLight ScaleFactor.
500         /// </summary>
501         /// <param name="scaleFactor">Scale factor that controls light source intensity in [0.0f, 1.0f].</param>
502         private void SetImageBasedLightScaleFactor(float scaleFactor)
503         {
504             Interop.SceneView.SetImageBasedLightScaleFactor(SwigCPtr, scaleFactor);
505             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
506         }
507
508         /// <summary>
509         /// Get the ImageBasedLight ScaleFactor.
510         /// </summary>
511         /// <returns>ImageBasedLightScaleFactor that controls light source intensity.</returns>
512         private float GetImageBasedLightScaleFactor()
513         {
514             float scaleFactor = Interop.SceneView.GetImageBasedLightScaleFactor(SwigCPtr);
515             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
516             return scaleFactor;
517         }
518
519         private void CameraTransition(Camera sourceCamera, Camera destinationCamera, int durationMilliSeconds, AlphaFunction alphaFunction)
520         {
521             inCameraTransition = true;
522
523             Position sourcePosition = sourceCamera.Position;
524             Rotation sourceOrientation = sourceCamera.Orientation;
525
526             Position destinationPosition = destinationCamera.Position;
527             Rotation destinationOrientation = destinationCamera.Orientation;
528
529             cameraTransition = new Animation(durationMilliSeconds);
530
531             KeyFrames positionKeyFrames = new KeyFrames();
532             positionKeyFrames.Add(0.0f, sourcePosition);
533             positionKeyFrames.Add(1.0f, destinationPosition);
534
535             KeyFrames orientationKeyFrames = new KeyFrames();
536             orientationKeyFrames.Add(0.0f, sourceOrientation);
537             orientationKeyFrames.Add(1.0f, destinationOrientation);
538
539             cameraTransition.AnimateBetween(destinationCamera, "Position", positionKeyFrames, Animation.Interpolation.Linear, alphaFunction);
540             cameraTransition.AnimateBetween(destinationCamera, "Orientation", orientationKeyFrames, Animation.Interpolation.Linear, alphaFunction);
541
542             if(destinationCamera.ProjectionMode == Camera.ProjectionModeType.Perspective)
543             {
544                 Radian sourceFieldOfView = sourceCamera.FieldOfView;
545                 Radian destinationFieldOfView = destinationCamera.FieldOfView;
546
547                 // If ProjectionDirection is not equal, match the value.
548                 if (sourceCamera.ProjectionDirection != destinationCamera.ProjectionDirection)
549                 {
550                     float aspect = destinationCamera.AspectRatio;
551                     if (destinationCamera.ProjectionDirection == Camera.ProjectionDirectionType.Vertical)
552                     {
553                         Camera.ConvertFovFromHorizontalToVertical(aspect, ref sourceFieldOfView);
554                     }
555                     else
556                     {
557                         Camera.ConvertFovFromVerticalToHorizontal(aspect, ref sourceFieldOfView);
558                     }
559                 }
560
561                 KeyFrames fieldOfViewKeyFrames = new KeyFrames();
562                 fieldOfViewKeyFrames.Add(0.0f, sourceFieldOfView.ConvertToFloat());
563                 fieldOfViewKeyFrames.Add(1.0f, destinationFieldOfView.ConvertToFloat());
564                 cameraTransition.AnimateBetween(destinationCamera, "FieldOfView", fieldOfViewKeyFrames, Animation.Interpolation.Linear, alphaFunction);
565
566                 sourceFieldOfView.Dispose();
567                 destinationFieldOfView.Dispose();
568                 fieldOfViewKeyFrames.Dispose();
569             }
570             else
571             {
572                 float sourceOrthographicSize = sourceCamera.OrthographicSize;
573                 float destinationOrthographicSize = destinationCamera.OrthographicSize;
574
575                 // If ProjectionDirection is not equal, match the value.
576                 if (sourceCamera.ProjectionDirection != destinationCamera.ProjectionDirection)
577                 {
578                     float aspect = destinationCamera.AspectRatio;
579                     if (destinationCamera.ProjectionDirection == Camera.ProjectionDirectionType.Vertical)
580                     {
581                         sourceOrthographicSize = sourceOrthographicSize / aspect;
582                     }
583                     else
584                     {
585                         sourceOrthographicSize = sourceOrthographicSize * aspect;
586                     }
587                 }
588
589                 KeyFrames orthographicSizeKeyFrames = new KeyFrames();
590                 orthographicSizeKeyFrames.Add(0.0f, sourceOrthographicSize);
591                 orthographicSizeKeyFrames.Add(1.0f, destinationOrthographicSize);
592                 cameraTransition.AnimateBetween(destinationCamera, "OrthographicSize", orthographicSizeKeyFrames, Animation.Interpolation.Linear, alphaFunction);
593
594                 orthographicSizeKeyFrames.Dispose();
595             }
596
597             float destinationNearPlaneDistance = destinationCamera.NearPlaneDistance;
598             float destinationFarPlaneDistance = destinationCamera.FarPlaneDistance;
599             destinationCamera.NearPlaneDistance = Math.Min(sourceCamera.NearPlaneDistance, destinationCamera.NearPlaneDistance);
600             destinationCamera.FarPlaneDistance = Math.Max(sourceCamera.FarPlaneDistance, destinationCamera.FarPlaneDistance);
601
602             cameraTransition.Finished += (s, e) =>
603             {
604                 this.GetSelectedCamera().NearPlaneDistance = destinationNearPlaneDistance;
605                 this.GetSelectedCamera().FarPlaneDistance = destinationFarPlaneDistance;
606                 inCameraTransition = false;
607                 CameraTransitionFinished?.Invoke(this, EventArgs.Empty);
608             };
609             cameraTransition.Play();
610
611             positionKeyFrames.Dispose();
612             orientationKeyFrames.Dispose();
613         }
614
615         /// <summary>
616         /// Release swigCPtr.
617         /// </summary>
618         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
619         [EditorBrowsable(EditorBrowsableState.Never)]
620         protected override void ReleaseSwigCPtr(global::System.Runtime.InteropServices.HandleRef swigCPtr)
621         {
622             Interop.SceneView.DeleteScene(swigCPtr);
623         }
624     }
625 }