// [DEMOCAM] -- PLX

#include "cg_local.h"
#include "cg_democams.h"

#define MAXCAM 128

#define DC_NONE			0
#define DC_FREECAM		1
#define DC_CAMEDIT		2
#define DC_TRANSPLAY	3
#define DC_SEQEDIT		4
#define DC_SEQPLAY		5


int	DC_Mod = DC_NONE;


// CAMS
typedef struct {
	vec3_t		Origin;
	vec3_t		Angles;
	vec3_t		Velocity;
	vec3_t		AngleVelocity;
	qboolean	used; // True when camera is created.
} democam_t;
democam_t	cams[MAXCAM];
int			camnum = 0;
int			camindex = 0;
democam_t	*currentcam = NULL;



// TRANSITIONS
typedef struct {
	int			start;
	int			end;
	int			time;
	int			type;
	int			exectime;
	qboolean	used; // True when transition is created.
	int			starttime;
} democamtrans_t;
democamtrans_t	trans[MAXCAM];
democamtrans_t	*currenttrans = NULL;
democam_t		transcam;
qboolean		playalltrans = qfalse;
int				transindex = 0;
qboolean		CamWasFree;



// SEQUENCES
typedef struct democam_rsFrame_s{
	vec3_t						Origin;
	vec3_t						Angles;
	struct democam_rsFrame_s	*next;
} democam_rsFrame_t;
typedef struct democam_recordedsequence_s{
	char								name[32];
	democam_rsFrame_t					*StartFrame;
	democam_rsFrame_t					*CurrentFrame;
	struct democam_recordedsequence_s	*next;
} democam_recordedsequence_t;
democam_recordedsequence_t	*sequences = NULL;
democam_recordedsequence_t	tmp_sequence;



democam_t freecam;



void DemoCam_SwitchMod ( int mod );
void DemoCam_NewCam ( void );				// cmd : addcam
void DemoCam_DelCam ( void );				// cmd : delcam
void DemoCam_NextCam ( void );				// cmd : nextcam
void DemoCam_PrevCam ( void );				// cmd : prevcam
void DemoCam_SwitchToCamByNumber ( void );	// cmd : switchto
void DemoCam_WriteCameraFile ( void );		// cmd : writecamerafile
void DemoCam_EndOfTransition ( void );



/*
==================
DemoCam_SwitchMod
==================
*/
void DemoCam_SwitchMod ( int mod ) {
	char txt[64];

	//if ( !cg.demoPlaying ) return; // Available only in demoplayer

	switch(mod) {
		case DC_CAMEDIT:
			// If there is no cam then create the first
			if (camnum == 0) DemoCam_NewCam();

			if (currentcam == NULL) currentcam = &cams[0];

			// Center viewangles user command to currentcam angles
			Q_snprintfz(txt, 64, "centerviewonvec %f %f %f\n", currentcam->Angles[0], currentcam->Angles[1], currentcam->Angles[2]);
			trap_Cmd_ExecuteText( EXEC_APPEND, txt );

			CamIsFree = qtrue;
			trap_Cvar_SetValue( "cg_thirdPerson", 1 ); // Needed to draw followed player model
			Com_Printf("Switched to CamEdit mod.\n");
			break;

		case DC_TRANSPLAY:
			CamIsFree = qtrue;
			trap_Cvar_SetValue( "cg_thirdPerson", 1 ); // Needed to draw followed player model
			Com_Printf("Switched to TransPlay mod.\n");
			break;

		case DC_FREECAM:
			CamIsFree = qtrue;
			trap_Cvar_SetValue( "cg_thirdPerson", 1 ); // Needed to draw followed player model
			Com_Printf("Switched to FreeCam mod.\n");
			break;

		case DC_SEQEDIT:
			CamIsFree = qtrue;
			trap_Cvar_SetValue( "cg_thirdPerson", 1 ); // Needed to draw followed player model
			Com_Printf("Switched to SeqEdit mod.\n");
			break;

		case DC_SEQPLAY:
			CamIsFree = qtrue;
			trap_Cvar_SetValue( "cg_thirdPerson", 1 ); // Needed to draw followed player model
			Com_Printf("Switched to SeqPlay mod.\n");
			break;

		case DC_NONE:
			CamIsFree = qfalse;
			trap_Cvar_SetValue( "cg_thirdPerson", 0 );
			Com_Printf("Switched to normal mod.\n");
			break;

		default:
			CamIsFree = qfalse;
			trap_Cvar_SetValue( "cg_thirdPerson", 0 );
			Com_Printf("Switched to normal mod.\n");
			break;
	}

	DC_Mod = mod;


}

