SceneCamera.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. using bs;
  4. namespace bs.Editor
  5. {
  6. /** @addtogroup Scene-Editor
  7. * @{
  8. */
  9. /// <summary>
  10. /// Handles camera movement in the scene view.
  11. /// </summary>
  12. [RunInEditor]
  13. internal sealed class SceneCamera : ManagedComponent
  14. {
  15. #region Constants
  16. public const float StartSpeed = 4.0f;
  17. public const float TopSpeed = 12.0f;
  18. public const string MoveForwardBinding = "SceneForward";
  19. public const string MoveLeftBinding = "SceneLeft";
  20. public const string MoveRightBinding = "SceneRight";
  21. public const string MoveBackBinding = "SceneBackward";
  22. public const string MoveUpBinding = "SceneUp";
  23. public const string MoveDownBinding = "SceneDown";
  24. public const string FastMoveBinding = "SceneFastMove";
  25. public const string PanBinding = "ScenePan";
  26. public const string RotateBinding = "SceneRotate";
  27. public const string HorizontalAxisBinding = "SceneHorizontal";
  28. public const string VerticalAxisBinding = "SceneVertical";
  29. public const string ScrollAxisBinding = "SceneScroll";
  30. public const string ViewSettingsKey = "SceneCamera0_ViewSettings";
  31. public const string MoveSettingsKey = "SceneCamera0_MoveSettings";
  32. public const string RenderSettingsKey = "SceneCamera0_RenderSettings";
  33. #endregion
  34. #region Fields
  35. private VirtualButton moveForwardBtn;
  36. private VirtualButton moveLeftBtn;
  37. private VirtualButton moveRightBtn;
  38. private VirtualButton moveBackwardBtn;
  39. private VirtualButton moveUpBtn;
  40. private VirtualButton moveDownBtn;
  41. private VirtualButton fastMoveBtn;
  42. private VirtualButton activeBtn;
  43. private VirtualButton panBtn;
  44. private VirtualAxis horizontalAxis;
  45. private VirtualAxis verticalAxis;
  46. private VirtualAxis scrollAxis;
  47. private float currentSpeed;
  48. private Degree yaw;
  49. private Degree pitch;
  50. private bool lastHideCursorState;
  51. private Camera camera;
  52. private bool inputEnabled = true;
  53. private SceneCameraViewSettings viewSettings;
  54. // Animating camera transitions
  55. private CameraAnimation animation = new CameraAnimation();
  56. private float frustumWidth = 50.0f;
  57. private float lerp;
  58. private bool isAnimating;
  59. #endregion
  60. #region Public properties
  61. /// <summary>
  62. /// Returns the internal camera component. You should not make modifications to the returned camera.
  63. /// </summary>
  64. public Camera Camera { get => camera; }
  65. /// <summary>
  66. /// Settings for controlling scene camera view.
  67. /// </summary>
  68. public SceneCameraViewSettings ViewSettings
  69. {
  70. get => viewSettings;
  71. set
  72. {
  73. viewSettings = value;
  74. camera.ProjectionType = value.projectionType;
  75. camera.NearClipPlane = value.nearClipPlane;
  76. camera.FarClipPlane = value.farClipPlane;
  77. camera.OrthoHeight = value.orthographicSize;
  78. camera.FieldOfView = value.fieldOfView;
  79. camera.Viewport.ClearColor = value.backgroundColor;
  80. NotifyNeedsRedraw();
  81. }
  82. }
  83. /// <summary>
  84. /// Settings for controlling scene camera movement.
  85. /// </summary>
  86. public SceneCameraMoveSettings MoveSettings { get; set; }
  87. /// <summary>
  88. /// Options for controlling scene camera rendering.
  89. /// </summary>
  90. public RenderSettings RenderSettings
  91. {
  92. get => camera.RenderSettings;
  93. set => camera.RenderSettings = value;
  94. }
  95. #endregion
  96. #region Public methods
  97. /// <summary>
  98. /// Changes the scene camera projection type and animates the transition.
  99. /// </summary>
  100. /// <param name="projectionType">New projection type.</param>
  101. public void ChangeProjectionType(ProjectionType projectionType)
  102. {
  103. if (camera.ProjectionType != projectionType)
  104. {
  105. CameraState state = new CameraState();
  106. state.Position = camera.SceneObject.Position;
  107. state.Rotation = camera.SceneObject.Rotation;
  108. state.Orthographic = projectionType == ProjectionType.Orthographic;
  109. state.FrustumWidth = frustumWidth;
  110. viewSettings.projectionType = projectionType;
  111. ProjectSettings.SetObject(ViewSettingsKey, viewSettings);
  112. SetState(state);
  113. }
  114. }
  115. /// <summary>
  116. /// Enables or disables camera controls.
  117. /// </summary>
  118. /// <param name="enable">True to enable controls, false to disable.</param>
  119. public void EnableInput(bool enable)
  120. {
  121. inputEnabled = enable;
  122. }
  123. /// <summary>
  124. /// Focuses the camera on the currently selected object(s).
  125. /// </summary>
  126. public void FrameSelected()
  127. {
  128. SceneObject[] selectedObjects = Selection.SceneObjects;
  129. if (selectedObjects.Length > 0)
  130. {
  131. AABox box = EditorUtility.CalculateBounds(Selection.SceneObjects);
  132. FrameBounds(box);
  133. }
  134. }
  135. /// <summary>
  136. /// Orients the camera so it looks along the provided axis.
  137. /// </summary>
  138. public void LookAlong(Vector3 axis)
  139. {
  140. Vector3 up = Vector3.YAxis;
  141. if (MathEx.Abs(Vector3.Dot(axis, up)) > 0.9f)
  142. up = Vector3.ZAxis;
  143. CameraState state = new CameraState();
  144. state.Position = camera.SceneObject.Position;
  145. state.Rotation = Quaternion.LookRotation(axis, up);
  146. state.Orthographic = camera.ProjectionType == ProjectionType.Orthographic;
  147. state.FrustumWidth = frustumWidth;
  148. SetState(state);
  149. }
  150. /// <summary>
  151. /// Notifies the system that the 3D viewport should be redrawn.
  152. /// </summary>
  153. internal void NotifyNeedsRedraw()
  154. {
  155. camera?.NotifyNeedsRedraw();
  156. }
  157. /// <summary>
  158. /// Enables or disables on-demand drawing. When enabled the 3D viewport will only be redrawn when
  159. /// <see cref="NotifyNeedsRedraw"/> is called. If disabled the viewport will be redrawn every frame.
  160. /// </summary>
  161. /// <param name="enabled">True to enable on-demand drawing, false otherwise.</param>
  162. internal void ToggleOnDemandDrawing(bool enabled)
  163. {
  164. if (camera == null)
  165. return;
  166. if (enabled)
  167. camera.Flags = CameraFlag.OnDemand;
  168. else
  169. camera.Flags = new CameraFlag();
  170. }
  171. #endregion
  172. #region Private methods
  173. private void OnReset()
  174. {
  175. camera = SceneObject.GetComponent<Camera>();
  176. ViewSettings = ProjectSettings.GetObject<SceneCameraViewSettings>(ViewSettingsKey);
  177. MoveSettings = ProjectSettings.GetObject<SceneCameraMoveSettings>(MoveSettingsKey);
  178. RenderSettings = ProjectSettings.GetObject<RenderSettings>(RenderSettingsKey);
  179. moveForwardBtn = new VirtualButton(MoveForwardBinding);
  180. moveLeftBtn = new VirtualButton(MoveLeftBinding);
  181. moveRightBtn = new VirtualButton(MoveRightBinding);
  182. moveBackwardBtn = new VirtualButton(MoveBackBinding);
  183. moveUpBtn = new VirtualButton(MoveUpBinding);
  184. moveDownBtn = new VirtualButton(MoveDownBinding);
  185. fastMoveBtn = new VirtualButton(FastMoveBinding);
  186. activeBtn = new VirtualButton(RotateBinding);
  187. panBtn = new VirtualButton(PanBinding);
  188. horizontalAxis = new VirtualAxis(HorizontalAxisBinding);
  189. verticalAxis = new VirtualAxis(VerticalAxisBinding);
  190. scrollAxis = new VirtualAxis(ScrollAxisBinding);
  191. NotifyNeedsRedraw();
  192. }
  193. private void OnUpdate()
  194. {
  195. bool isOrthographic = camera.ProjectionType == ProjectionType.Orthographic;
  196. float frameDelta = Time.FrameDelta;
  197. if (inputEnabled)
  198. {
  199. bool goingForward = VirtualInput.IsButtonHeld(moveForwardBtn);
  200. bool goingBack = VirtualInput.IsButtonHeld(moveBackwardBtn);
  201. bool goingLeft = VirtualInput.IsButtonHeld(moveLeftBtn);
  202. bool goingRight = VirtualInput.IsButtonHeld(moveRightBtn);
  203. bool goingUp = VirtualInput.IsButtonHeld(moveUpBtn);
  204. bool goingDown = VirtualInput.IsButtonHeld(moveDownBtn);
  205. bool fastMove = VirtualInput.IsButtonHeld(fastMoveBtn);
  206. bool camActive = VirtualInput.IsButtonHeld(activeBtn);
  207. bool isPanning = VirtualInput.IsButtonHeld(panBtn);
  208. bool hideCursor = camActive || isPanning;
  209. if (hideCursor != lastHideCursorState)
  210. {
  211. if (hideCursor)
  212. {
  213. Cursor.Hide();
  214. Rect2I clipRect;
  215. clipRect.x = Input.PointerPosition.x - 2;
  216. clipRect.y = Input.PointerPosition.y - 2;
  217. clipRect.width = 4;
  218. clipRect.height = 4;
  219. Cursor.ClipToRect(clipRect);
  220. }
  221. else
  222. {
  223. Cursor.Show();
  224. Cursor.ClipDisable();
  225. }
  226. lastHideCursorState = hideCursor;
  227. }
  228. if (camActive)
  229. {
  230. float horzValue = VirtualInput.GetAxisValue(horizontalAxis);
  231. float vertValue = VirtualInput.GetAxisValue(verticalAxis);
  232. float rotationAmount = MoveSettings.rotationalSpeed * EditorSettings.MouseSensitivity;
  233. yaw += new Degree(horzValue * rotationAmount);
  234. pitch += new Degree(vertValue * rotationAmount);
  235. yaw = MathEx.WrapAngle(yaw);
  236. pitch = MathEx.WrapAngle(pitch);
  237. Quaternion yRot = Quaternion.FromAxisAngle(Vector3.YAxis, yaw);
  238. Quaternion xRot = Quaternion.FromAxisAngle(Vector3.XAxis, pitch);
  239. Quaternion camRot = yRot * xRot;
  240. camRot.Normalize();
  241. SceneObject.Rotation = camRot;
  242. // Handle movement using movement keys
  243. Vector3 direction = Vector3.Zero;
  244. if (goingForward) direction += SceneObject.Forward;
  245. if (goingBack) direction -= SceneObject.Forward;
  246. if (goingRight) direction += SceneObject.Right;
  247. if (goingLeft) direction -= SceneObject.Right;
  248. if (goingUp) direction += SceneObject.Up;
  249. if (goingDown) direction -= SceneObject.Up;
  250. if (direction.SqrdLength != 0)
  251. {
  252. direction.Normalize();
  253. float multiplier = 1.0f;
  254. if (fastMove)
  255. multiplier = MoveSettings.fastModeMultiplier;
  256. currentSpeed = MathEx.Clamp(currentSpeed + MoveSettings.acceleration * frameDelta, StartSpeed, TopSpeed);
  257. currentSpeed *= multiplier;
  258. }
  259. else
  260. {
  261. currentSpeed = 0.0f;
  262. }
  263. const float tooSmall = 0.0001f;
  264. if (currentSpeed > tooSmall)
  265. {
  266. Vector3 velocity = direction * currentSpeed;
  267. SceneObject.Move(velocity * frameDelta);
  268. }
  269. NotifyNeedsRedraw();
  270. }
  271. // Pan
  272. if (isPanning)
  273. {
  274. float horzValue = VirtualInput.GetAxisValue(horizontalAxis);
  275. float vertValue = VirtualInput.GetAxisValue(verticalAxis);
  276. Vector3 direction = new Vector3(horzValue, -vertValue, 0.0f);
  277. direction = camera.SceneObject.Rotation.Rotate(direction);
  278. SceneObject.Move(direction * MoveSettings.panSpeed * frameDelta);
  279. NotifyNeedsRedraw();
  280. }
  281. }
  282. else
  283. {
  284. if (lastHideCursorState)
  285. {
  286. Cursor.Show();
  287. Cursor.ClipDisable();
  288. lastHideCursorState = false;
  289. }
  290. }
  291. SceneWindow sceneWindow = EditorWindow.GetWindow<SceneWindow>();
  292. if ((sceneWindow.Active && sceneWindow.HasFocus) || sceneWindow.IsPointerHovering)
  293. {
  294. Rect2I bounds = sceneWindow.Bounds;
  295. // Move using scroll wheel
  296. if (bounds.Contains(Input.PointerPosition))
  297. {
  298. float scrollAmount = VirtualInput.GetAxisValue(scrollAxis);
  299. if(scrollAmount != 0)
  300. {
  301. if (!isOrthographic)
  302. {
  303. SceneObject.Move(SceneObject.Forward * scrollAmount * MoveSettings.scrollSpeed * frameDelta);
  304. }
  305. else
  306. {
  307. float oldOrthoHeight = camera.OrthoHeight;
  308. float orthoHeight = MathEx.Max(1.0f, oldOrthoHeight - scrollAmount * frameDelta);
  309. if (oldOrthoHeight != orthoHeight)
  310. camera.OrthoHeight = orthoHeight;
  311. }
  312. NotifyNeedsRedraw();
  313. }
  314. }
  315. }
  316. UpdateAnim();
  317. }
  318. /// <summary>
  319. /// Moves and orients a camera so that the provided bounds end covering the camera's viewport.
  320. /// </summary>
  321. /// <param name="bounds">Bounds to frame in camera's view.</param>
  322. /// <param name="padding">Amount of padding to leave on the borders of the viewport, in percent [0, 1].</param>
  323. private void FrameBounds(AABox bounds, float padding = 0.0f)
  324. {
  325. // TODO - Use AABox bounds directly instead of a sphere to be more accurate
  326. float worldWidth = bounds.Size.Length;
  327. float worldHeight = worldWidth;
  328. if (worldWidth == 0.0f)
  329. worldWidth = 1.0f;
  330. if (worldHeight == 0.0f)
  331. worldHeight = 1.0f;
  332. float boundsAspect = worldWidth / worldHeight;
  333. float paddingScale = MathEx.Clamp01(padding) + 1.0f;
  334. float frustumWidth;
  335. // If camera has wider aspect than bounds then height will be the limiting dimension
  336. if (camera.AspectRatio > boundsAspect)
  337. frustumWidth = worldHeight * camera.AspectRatio * paddingScale;
  338. else // Otherwise width
  339. frustumWidth = worldWidth * paddingScale;
  340. float distance = CalcDistanceForFrustumWidth(frustumWidth);
  341. Vector3 forward = bounds.Center - SceneObject.Position;
  342. forward.Normalize();
  343. GetNearFarForDistance(distance, out var near, out var far);
  344. viewSettings.nearClipPlane = near;
  345. viewSettings.farClipPlane = far;
  346. ProjectSettings.SetObject(ViewSettingsKey, viewSettings);
  347. CameraState state = new CameraState();
  348. state.Position = bounds.Center - forward * distance;
  349. state.Rotation = Quaternion.LookRotation(forward, Vector3.YAxis);
  350. state.Orthographic = camera.ProjectionType == ProjectionType.Orthographic;
  351. state.FrustumWidth = frustumWidth;
  352. SetState(state);
  353. }
  354. /// <summary>
  355. /// Changes the state of the camera, either instantly or animated over several frames. The state includes
  356. /// camera position, rotation, type and possibly other parameters.
  357. /// </summary>
  358. /// <param name="state">New state of the camera.</param>
  359. /// <param name="animated">Should the state be linearly interpolated over a course of several frames.</param>
  360. private void SetState(CameraState state, bool animated = true)
  361. {
  362. CameraState startState = new CameraState();
  363. startState.Position = SceneObject.Position;
  364. startState.Rotation = SceneObject.Rotation;
  365. startState.Orthographic = camera.ProjectionType == ProjectionType.Orthographic;
  366. startState.FrustumWidth = frustumWidth;
  367. animation.Start(startState, state);
  368. if (!animated)
  369. {
  370. ApplyState(1.0f);
  371. isAnimating = false;
  372. }
  373. else
  374. {
  375. isAnimating = true;
  376. lerp = 0.0f;
  377. }
  378. }
  379. /// <summary>
  380. /// Applies the animation target state depending on the interpolation parameter. <see cref="SetState"/>.
  381. /// </summary>
  382. /// <param name="t">Interpolation parameter ranging [0, 1] that interpolated between the start state and the
  383. /// target state.</param>
  384. private void ApplyState(float t)
  385. {
  386. animation.Update(t);
  387. SceneObject.Position = animation.State.Position;
  388. SceneObject.Rotation = animation.State.Rotation;
  389. frustumWidth = animation.State.FrustumWidth;
  390. Vector3 eulerAngles = SceneObject.Rotation.ToEuler();
  391. pitch = (Degree)eulerAngles.x;
  392. yaw = (Degree)eulerAngles.y;
  393. Degree FOV = (Degree)(1.0f - animation.State.OrthographicPct) * viewSettings.fieldOfView;
  394. if (FOV < (Degree)5.0f)
  395. {
  396. camera.ProjectionType = ProjectionType.Orthographic;
  397. camera.OrthoHeight = frustumWidth * 0.5f / camera.AspectRatio;
  398. }
  399. else
  400. {
  401. camera.ProjectionType = ProjectionType.Perspective;
  402. camera.FieldOfView = FOV;
  403. }
  404. // Note: Consider having a global setting for near/far planes as changing it here might confuse the user
  405. float distance = CalcDistanceForFrustumWidth(frustumWidth);
  406. GetNearFarForDistance(distance, out var near, out var far);
  407. camera.NearClipPlane = near;
  408. camera.FarClipPlane = far;
  409. NotifyNeedsRedraw();
  410. }
  411. /// <summary>
  412. /// Calculates distance at which the camera's frustum width is equal to the provided width.
  413. /// </summary>
  414. /// <param name="frustumWidth">Frustum width to find the distance for, in world units.</param>
  415. /// <returns>Distance at which the camera's frustum is the specified width, in world units.</returns>
  416. private float CalcDistanceForFrustumWidth(float frustumWidth)
  417. {
  418. if (camera.ProjectionType == ProjectionType.Perspective)
  419. return (frustumWidth * 0.5f) / MathEx.Tan(camera.FieldOfView * 0.5f);
  420. else
  421. return frustumWidth * 2.0f;
  422. }
  423. /// <summary>
  424. /// Updates camera state transition animation. Should be called every frame.
  425. /// </summary>
  426. private void UpdateAnim()
  427. {
  428. if (!isAnimating)
  429. return;
  430. const float ANIM_TIME = 0.5f; // 0.5f seconds
  431. lerp += Time.FrameDelta * (1.0f / ANIM_TIME);
  432. if (lerp >= 1.0f)
  433. {
  434. lerp = 1.0f;
  435. isAnimating = false;
  436. }
  437. ApplyState(lerp);
  438. }
  439. /// <summary>
  440. /// Calculates the camera near and far plane distances used for looking at an object certain distance from the
  441. /// camera.
  442. /// </summary>
  443. /// <param name="distance">Distance of the object from the camera.</param>
  444. /// <param name="near">Output near plane distance.</param>
  445. /// <param name="far">Output far plane distance.</param>
  446. private static void GetNearFarForDistance(float distance, out float near, out float far)
  447. {
  448. if (distance < 1)
  449. {
  450. near = 0.005f;
  451. far = 1000f;
  452. }
  453. if (distance < 100)
  454. {
  455. near = 0.05f;
  456. far = 2500f;
  457. }
  458. else if (distance < 1000)
  459. {
  460. near = 0.5f;
  461. far = 10000f;
  462. }
  463. else
  464. {
  465. near = 5.0f;
  466. far = 1000000f;
  467. }
  468. }
  469. /// <summary>
  470. /// Contains data for a possible camera state. Camera states can be interpolated between each other as needed.
  471. /// </summary>
  472. private struct CameraState
  473. {
  474. private float _orthographic;
  475. public Vector3 Position { get; set; }
  476. public Quaternion Rotation { get; set; }
  477. public float FrustumWidth { get; set; }
  478. public bool Orthographic
  479. {
  480. get { return _orthographic > 0.5; }
  481. set { _orthographic = value ? 1.0f : 0.0f; }
  482. }
  483. public float OrthographicPct
  484. {
  485. get { return _orthographic; }
  486. set { _orthographic = value; }
  487. }
  488. }
  489. /// <summary>
  490. /// Helper class that performs linear interpolation between two camera states.
  491. /// </summary>
  492. private struct CameraAnimation
  493. {
  494. private CameraState start;
  495. private CameraState target;
  496. private CameraState interpolated;
  497. /// <summary>
  498. /// Returns currently interpolated animation state.
  499. /// </summary>
  500. public CameraState State
  501. {
  502. get { return interpolated; }
  503. }
  504. /// <summary>
  505. /// Initializes the animation with initial and target states.
  506. /// </summary>
  507. /// <param name="start">Initial state to animate from.</param>
  508. /// <param name="target">Target state to animate towards.</param>
  509. public void Start(CameraState start, CameraState target)
  510. {
  511. this.start = start;
  512. this.target = target;
  513. }
  514. /// <summary>
  515. /// Updates the animation by interpolating between the start and target states.
  516. /// </summary>
  517. /// <param name="t">Interpolation parameter in range [0, 1] that determines how much to interpolate between
  518. /// start and target states.</param>
  519. public void Update(float t)
  520. {
  521. interpolated = new CameraState();
  522. interpolated.Position = start.Position * (1.0f - t) + target.Position * t;
  523. interpolated.Rotation = Quaternion.Slerp(start.Rotation, target.Rotation, t);
  524. interpolated.OrthographicPct = start.OrthographicPct * (1.0f - t) + target.OrthographicPct * t;
  525. interpolated.FrustumWidth = start.FrustumWidth * (1.0f - t) + target.FrustumWidth * t;
  526. }
  527. };
  528. #endregion
  529. }
  530. /// <summary>
  531. /// Contains properties used for controlling scene camera movement.
  532. /// </summary>
  533. [SerializeObject]
  534. internal class SceneCameraMoveSettings
  535. {
  536. [Range(0.1f, 10.0f)]
  537. public float acceleration = 1.0f;
  538. [Range(1.0f, 10.0f)]
  539. public float fastModeMultiplier = 2.0f;
  540. [Range(0.1f, 10.0f)]
  541. public float panSpeed = 3.0f;
  542. [Range(0.1f, 3.0f)]
  543. public float scrollSpeed = 3.0f;
  544. [Range(0.1f, 10.0f)]
  545. public float rotationalSpeed = 3.0f;
  546. }
  547. /// <summary>
  548. /// Contains properties used for controlling scene camera view.
  549. /// </summary>
  550. [SerializeObject]
  551. internal class SceneCameraViewSettings
  552. {
  553. public ProjectionType projectionType = ProjectionType.Perspective;
  554. [Range(10.0f, 170.0f, false)]
  555. public Degree fieldOfView = new Degree(90.0f);
  556. [Range(0.001f, 10000.0f, false)]
  557. public float orthographicSize = 10.0f;
  558. [Range(0.0001f, 10, false)]
  559. public float nearClipPlane = 0.05f;
  560. [Range(1.0f, 100000.0f, false)]
  561. public float farClipPlane = 2500.0f;
  562. public Color backgroundColor = new Color(0.282f, 0.341f, 0.478f);
  563. }
  564. /** @} */
  565. }