//===========================================================================//
// File:	camship.hh                                                          //
// Project: Munga			                                                     //
// Contents: Camera Interface 												           //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 08/08/95  JM  Initial coding.                                             //
// Classes: CameraShip					  													  //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc.                     //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//
#if !defined(CAMSHIP_HPP)
#	define CAMSHIP_HPP

#	if !defined (MOVER_HPP)
#		include <mover.hpp>
#	endif

#	if !defined (CAMMGR_HPP)
#		include <cammgr.hpp>
#	endif

	class CameraControlsMapper;

	//##########################################################################
	//###############       CameraShip::DirectionMessage       #################
	//##########################################################################

	class CameraShip__DirectionMessage :
		public Mover::Message
	{
	public:
		EntityID
			goalEntity;
		Scalar
			timeOnCamera;
		Point3D
			focusOffset;

		CameraShip__DirectionMessage(
			Receiver::MessageID message_ID,
			size_t length,
			const EntityID& goal_entity,
			Scalar time_on_camera,
			const Point3D& focus
		):
			Entity::Message(message_ID, length),
			goalEntity(goal_entity),
			timeOnCamera(time_on_camera),
			focusOffset(focus)
				{}
	};

	//##########################################################################
	//############################# CameraShip  ################################
	//##########################################################################

	class CameraShip :
		public Mover
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Shared Data support
	//
	public:
		static Derivation ClassDerivations;
		static SharedData DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Messaging support
	//
	protected:

		static const HandlerEntry
			MessageHandlerEntries[];
		static MessageHandlerSet
			MessageHandlers;

	public:
		enum{
			DirectionMessageID = Entity::NextMessageID,
			NextMessageID
		};

		typedef CameraShip__DirectionMessage DirectionMessage;

		void
			DirectionMessageHandler(DirectionMessage *message);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Attribute Support
	//
	public:
		enum
		{
			MapRangeAttributeID = Mover::NextAttributeID,
			MapLinearPositionAttributeID,
			MapAngularPositionAttributeID,
			NextAttributeID
		};

	private:
		static const IndexEntry AttributePointers[];

	protected:
		static AttributeIndexSet	AttributeIndex;

	public:
		Scalar
			mapRange;
		Point3D
			*mapLinearPosition;	// pointer to linear position of object or NULL
		Quaternion
			*mapAngularPosition;	// pointer to angular position of object or NULL

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Model support
	//
	public:
		enum {
			ControlsMapperSubsystem,
			BasicSubsystemCount
		};
		void
			SetMappingSubsystem(CameraControlsMapper *mapper);

		//
		// Various States of the CameraShip
		//
		enum {
			ConfigureCamerasState = Mover::StateCount,
			StateCount
		};

		typedef void
			(CameraShip::*Performance)(Scalar time_slice);

		void
			SetPerformance(Performance performance)
				{
					Check(this);
					activePerformance = (Simulation::Performance)performance;
				}

		void
			FollowGoal(Scalar time_slice);

		void
			DriveCamera(Scalar time_slice);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Flag Support
	//
	public:

		enum{
			DefaultFlags  = 	Mover::DefaultFlags |
									NoCollisionVolumeFlag |
									NoCollisionTestFlag |
									InitialStasisFlag
		};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction and Destruction
	//
	public:

		static CameraShip*
			Make(MakeMessage *creation_message);

		CameraShip(
			MakeMessage *creation_message,
			SharedData &virtual_data = DefaultData
		);
		~CameraShip();

		Logical
			TestInstance() const;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Public Data and Member Access Functions
	//
	public:

		void
			SetGoalEntity(Entity *goal_entity)
				{Check(this); Check(goal_entity); goalEntity = goal_entity;}

		Entity*
			GetGoalEntity()
				{Check(this); return goalEntity; }

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Local Member Data
	//
	public:
		void
			GoToClosestCamera(const Point3D &point_3D);
		CameraInstance*
			GetCurrentCamera()
				{Check(this); return currentCamera;}

		Time
			lastSwitch;
		Scalar
      	timeOnCamera;

	protected:
		CameraInstanceManager
			cameraManager;
		Entity
			*goalEntity;
		CameraInstance
			*currentCamera;
		Point3D
			focusOffset;

		void
			MoveCameraShip(CameraInstance *camera_instance);

		void
			AimCameraAtPoint(const Point3D &point_3D);

		void
			RotateCameraToPoint(
				Scalar time_slice,
				const Point3D &point_3D
			);

		//
		// Camera Motion Support
		//
	public:
		void
			ResetMotionVariables()
				{
					Check(this);
					localVelocity = Motion::Identity;
					localAcceleration = Motion::Identity;
					worldLinearVelocity = Vector3D::Identity;
					worldLinearAcceleration = Vector3D::Identity;
				}

	protected:
		void
			ApplyControlledPanAndTilt(
				CameraControlsMapper *controls,
				Scalar	time_slice
			);
		void
			ApplyControlledCameraHeight(CameraControlsMapper *controls);

		void
			ApplyControlledCameraMotion(
				CameraControlsMapper *controls,
				Scalar time_slice
			);

		//
		// Camera Manager Support
		//
	public:
		void
			CreateCameraInstance();

		void
			DeleteCameraInstance();

		void
			IncrementCameraInstance();

		void
			DecrementCameraInstance();

	public:
		void
			OutputCameraList()
				{cameraManager.WriteNotationFile();}
	};

#endif