void DemoCam_NextMod ( void ) {
	Com_Printf("Current mod : %d.\n", DC_Mod);
	switch (DC_Mod) {
		case DC_NONE:
			DemoCam_SwitchMod(DC_FREECAM);
			break;
		case DC_FREECAM:
			DemoCam_SwitchMod(DC_CAMEDIT);
			break;
		case DC_CAMEDIT:
			DemoCam_SwitchMod(DC_SEQEDIT);
			break;
		case DC_TRANSPLAY:
			//DemoCam_SwitchMod(DC_FREECAM);
			break;
		case DC_SEQEDIT:
			DemoCam_SwitchMod(DC_NONE);
			break;
		case DC_SEQPLAY:
			//DemoCam_SwitchMod(DC_FREECAM);
			break;
		default:
			break;
	}
}

/* #########################################################################################
                                      C A M E R A S
######################################################################################### */

/*
==================
DemoCam_CreateCam
Add a new cam at current position in defined slot
==================
*/
void DemoCam_CreateCam ( void ) {

	int		newcamindex;

	if (trap_Cmd_Argc() < 2) return;

	newcamindex = atoi(trap_Cmd_Argv(1));

	if (cams[newcamindex].used) { // Not a free slot
		Com_Printf("This camera slot is not free (%d)\n", newcamindex);
		return;
	}

	camnum++;

	// Set cam properties
	VectorCopy( cg.refdef.vieworg, cams[newcamindex].Origin );
	VectorCopy( cg.refdef.viewangles, cams[newcamindex].Angles);
	cams[newcamindex].used = qtrue;

	if (currentcam == NULL) currentcam = &cams[newcamindex]; // If it is the first cam, make it the current

	Com_Printf("Camera %d created\n", newcamindex);

}

/*
==================
DemoCam_SetCamOrigin
==================
*/
void DemoCam_SetCamOrigin ( void ) {
	int		camindex;

	if (trap_Cmd_Argc() < 5) return;

	camindex = atoi(trap_Cmd_Argv(1));

	if (!cams[camindex].used) { // Not a free slot
		Com_Printf("Camera %d does not exist\n", camindex);
		return;
	}
	
	cams[camindex].Origin[0] = atof(trap_Cmd_Argv(2));
	cams[camindex].Origin[1] = atof(trap_Cmd_Argv(3));
	cams[camindex].Origin[2] = atof(trap_Cmd_Argv(4));

}

/*
==================
DemoCam_SetCamAngles
==================
*/
void DemoCam_SetCamAngles ( void ) {
	int		camindex;

	if (trap_Cmd_Argc() < 5) return;

	camindex = atoi(trap_Cmd_Argv(1));

	if (!cams[camindex].used) { // Not a free slot
		Com_Printf("Camera %d does not exist\n", camindex);
		return;
	}
	
	cams[camindex].Angles[0] = atof(trap_Cmd_Argv(2));
	cams[camindex].Angles[1] = atof(trap_Cmd_Argv(3));
	cams[camindex].Angles[2] = atof(trap_Cmd_Argv(4));

}

/*
==================
DemoCam_NewCam
Add a new cam at current position
==================
*/
void DemoCam_NewCam ( void ) {

	int		i;
	int		newcamindex;

	// Find the first free slot
	for(i=0; i < MAXCAM; i++) {
		if (!cams[i].used) break;
	}

	if (i==MAXCAM) { // No free slot
		Com_Printf("Cameras max limit reached (%d)\n", MAXCAM);
		return;
	}

	// Add the cam
	newcamindex = i;
	camnum++;

	// Set cam properties
	VectorCopy( cg.refdef.vieworg, cams[newcamindex].Origin );
	VectorCopy( cg.refdef.viewangles, cams[newcamindex].Angles);
	cams[newcamindex].used = qtrue;

	if (currentcam == NULL) {
		currentcam = &cams[newcamindex]; // If it is the first cam, set it to current
		camindex = newcamindex;
	}

	Com_Printf("Camera %d added\n", newcamindex);

}

