#include <AfxWin.h>
#include <AfxExt.h>
#define INITGUID
#include <ddraw.h>
#include <d3d.h>
#include <d3drm.h>
#include <d3drmwin.h>
#include <math.h>
#include "MorphPlayWin.h"
#include "resource.h"

#pragma comment (lib,"ddraw.lib")
#pragma comment (lib,"d3drm.lib")


BEGIN_MESSAGE_MAP(MorphPlayWin, MorphWin)
	//{{AFX_MSG_MAP(MorphPlayWin)
	ON_COMMAND(ID_RENDER_WIREFRAME, OnRenderWireframe)
	ON_COMMAND(ID_RENDER_FLAT, OnRenderFlat)
	ON_COMMAND(ID_RENDER_GOURAUD, OnRenderGouraud)
	ON_UPDATE_COMMAND_UI(ID_RENDER_FLAT, OnUpdateRenderFlat)
	ON_UPDATE_COMMAND_UI(ID_RENDER_GOURAUD, OnUpdateRenderGouraud)
	ON_UPDATE_COMMAND_UI(ID_RENDER_WIREFRAME, OnUpdateRenderWireframe)
	ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


D3DVALUE MorphPlayWin::morphtime=0;

BOOL MorphPlayWin::drag=FALSE;
BOOL MorphPlayWin::end_drag=TRUE;
int MorphPlayWin::last_x=0, MorphPlayWin::last_y=0;


MorphPlayWin::MorphPlayWin()
{
//	meshbuilder=0;
    morphtime=0;

    drag=FALSE;
    end_drag=TRUE;
    last_x=last_y=0;
}

BOOL MorphPlayWin::CreateScene()
{
    // --------DIRECTIONAL LIGHT ÍÀÏÐÀÂËÅÍÍÛÉ ÑÂÅÒ --------
    LPDIRECT3DRMLIGHT dlight;
    d3drm->CreateLightRGB( D3DRMLIGHT_DIRECTIONAL,
            D3DVALUE(1.00), D3DVALUE(1.00), D3DVALUE(1.00),
            &dlight);

    LPDIRECT3DRMLIGHT alight;
    d3drm->CreateLightRGB( D3DRMLIGHT_AMBIENT,
            D3DVALUE(0.40), D3DVALUE(0.40), D3DVALUE(0.40),
            &alight);

    LPDIRECT3DRMFRAME lightframe;
    d3drm->CreateFrame( scene, &lightframe );
    lightframe->AddLight( dlight );
    lightframe->AddLight( alight );
    lightframe->SetOrientation( scene,
            D3DVALUE(0), D3DVALUE(-1), D3DVALUE(1),
            D3DVALUE(0), D3DVALUE(1), D3DVALUE(0));
    alight->Release();
    alight=0;
    dlight->Release();
    dlight=0;
    lightframe->Release();
    lightframe=0;

    //------ CAMERA ÊÀÌÅÐÀ ----------
    d3drm->CreateFrame( scene, &camera );
    camera->SetPosition( scene, D3DVALUE(0), D3DVALUE(0), D3DVALUE(-50));
    d3drm->CreateViewport( device, camera, 0, 0,
            device->GetWidth(), device->GetHeight(),
            &viewport);

    return TRUE;
}

void MorphPlayWin::OnFileOpen()
{
    static char BASED_CODE filter[] =
            "Morph Files (*.mrf)|*.mrf|X Files (*.x)|*.x||";
    CFileDialog opendialog( TRUE, 0, 0, OFN_FILEMUSTEXIST,
            filter, this );
    if ( opendialog.DoModal() == IDOK )
    {
        CString filename = opendialog.GetPathName();
        CWaitCursor cur;
        InitMorphSequence( filename );
    }
}


BOOL MorphPlayWin::InitMorphSequence( const CString& filename )
{
    if (frame)
        frame->DeleteVisual( mesh );
    else
    {
        d3drm->CreateFrame( scene, &frame );
        frame->AddMoveCallback( UpdateDrag, NULL );
        frame->AddMoveCallback( UpdateMorph, this );
    }

    if (LoadMorphSequence( filename )==FALSE)
        return FALSE;

    DWORD targets=GetNumMorphTargets();
    for (DWORD i=0;i<targets;i++)
        AddMorphKey( i, D3DVALUE(i) );
    maxmorphtime=D3DVALUE(targets-1);
    morphtime=D3DVALUE(0.0);
    mesh=GetMorphMesh();
    mesh->SetGroupColorRGB( 0,
            D3DVALUE(.67), D3DVALUE(.82), D3DVALUE(.94) );
    frame->AddVisual( mesh );

    return TRUE;
}


