///////////////////////////////////////////////////////////////////////////////
//
// File: AVP_CameraVolumeData.h
//
// Created by Martin G.Harris (14/9/2006)
// 
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//
// Class to contain project specific camera types and their associated data.
//
///////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __AVP_CAMERA_VOLUME_DATA_H__
#define __AVP_CAMERA_VOLUME_DATA_H__


#ifdef ASURA_USE_CAMERA_VOLUME

// Includes
#include "Core/Asura_Maths.h"
#include "Network/Asura_Guid.h"

//////////////////////////////
// AVP_CameraVolumeData //
//////////////////////////////
// Storage for the camera properties associated with the camera volume client entity.
// The chunk data is saved out as a version number, followed by the shared data and then
// data for the specific camera type.
class AVP_CameraVolumeData
{
public:
	AVP_CameraVolumeData();

	void Reset(); // Reset to some known default values.

	// Assignment
	// MGH 14/9/2006: The default assigment operator is OK at the moment.
	//AVP_CameraVolumeData& operator=(const AVP_CameraVolumeData& xOther);

	//
	// Chunk buffer functions
	//
	int	 GetChunkBufferSize() const;
	void FillInChunkBuffer(char*& pcChunkBuffer);
	void InitialiseFromChunkBuffer(const char*& pcChunkBuffer);

	// Fallback code for when the client entity is missing (ie chunk data version = 0).
	static void FillInChunkBuffer_V0(char*& pcChunkBuffer);
	static int GetChunkBufferSize_V0();

	// Allow server entities to skip the relevant number of bytes.
	static void SkipChunk(const char*& pcChunkBuffer);

	// Types
	// Do *not* renumber this list as the values are saved out to chunks.
	// If you add to this list then update ToolsAVP_Entity_CameraVolume too.
	enum CameraType
	{
		TYPE_FIXED_ANGLE,	// Fixed rotation, elevation and distance relative to target.
		TYPE_STATIC_CAM,	// Camera has fixed position.
		TYPE_RAIL_CAM,		// Camera moves along rail.

		NUM_CAMERA_TYPES
	};

	// Flags in m_uFlags
	enum FLAGS
	{
		FLAG_SHARED_OVERRIDE_TIME_TO_RESET	= 0x00000001,
		FLAG_SHARED_OVERRIDE_FOV			= 0x00000002,
		FLAG_SHARED_OVERRIDE_TARGET			= 0x00000004,
		FLAG_RAIL_CAM_USE_PLAYER_RAIL		= 0x00000008, // Use player rail in "rail cam"?
	};

	// General properties shared by all camera types.
	struct ChunkData_Shared
	{
		int   m_iType; // Camera type (CameraType).
		u_int m_uFlags;
		
		float m_fTimeToReset;
		float m_fFOV;
		Asura_Guid m_uTarget;

		enum { CURRENT_VERSION = 1 };
	};

	// Properties for "fixed angle" camera type.
	struct ChunkData_FixedAngle
	{
		float m_fRotation;
		float m_fElevation;
		float m_fDistance;

		enum { CURRENT_VERSION = 0 };
	};

	// Properties for "static cam".
	struct ChunkData_StaticCam
	{
		Asura_Vector_3 m_xPosition;

		enum { CURRENT_VERSION = 0 };
	};

	// Properties for "rail cam".
	struct ChunkData_RailCam
	{
		Asura_Vector_3 m_xCameraRailStart;
		Asura_Vector_3 m_xCameraRailEnd;

		Asura_Vector_3 m_xPlayerRailStart;
		Asura_Vector_3 m_xPlayerRailEnd;

		enum { CURRENT_VERSION = 0 };
	};

	// Accessors
	CameraType GetType() const { return static_cast<CameraType>(m_xShared.m_iType); }

	const ChunkData_Shared&		GetProperties_Shared()     const { return m_xShared; }
	const ChunkData_FixedAngle&	GetProperties_FixedAngle() const { return m_xFixedAngle; }
	const ChunkData_StaticCam&	GetProperties_StaticCam()  const { return m_xStaticCam; }
	const ChunkData_RailCam&	GetProperties_RailCam()    const { return m_xRailCam; }


	bool IsEnabledOverrideTimeToReset() const
	{
		return (m_xShared.m_uFlags & FLAG_SHARED_OVERRIDE_TIME_TO_RESET) != 0;
	}
	bool IsEnabledOverrideFOV() const
	{
		return (m_xShared.m_uFlags & FLAG_SHARED_OVERRIDE_FOV) != 0;
	}
	bool IsEnabledOverrideTarget() const
	{
		return (m_xShared.m_uFlags & FLAG_SHARED_OVERRIDE_TARGET) != 0;
	}
	bool IsEnabledUsePlayerRail() const
	{
		return (m_xShared.m_uFlags & FLAG_RAIL_CAM_USE_PLAYER_RAIL) != 0;
	}

#ifdef ASURA_TOOLS
	// Displace any positions by the specified offset.
	void Displace(const Asura_Vector_3& xMove);
#endif //ASURA_TOOLS


private:
	//
	// Member data
	//
	ChunkData_Shared m_xShared; // Shared properties

	// MGH 14/9/2006: I was going to use a union, but can't because Asura_Vector_3 has
	// copy constructors etc. Having all the data for all the camera types in the class is
	// actually quite convenient for tools and happens to be how EA's Dante camera worked too.
	// If this class gets too fat then we may need to rethink.
	ChunkData_FixedAngle m_xFixedAngle;
	ChunkData_StaticCam  m_xStaticCam;
	ChunkData_RailCam	 m_xRailCam;

	//
	// Static member data
	//
	static const size_t s_auChunkSize[NUM_CAMERA_TYPES]; // Sizes of the various chunks

	// Friends
	friend class ToolsAVP_Entity_CameraVolume;
};

#endif //ASURA_USE_CAMERA_VOLUME

#endif //__AVP_CAMERA_VOLUME_DATA_H__