/*
==================
DemoCam_DelCam
Deletde current cam
==================
*/
void DemoCam_DelCam ( void ) {
	if (camnum > 0 && DC_Mod == DC_CAMEDIT) {
		currentcam->used = qfalse;
		camnum--;
		Com_Printf("Camera %d deleted\n", camindex);
		if (camnum == 0) {
			DemoCam_SwitchMod(DC_NONE);
			return;
		}
		DemoCam_NextCam();
	}
}

/*
==================
DemoCam_SwitchToCamByNumber
Switch to cam NUM
==================
*/
void DemoCam_SwitchToCamByNumber ( void ) {
	char txt[64];
	int num;

	if (trap_Cmd_Argc() < 2) return;

	num = atoi(trap_Cmd_Argv(1));

	if (!cams[num].used) {
		Com_Printf("Camera %d does not exist.\n", num);
		return;
	}

	// Switch to next cam
	camindex = num;
	currentcam = &cams[camindex];

	// Center viewangles user command to currentcam angles
	Q_snprintfz(txt, 64, "centerviewonvec %f %f %f\n", currentcam->Angles[0], currentcam->Angles[1], currentcam->Angles[2]);
	trap_Cmd_ExecuteText( EXEC_APPEND, txt );

	Com_Printf("Switched to camera %d\n", camindex);



}

/*
==================
DemoCam_NextCam
Switch to next cam
==================
*/
void DemoCam_NextCam ( void ) {

	int		i;
	char	txt[64];

	if (!camnum) {
		Com_Printf("There is no camera.\n");
		return;
	}

	if (!CamIsFree) {
		camindex = MAXCAM - 1;
	}

	// Find the next used slot
	i = camindex + 1;
	if (i == MAXCAM) i = 0;
	while(!cams[i].used) {
		i++;
		if (i == MAXCAM) i = 0;
	}

	// Switch to next cam
	camindex = i;
	currentcam = &cams[camindex];

	// Center viewangles user command to currentcam angles
	Q_snprintfz(txt, 64, "centerviewonvec %f %f %f\n", currentcam->Angles[0], currentcam->Angles[1], currentcam->Angles[2]);
	trap_Cmd_ExecuteText( EXEC_APPEND, txt );

	if (DC_Mod != DC_CAMEDIT) {
		DemoCam_SwitchMod(DC_CAMEDIT);
	}

	Com_Printf("Switched to camera %d\n", camindex);
}

/*
==================
DemoCam_PrevCam
Switch to prev cam
==================
*/
void DemoCam_PrevCam ( void ) {

	int		i;
	char	txt[64];

	if (!camnum) {
		Com_Printf("There is no camera.\n");
		return;
	}

	if (!CamIsFree) {
		camindex = 0;
	}

	// Find the prev used slot
	i = camindex - 1;
	if (i < 0) i = MAXCAM - 1;
	while(!cams[i].used) {
		i--;
		if (i < 0) i = MAXCAM - 1;
	}

	// Switch to next cam
	camindex = i;
	currentcam = &cams[camindex];

	// Center viewangles user command to currentcam angles
	Q_snprintfz(txt, 64, "centerviewonvec %f %f %f\n", currentcam->Angles[0], currentcam->Angles[1], currentcam->Angles[2]);
	trap_Cmd_ExecuteText( EXEC_APPEND, txt );

	if (DC_Mod != DC_CAMEDIT) {
		DemoCam_SwitchMod(DC_CAMEDIT);
	}

	Com_Printf("Switched to camera %d\n", camindex);
}

/* #########################################################################################
                                     T R A N S I T I O N S
######################################################################################### */