void MorphPlayWin::UpdateMorph(LPDIRECT3DRMFRAME, void* ptr, D3DVALUE)
{
    MorphPlayWin* win=(MorphPlayWin*)ptr;
    const D3DVALUE maxtime=win->maxmorphtime;
    const int morphspeed=win->morphspeed;
    const D3DVALUE morphtimeinc=win->morphtimeinc;

    if (morphspeed==MORPH_FORWARD)
    {
        morphtime+=morphtimeinc;
        if (morphtime>maxtime)
            morphtime=D3DVALUE(0);
    }
    else if (morphspeed==MORPH_REVERSE)
    {
        morphtime-=morphtimeinc;
        if (morphtime<D3DVALUE(0))
            morphtime=maxtime;
    }
    else if (morphspeed==MORPH_BOTH)
    {
        static BOOL forward=TRUE;
        if (forward)
            morphtime+=morphtimeinc;
        else
            morphtime-=morphtimeinc;
        if (morphtime<D3DVALUE(0) || morphtime>maxtime)
            forward=1-forward;
    }

    win->SetMorphTime( morphtime );
}

void MorphPlayWin::OnLButtonDown(UINT nFlags, CPoint point)
{
    if (!drag)
    {
        drag=TRUE;
        last_x = GetMouseX();
        last_y = GetMouseY();
        ShowCursor( FALSE );
        SetCapture();
    }
    MorphWin::OnLButtonDown(nFlags, point);
}

void MorphPlayWin::OnLButtonUp(UINT nFlags, CPoint point)
{
    if (drag)
    {
        end_drag=TRUE;
        ReleaseCapture();
        ShowCursor( TRUE );
    }
    MorphWin::OnLButtonUp(nFlags, point);
}

void MorphPlayWin::UpdateDrag(LPDIRECT3DRMFRAME frame, void*, D3DVALUE)
{
    if (drag)
    {
        double delta_x, delta_y;
        int x=GetMouseX();
        int y=GetMouseY();
        delta_x = x - last_x;
        delta_y = y - last_y;
        last_x = x;
        last_y = y;

        double delta_r = sqrt(delta_x * delta_x + delta_y * delta_y);
        double radius = 50;
        double denom;

        denom = sqrt(radius * radius + delta_r * delta_r);

        if (!(delta_r == 0 || denom == 0))
            frame->SetRotation( 0,
              D3DDivide(D3DVAL((float)-delta_y), D3DVAL((float)delta_r)),
              D3DDivide(D3DVAL((float)-delta_x), D3DVAL((float)delta_r)),
              D3DVAL(0.0),
              D3DDivide(D3DVAL((float)delta_r), D3DVAL((float)denom)));
    }

    if (end_drag)
    {
        drag=FALSE;
        end_drag=FALSE;
    }
}

void MorphPlayWin::OnIdle(LONG)
{
    if (drag && frame)
        frame->SetRotation( 0,
                D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0) );
}


void MorphPlayWin::OnRenderWireframe() 
{
//	if (meshbuilder)
//		meshbuilder->SetQuality( D3DRMRENDER_WIREFRAME );
}

void MorphPlayWin::OnRenderFlat() 
{
//	if (meshbuilder)
//		meshbuilder->SetQuality( D3DRMRENDER_FLAT );
}

void MorphPlayWin::OnRenderGouraud() 
{
//	if (meshbuilder)
//		meshbuilder->SetQuality( D3DRMRENDER_GOURAUD );
}

void MorphPlayWin::OnUpdateRenderWireframe(CCmdUI* pCmdUI) 
{
//	if (meshbuilder)
//	{
//		D3DRMRENDERQUALITY meshquality = meshbuilder->GetQuality();
//		pCmdUI->SetCheck( meshquality==D3DRMRENDER_WIREFRAME );
//	}
}

void MorphPlayWin::OnUpdateRenderFlat(CCmdUI* pCmdUI) 
{
//	if (meshbuilder)
//	{
//		D3DRMRENDERQUALITY meshquality = meshbuilder->GetQuality();
//		pCmdUI->SetCheck( meshquality==D3DRMRENDER_FLAT );
//	}
}

void MorphPlayWin::OnUpdateRenderGouraud(CCmdUI* pCmdUI) 
{
//	if (meshbuilder)
//	{
//		D3DRMRENDERQUALITY meshquality = meshbuilder->GetQuality();
//		pCmdUI->SetCheck( meshquality==D3DRMRENDER_GOURAUD );
//	}
}




/*void MorphPlayWin::OnFileOpen() 
{
	// TODO: Add your command handler code here
	
}

void MorphPlayWin::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	
	RMWin::OnLButtonDown(nFlags, point);
}

void MorphPlayWin::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	
	RMWin::OnLButtonUp(nFlags, point);
}
*/