
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

#include "general.h"
#include "globals.h"
#include "intui.h"
#include "timer.h"
#include "spl_math.h"
#include "spl_util.h"
#include "spl_gfx.h"
#include "rotate_p.h"
/************************************************************************/
/*                                                                      */
/* This file contains code to handle the ROTATE P. command.		*/
/*                                                                      */
/************************************************************************/

static Boolean_T	Rotate_P_Active;
static short		Old_Rot_X;
static short		Old_Rot_Y;
static Vector_T		Old_Rotation_Vector;
static Vector_T		Box_Min, Box_Max;

static 
void Rotate_P_Timeout()
/************************************************************************/
/*                                                                      */
/* Function called when timer expires: Draw splines in persp window.	*/
/*                                                                      */
/************************************************************************/
{
    Compute_Splines();

    Clear_All(What_P);
    Draw_All(What_P);

    Redraw_Mask = 0;

    Stop_Timer();

} /* Rotate_P_Timeout */

static 
void Rotate_P_Redraw(long What)
/************************************************************************/
/*                                                                      */
/* Function called to redraw screen while rotating persp window.	*/
/*                                                                      */
/************************************************************************/
{
    Compute_Rotation_Matrix(M_Rotation, Rotation_Vector);

    Clear_All(What_P);
    Draw_Box(Box_Min, Box_Max, NULL, DM_Plane, What_P);
    Draw_Origin(DM_Normal, What_P);

    Start_Timer(Delay_Draw_Seconds, Delay_Draw_Micros);
    Redraw_Mask |= What_P;

} /* Rotate_P_Redraw */

static
void Rotate_P_Select_Up(short X, short Y)
/************************************************************************/
/*                                                                      */
/* Function called when mouse button is released.			*/
/* X, Y are the actual coordinates in the active window.		*/
/*                                                                      */
/************************************************************************/
{
	/* If the timer hasn't expired, then call the timeout handler to*/
	/* compute and draw the splines.				*/

    if (!Check_Timer()) Rotate_P_Timeout();

    Set_Mode_Normal();

} /* Rotate_P_Select_Up */

static 
void Rotate_P_Select_Down(short X, short Y)
/************************************************************************/
/*                                                                      */
/* Function called when mouse button is pressed.			*/
/* X, Y are the actual coordinates in the active window.		*/
/*                                                                      */
/************************************************************************/
{

    if (X < 0) return;
    if (Get_Bounding_Box(Box_Min, Box_Max)) {

	/* If we couldn't create a bbox, then just make a box.	*/
	Vec3Scalar(Box_Min, =, -Grid_Size, -Grid_Size, -Grid_Size);
	Vec3Scalar(Box_Max, =,  Grid_Size,  Grid_Size,  Grid_Size);
    }
    Rotate_P_Active = TRUE;

    Old_Rot_X = X;
    Old_Rot_Y = Y;

    Old_Rotation_Vector[0] = Rotation_Vector[0];
    Old_Rotation_Vector[1] = Rotation_Vector[1];
    Old_Rotation_Vector[2] = Rotation_Vector[2];

    if (MQ_Size_Rotate_P > 0) {
	SetMouseQueue(Windows[Id_Active_Window].Window, MQ_Size_Rotate_P); 
	Redraw_Always = TRUE;
    } else Redraw_Always = FALSE;

} /* Rotate_P_Select_Down */

static 
void  Rotate_P_Move(short X, short Y)
/************************************************************************/
/*                                                                      */
/* Function called when mouse is moved to rotate persp. window.		*/
/* X, Y are the actual coordinates in the active window.		*/
/*                                                                      */
/************************************************************************/
{
    if (X < 0) return;

    if (!Rotate_P_Active) return;

    X = (X - Old_Rot_X) / 2;
    Y = (Y - Old_Rot_Y) / 2;

    X += Old_Rotation_Vector[2];
    Y += Old_Rotation_Vector[0];
    X %= 360;
    Y %= 360;
    Rotation_Vector[2] = X;
    Rotation_Vector[0] = Y;

    sprintf(Error_Msg, "Rotate P.(%3.0f,%3.0f,%3.0f)", 
		Rotation_Vector[0],
		Rotation_Vector[1],
		Rotation_Vector[2]);
    Display_Status(Error_Msg);

    if (Redraw_Always) Rotate_P_Redraw(What_P);
    else               Redraw_Mask = What_P;

} /* Rotate_P_Move */


Boolean_T Rotate_P_Handle_Event(struct IntuiMessage *Msg)
/************************************************************************/
/*                                                                      */
/* Event handler routine for the 'ROTATE P' mode.			*/
/* Events handled:							*/
/*	Select down: Start rotating.					*/
/*	Select up  : Stop rotating.					*/
/*	Mouse move : Rotate persp.					*/
/*                                                                      */
/************************************************************************/
{

    switch (Msg->Class) {


    case IDCMP_MOUSEBUTTONS:
		/* Msg->Code contain id of button pressed 		*/
		/* Msg->MouseX and Msg->MouseY contain mouse position 			*/

	switch (Msg->Code) {

	case SELECTDOWN:
	    Rotate_P_Select_Down(Msg->MouseX, Msg->MouseY);
	    return(TRUE);

	case SELECTUP:
	    Rotate_P_Select_Up(Msg->MouseX, Msg->MouseY);
	    return(TRUE);

	} /* switch (Msg->Code) */
	break;

    case IDCMP_MOUSEMOVE:
	Rotate_P_Move(Msg->MouseX, Msg->MouseY);
	return(TRUE);

    } /* switch (Msg->Class) */

    return(FALSE);

} /* Rotate_P_Handle_Event */

void Set_Mode_Rotate_P()
/************************************************************************/
/*                                                                      */
/* Change to ROTATE P mode.						*/
/*                                                                      */
/************************************************************************/
{
    Rotate_P_Active		= FALSE;
    State.Handle_Event		= Rotate_P_Handle_Event;
    State.Timeout		= Rotate_P_Timeout;
    State.Redraw		= Rotate_P_Redraw;

    Display_Status("Rotate P.");

} /* Set_Mode_Rotate_P */