/*
==================
DemoCam_CreateTrasition
==================
*/
void DemoCam_CreateTransition ( void ) { // Console command
	int		index;
	vec3_t	vec;
	float	len;
	float	speed;

	if (trap_Cmd_Argc() < 6) return;

	index = atoi(trap_Cmd_Argv(1));

	trans[index].start = atoi(trap_Cmd_Argv(2));
	trans[index].end = atoi(trap_Cmd_Argv(3));
	trans[index].type = atoi(trap_Cmd_Argv(5));
	trans[index].time = atoi(trap_Cmd_Argv(4));

	switch (trans[index].type) {
		case 1 :
			if (trans[index].time < 0) { // Speed defined and not time defined
				VectorSubtract(cams[trans[index].end].Origin, cams[trans[index].start].Origin, vec);
				len = VectorNormalize(vec); // Len
				speed = -(float)trans[index].time;
				trans[index].time = (int)((len * 1000) / speed);
				Com_Printf("len : %f, time : %d, speed : %f\n", len, trans[index].time, speed);
			}
			break;
		default:
			break;
	}


	trans[index].used = qtrue;
	trans[index].starttime = 0;
}

/*
==================
DemoCam_StartTrans
==================
*/
void DemoCam_StartTrans ( int index ) {
	int		i;
	vec3_t	dir;
	float	len;
	float	speed;


	Com_Printf("Starting trans %d\n",index);

	currenttrans = &trans[index];
	transindex = index;

	currenttrans->starttime = cg.realTime;
	VectorCopy(cams[currenttrans->start].Angles, transcam.Angles);
	VectorCopy(cams[currenttrans->start].Origin, transcam.Origin);


	switch (currenttrans->type) {
		case 1 : // Init standart stransition

			// Origin
			VectorSubtract(cams[currenttrans->end].Origin, cams[currenttrans->start].Origin, dir); // Find direction
			len = VectorNormalize(dir); // Len
			speed = (len * 1000) / currenttrans->time; // Speed
			for(i=0;i<3;i++) transcam.Velocity[i] = dir[i]*speed; // Velocity
			Com_Printf("len : %f, time : %d, speed : %f\n", len, currenttrans->time, speed);

			// Angle
			for(i=0;i<3;i++) {
				transcam.AngleVelocity[i] = cams[currenttrans->end].Angles[i] - cams[currenttrans->start].Angles[i];
				if (transcam.AngleVelocity[i] > 180) transcam.AngleVelocity[i] -= 360;
				if (transcam.AngleVelocity[i] < -180) transcam.AngleVelocity[i] += 360;
			}
			for(i=0;i<3;i++) transcam.AngleVelocity[i] = (transcam.AngleVelocity[i] * 1000) / currenttrans->time;

			break;
		default:
			break;
	}

	if (DC_Mod != DC_TRANSPLAY) DemoCam_SwitchMod(DC_TRANSPLAY);
}

/*
==================
DemoCam_EndOfTransition
==================
*/
void DemoCam_EndOfTransition ( void ) {
	int i;

	// Return to normal mod
	currenttrans->starttime = 0;
	currenttrans = NULL;
	DemoCam_SwitchMod(DC_NONE);

	if (playalltrans) {
		// Find the next transition
		for (i = transindex + 1 ; i < MAXCAM ; i++) {
			if (trans[i].used) break;
		}

		if (i >= MAXCAM) { // There is no more transition
			playalltrans = qfalse;

		} else { // Start the transition
			DemoCam_StartTrans(i);
		}
	}

}

/*
==================
DemoCam_StartTransition
==================
*/
void DemoCam_StartTransition ( void ) { // Console command (play transition number X)

	if (currenttrans != NULL) {
		Com_Printf("A transition is already playing.\n");
	}

	if (trap_Cmd_Argc() < 2) return;
	DemoCam_StartTrans(atoi(trap_Cmd_Argv(1)));
}

/*
==================
DemoCam_StartTransitions
==================
*/
void DemoCam_StartTransitions ( void ) { // Console command (play all transitions)
	int i;

	if (currenttrans != NULL) {
		Com_Printf("A transition is already playing.\n");
	}

	// Find the first transition
	for (i = 0 ; i < MAXCAM ; i++) {
		if (trans[i].used) break;
	}

	if (i >= MAXCAM) { // There is no transition
		Com_Printf("There is no transition to play.\n");
		return;
	}

	// We will play all transition
	playalltrans = qtrue;

	DemoCam_StartTrans(i);

}

/* #########################################################################################
                                      S E Q U E N C E S
######################################################################################### */

