text: /*
  * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
  * its licensors.
  *
  * For complete copyright and license terms please see the LICENSE at the root of this
  * distribution (the "License"). All use of this software is governed by the License,
  * or, if provided, by the license below or the license accompanying this file. Do not
  * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *
  */
  #pragma once
  #include <AzCore/Component/ComponentBus.h>
  #include <AzCore/EBus/EBus.h>
  
  namespace Camera
  {
      /** 
       * Use this bus to send messages to a camera component on an entity
       * If you create your own camera you should implement this bus
       * Call like this:
       * Camera::CameraRequestBus::Event(cameraEntityId, &Camera::CameraRequestBus::Events::SetFov, newFov);
      */
      class CameraComponentRequests
          : public AZ::ComponentBus
      {
      public:
          virtual ~CameraComponentRequests() = default;
          /**
          * Gets the camera's field of view in degrees
          * @return The camera's field of view in degrees
          */
          virtual float GetFov() = 0;
          
          /**
          * Gets the camera's distance from the near clip plane in meters
          * @return The camera's distance from the near clip plane in meters
          */
          virtual float GetNearClipDistance() = 0;
  
          /**
          * Gets the camera's distance from the far clip plane in meters
          * @return The camera's distance from the far clip plane in meters
          */
          virtual float GetFarClipDistance() = 0;
  
          /**
          * Gets the camera frustum's width
          * @return The camera frustum's width
          */
          virtual float GetFrustumWidth() = 0;
  
          /**
          * Gets the camera frustum's height
          * @return The camera frustum's height
          */
          virtual float GetFrustumHeight() = 0;
  
          /**
          * Sets the camera's field of view in degrees between 0 < fov < 180 degrees
          * @param fov The camera frustum's new field of view in degrees
          */
          virtual void SetFov(float fov) = 0;
  
          /**
          * Sets the near clip plane to a given distance from the camera in meters.  Should be small, but greater than 0
          * @param nearClipDistance The camera frustum's new near clip plane distance from camera
          */
          virtual void SetNearClipDistance(float nearClipDistance) = 0;
  
          /**
          * Sets the far clip plane to a given distance from the camera in meters.
          * @param farClipDistance The camera frustum's new far clip plane distance from camera
          */
          virtual void SetFarClipDistance(float farClipDistance) = 0;
  
          /**
          * Sets the camera frustum's width
          * @param width The camera frustum's new width
          */
          virtual void SetFrustumWidth(float width) = 0;
  
          /**
          * Sets the camera frustum's height
          * @param height The camera frustum's new height
          */
          virtual void SetFrustumHeight(float height) = 0;
  
          /**
          * Makes the camera the active view
          */
          virtual void MakeActiveView() = 0;
      };
      using CameraRequestBus = AZ::EBus<CameraComponentRequests>;
  
      /**
      * Use this broadcast bus to gather a list of all active cameras
      * If you create your own camera you should handle this bus
      * Call like this:
      * 
      * AZ::EBusAggregateResults<AZ::EntityId> results;
      * Camera::CameraBus::BroadcastResult(results, &Camera::CameraRequests::GetCameras);
      */
      class CameraRequests
          : public AZ::EBusTraits
      {
      public:
          virtual ~CameraRequests() = default;
  
          /// Get a list of all cameras
          virtual AZ::EntityId GetCameras() = 0;
      };
      using CameraBus = AZ::EBus<CameraRequests>;
  
      /**
      * Handle this bus if you want to know when cameras are added or removed during edit or run time
      * You will get an OnCameraAdded event for each camera that is already active
      * If you create your own camera you should call this bus on activation/deactivation
      * Connect to the bus like this
      * Camera::CameraNotificationBus::Handler::Connect()
      */
      class CameraNotifications
          : public AZ::EBusTraits
      {
      public:
          template<class Bus>
          struct CameraNotificationConnectionPolicy
              : public AZ::EBusConnectionPolicy<Bus>
          {
              static void Connect(typename Bus::BusPtr& busPtr, typename Bus::Context& context, typename Bus::HandlerNode& handler, const typename Bus::BusIdType& id = 0)
              {
                  AZ::EBusConnectionPolicy<Bus>::Connect(busPtr, context, handler, id);
  
                  AZ::EBusAggregateResults<AZ::EntityId> results;
                  CameraBus::BroadcastResult(results, &CameraRequests::GetCameras);
                  for (const AZ::EntityId& cameraId : results.values)
                  {
                      handler->OnCameraAdded(cameraId);
                  }
              }
          };
          /**
          * If the camera is active when a handler connects to the bus,
          * then OnCameraAdded() is immediately dispatched.
          */
          template<class Bus>
          using ConnectionPolicy = CameraNotificationConnectionPolicy<Bus>;
  
          virtual ~CameraNotifications() = default;
  
          /**
          * Called whenever a camera entity is added
          * @param cameraId The id of the camera added
          */
          virtual void OnCameraAdded(const AZ::EntityId& cameraId) = 0;
  
          /**
          * Called whenever a camera entity is removed
          * @param cameraId The id of the camera removed
          */
          virtual void OnCameraRemoved(const AZ::EntityId& cameraId) = 0;
      };
      using CameraNotificationBus = AZ::EBus<CameraNotifications>;
  
  #define CameraComponentTypeId "{E409F5C0-9919-4CA5-9488-1FE8A041768E}"
  #define EditorCameraComponentTypeId "{B99EFE3D-3F1D-4630-8A7B-31C70CC1F53C}"
  
  } // namespace Camera
  