/*
==================
DemoCam_rsNewFrame
Add rsFrame to the temp. sequence
==================
*/
void DemoCam_rsNewFrame ( vec3_t Origin, vec3_t Angles ) {
	democam_rsFrame_t	*newframe;
	democam_rsFrame_t	*current;

	// Create and init the new frame
	newframe = CG_Malloc(sizeof(democam_rsFrame_t));
	newframe->next = NULL;
	VectorCopy(Origin, newframe->Origin);
	VectorCopy(Angles, newframe->Angles);

	// Add it to the end of tmp_sequence
	if (tmp_sequence.StartFrame != NULL) {
		current = tmp_sequence.StartFrame;
		while (current->next != NULL) current = current->next;
		current->next = newframe;
	} else {
		tmp_sequence.StartFrame = newframe;
	}
}

/*
==================
DemoCam_rsCmdNewFrame
Add rsFrame to the temp. sequence
==================
*/
void DemoCam_rsCmdNewFrame ( void ) {
	vec3_t Origin;
	vec3_t Angles;

	if (trap_Cmd_Argc() < 7) return;

	Origin[0] = atof(trap_Cmd_Argv(1));
	Origin[1] = atof(trap_Cmd_Argv(2));
	Origin[2] = atof(trap_Cmd_Argv(3));
	Angles[0] = atof(trap_Cmd_Argv(4));
	Angles[1] = atof(trap_Cmd_Argv(5));
	Angles[2] = atof(trap_Cmd_Argv(6));

	DemoCam_rsNewFrame(Origin, Angles);

}

/*
==================
DemoCam_rsFreeFrames
==================
*/
void DemoCam_rsFreeFrames ( democam_rsFrame_t *startframe ) {
	if (startframe->next != NULL) DemoCam_rsFreeFrames(startframe->next);
	CG_Free(startframe);
}

/*
==================
DemoCam_rsValidateSequence
Validate a sequence
==================
*/
void DemoCam_rsValidateSequence ( void ) {
	democam_recordedsequence_t	*current = NULL; // silence compiler warning
	democam_recordedsequence_t	*sequence = NULL;

	if (trap_Cmd_Argc() < 2) return;

	// Search for a sequence with the same name
	if (sequences != NULL) {
		current = sequences;
		do {
			if (!strcmp(current->name, trap_Cmd_Argv(1))) {
				sequence = current;
				break;
			}
			current = current->next;
		} while (current != NULL);
	}

	if (sequence == NULL) { // If there is not

		// Create sequence
		sequence = CG_Malloc(sizeof(democam_recordedsequence_t));
		sequence->next = NULL;
		Q_strncpyz(sequence->name, trap_Cmd_Argv(1), 32);

		// Insert it to sequence list
		if (sequences != NULL) {
			current->next = sequence;
		} else {
			sequences = sequence;
		}

	}

	// If the sequence is not free, free it !
	if (sequence->StartFrame != NULL) {
		DemoCam_rsFreeFrames(sequence->StartFrame);
		sequence->StartFrame = NULL;
	}

	// Paste tempory sequence in our named one
	sequence->StartFrame = tmp_sequence.StartFrame;
	sequence->CurrentFrame = sequence->StartFrame;

	// Free the temp sequence
	tmp_sequence.StartFrame = NULL;
	tmp_sequence.CurrentFrame = NULL;

}

/*
==================
DemoCam_rsDelSequence
Delete a named sequence
==================
*/
void DemoCam_rsDelSequence ( void ) {
	democam_recordedsequence_t	*current;
	democam_recordedsequence_t	*tmp;
	democam_recordedsequence_t	*prev = NULL;

	if (trap_Cmd_Argc() < 2) return;

	// Search for a sequence with the same name
	if (sequences != NULL) {
		current = sequences;
		do {
			if (!strcmp(current->name, trap_Cmd_Argv(1))) { // We found it. we delete it
				// Delete frames
				if (current->StartFrame != NULL) DemoCam_rsFreeFrames(current->StartFrame);

				// Don't break the list
				if (prev != NULL) {
					prev->next = current->next;
				} else {
					sequences = current->next;
				}

				tmp = current;
				current = current->next;

				CG_Free(tmp);
				Com_Printf("%s deleted.\n", trap_Cmd_Argv(1));
			} else {
				prev = current;
				current = current->next;
			}
		} while (current != NULL);
	}
}









/* #########################################################################################
                                   C O N F I G    F I L E S
######################################################################################### */

/*
============
DemoCam_Printf -- Copy of FS_Printf() whitch has no trap_ function
============
*//*
int DemoCam_Printf( int file, const char *fmt, ... )
{
	char		msg[1024];
	size_t		len;
	va_list		argptr;

	va_start ( argptr, fmt );
	if( (len = vsprintf (msg, fmt, argptr)) > sizeof(msg) )
		Sys_Error ( "DemoCam_Printf: Buffer overflow" );
	va_end ( argptr );

	return trap_FS_Write( msg, len, file );
}*/

/*
==================
DemoCam_WriteCameraFile
Write a file which contain cameras defs
==================
*/
void DemoCam_WriteCameraFile ( void ) {

	int i;
	int file;

	char	name[MAX_QPATH];

	if( trap_Cmd_Argc() != 2 ) {
		Com_Printf( "usage: writecamerafile <filename>\n" );
		return;
	}

	Q_strncpyz( name, trap_Cmd_Argv(1), sizeof(name) );
	COM_DefaultExtension( name, ".camcfg", sizeof(name) );

	Com_Printf( "Writing %s\n", name );

	if( trap_FS_FOpenFile( name, &file, FS_WRITE ) == -1 ) {
		Com_Printf( "Couldn't write %s.\n", name );
		return;
	}

	trap_FS_Printf( file, "// Cameras defs file (generated by warsow)\n" );

	// Cameras defs
	for(i=0; i < MAXCAM; i++) {
		if (!cams[i].used) continue;
		trap_FS_Printf( file, "createcam %d\n", i );
		trap_FS_Printf( file, "setcamorigin %d %f %f %f\n", i , cams[i].Origin[0], cams[i].Origin[1], cams[i].Origin[2] );
		trap_FS_Printf( file, "setcamangles %d %f %f %f\n", i , cams[i].Angles[0], cams[i].Angles[1], cams[i].Angles[2] );
	}

	trap_FS_Printf( file, "\n// CamTrans defs\n" );

	// Transition defs
	for(i=0; i < MAXCAM; i++) {
		if (!trans[i].used) continue;
		trap_FS_Printf( file, "createtransition %d %d %d %d %d\n", i , trans[i].start, trans[i].end, trans[i].time, trans[i].type);
	}

	trap_FS_FCloseFile( file );

}


void DemoCam_TestFunction ( void ) {
	Com_Printf("%d - %d - %f\n", cg.realTime, cg.time, cg.frameTime);
	Com_Printf("%s\n", trap_Cmd_Argv(1));
}


void CG_RegisterDemoCamCommands( void ) {

	// Standart console commands
	trap_Cmd_AddCommand("democam", DemoCam_NextMod);					// democam
	trap_Cmd_AddCommand("addcam", DemoCam_NewCam);						// addcam
	trap_Cmd_AddCommand("delcam", DemoCam_DelCam);						// delcam
	trap_Cmd_AddCommand("nextcam", DemoCam_NextCam);					// nextcam
	trap_Cmd_AddCommand("prevcam", DemoCam_PrevCam);					// prevcam
	trap_Cmd_AddCommand("switchto", DemoCam_SwitchToCamByNumber);		// switchto CamNum
	trap_Cmd_AddCommand("writecamerafile", DemoCam_WriteCameraFile);	// writecamerafile FileName

	// CameraFile commands
	trap_Cmd_AddCommand("createcam", DemoCam_CreateCam);				// createcam CamNum
	trap_Cmd_AddCommand("setcamorigin", DemoCam_SetCamOrigin);			// setcamorigin CamNum o1 o2 o3
	trap_Cmd_AddCommand("setcamangles", DemoCam_SetCamAngles);			// setcamangles CamNum a1 a2 a3

	// Transitions
	trap_Cmd_AddCommand("createtransition", DemoCam_CreateTransition);	// createtransition TransNum Cam1 Cam2 Speed/Time Type
	trap_Cmd_AddCommand("starttransition", DemoCam_StartTransition);	// starttransition TransNum
	trap_Cmd_AddCommand("starttransitions", DemoCam_StartTransitions);	// starttransitions

	// Sequences
	trap_Cmd_AddCommand("rsNewFrame", DemoCam_rsCmdNewFrame);			// rsNewFrame o1 o2 o3 a1 a2 a3
	trap_Cmd_AddCommand("rsValidate", DemoCam_rsValidateSequence);		// rsValidate SeqName

	// removable
	trap_Cmd_AddCommand("testcmd", DemoCam_TestFunction);
}

void CG_UnregisterDemoCamCommands( void ) {

	// Standart console commands
	trap_Cmd_RemoveCommand("democam");
	trap_Cmd_RemoveCommand("addcam");
	trap_Cmd_RemoveCommand("delcam");
	trap_Cmd_RemoveCommand("nextcam");
	trap_Cmd_RemoveCommand("prevcam");
	trap_Cmd_RemoveCommand("switchto");
	trap_Cmd_RemoveCommand("writecamerafile");

	// CameraFile commands
	trap_Cmd_RemoveCommand("createcam");
	trap_Cmd_RemoveCommand("setcamorigin");
	trap_Cmd_RemoveCommand("setcamangles");

	// Transitions
	trap_Cmd_RemoveCommand("createtransition");
	trap_Cmd_RemoveCommand("starttransition");
	trap_Cmd_RemoveCommand("starttransitions");

	// Sequences
	trap_Cmd_RemoveCommand("rsNewFrame");
	trap_Cmd_RemoveCommand("rsValidate");

	// removable
	trap_Cmd_RemoveCommand("testcmd");

}

/* #########################################################################################
                                      D E M O C A M
######################################################################################### */

/*
==================
DemoCam
==================
*/
void DemoCam ( void ) {
	int			i;
	usercmd_t	cmd;

	vec3_t		forward;
	vec3_t		right;
	vec3_t		up;
	vec3_t		velocity;

	if ( !cg.demoPlaying ) return; // Available only in demoplayer

	switch (DC_Mod) {
		case DC_NONE:
			return;
			//break;
		case DC_FREECAM:
			break;
		case DC_CAMEDIT:
			if (CamIsFree) {

				trap_NET_GetUserCmd( trap_NET_GetCurrentUserCmdNum() - 1, &cmd );

				// Set cam angles
				currentcam->Angles[0] = SHORT2ANGLE( cmd.angles[0] );
				currentcam->Angles[1] = SHORT2ANGLE( cmd.angles[1] );
				currentcam->Angles[2] = SHORT2ANGLE( cmd.angles[2] );

				// Move the cam
				AngleVectors (currentcam->Angles, forward, right, up);
				VectorNormalize( forward );
				VectorNormalize( right );
				for( i = 0; i < 3; i++ ) velocity[i] = forward[i]*cmd.forwardmove + right[i]*cmd.sidemove;
				velocity[2] += cmd.upmove;
				VectorMA (currentcam->Origin, cg.frameTime, velocity, currentcam->Origin);

				// Apply cam to renderer POV
				VectorCopy(currentcam->Angles, cg.refdef.viewangles);
				VectorCopy( currentcam->Origin, cg.refdef.vieworg );

			}
			break;
		case DC_TRANSPLAY:
			// Check for end of transition
			if ((currenttrans != NULL) && (cg.realTime > currenttrans->starttime+currenttrans->time)) {
				Com_Printf("realTime(%d) > starttime(%d) + time(%d)\n", cg.realTime, currenttrans->starttime, currenttrans->time);
				DemoCam_EndOfTransition();
			}

			if (currenttrans != NULL) {

				// Move transcam
				switch (currenttrans->type) {
					case 0 : // Switch without transition
						break;
					case 1 : // Standart transition
						// Origin
						VectorMA (transcam.Origin, cg.frameTime, transcam.Velocity, transcam.Origin);
						// Angles
						for(i=0;i<3;i++) transcam.Angles[i] += transcam.AngleVelocity[i] * cg.frameTime;
						break;
					default:
						break;
				}

				// Apply cam to renderer POV
				VectorCopy(transcam.Angles, cg.refdef.viewangles);
				VectorCopy( transcam.Origin, cg.refdef.vieworg );

			}
			break;
		case DC_SEQEDIT:
			break;
		case DC_SEQPLAY:
			break;
		default:
			break;
	}

	//Clear blend effect
	for( i = 0; i < 4; i++ ) cg.refdef.blend[i] = 0.0f;


}
