/******************************Module*Header*******************************\
* Module Name: dlgdraw.c
*
* For gl drawing in dialog boxes
*
* Created: 12-06-95 -by- Marc Fortier [marcfo]
*
* Copyright (c) 1995 Microsoft Corporation
\**************************************************************************/

#include <windows.h>
#include <commdlg.h>
#include <scrnsave.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "ssintrnl.hxx"
#include "dlgdraw.hxx"

// Define this if want each TEX_BUTTON to be a separate window.  This is
// necessary if the main dialog window has WS_CLIP_CHILDREN, but so far this
// doesn't seem to be the case.
//#define SS_MULTIWINDOW 1

static void CalcGLViewport( HWND hwndParent, HWND hwndChild, IPOINT2D *pOrigin, ISIZE *pSize );

//materials for varying intensities

enum{
    MAT_INTENSITY_LOW = 0,
    MAT_INTENSITY_MID,
    MAT_INTENSITY_HIGH,
    MAT_COUNT
};

MATERIAL gMat[MAT_COUNT] = {
    {{0.3f, 0.3f, 0.3f}, {0.6f, 0.6f, 0.6f}, {0.2f, 0.2f, 0.2f}, 0.3f },
    {{0.2f, 0.2f, 0.2f}, {0.8f, 0.8f, 0.8f}, {0.2f, 0.2f, 0.2f}, 0.3f },
    {{0.2f, 0.2f, 0.2f}, {1.0f, 1.0f, 1.0f}, {0.2f, 0.2f, 0.2f}, 0.3f }
};

float colorBlack[3] = {0.0f, 0.0f, 0.0f};

/**************************************************************************\
* SS_TEX_BUTTON constructor
*
* This allows drawing GL textures on a button
*
* For optimum performance, GL is configured on the main dialog window, and
* 'viewported' to the button.
* Defining SS_MULTIWINDOW results in the texture being drawn in the actual
* button window.
*
* Note: this only works for buttons on the main dialog window for now.
\**************************************************************************/

SS_TEX_BUTTON::SS_TEX_BUTTON( HWND hDlg, HWND hDlgBtn )
{
    PSSW psswParent = gpss->sswTable.PsswFromHwnd( hDlg );
    SS_ASSERT( psswParent, "SS_TEX_BUTTON constructor: NULL psswParent\n" );

    // The parent needs to have an hrc context, since we will be using it
    // for drawing.

    SS_GL_CONFIG GLc = { 0, 0, NULL };
    if( !psswParent->ConfigureForGL( &GLc ) ) {
        SS_WARNING( "SS_TEX_BUTTON constructor: ConfigureForGL failed\n" );
        return;
    }

#ifdef SS_MULTIWINDOW
    // Each button is a separate GL window, using its parents hrc
    pssw = new SSW( psswParent, hDlgBtn );

    SS_ASSERT( pssw, "SS_TEX_BUTTON constructor: pssw alloc failure\n" );

    // Configure the pssw for GL

    GLc.pfFlags = 0;
    GLc.hrc = psswParent->GetHRC();
    GLc.pStretch = NULL;

    if( ! pssw->ConfigureForGL( &GLc ) ) {
        SS_WARNING( "SS_TEX_BUTTON constructor: ConfigureForGL failed\n" );
        return;
    }
#else
    // Make the button a 'subwindow' of the parent
    pssw = NULL;

    // Calculate the viewport to draw to

    CalcGLViewport( hDlg, hDlgBtn, &origin, &size );
#endif

    // Init various GL stuff
    InitGL();

    pCurTex = NULL;
    bEnabled = TRUE;
}

/**************************************************************************\
* SS_TEX_BUTTON destructor
*
\**************************************************************************/

SS_TEX_BUTTON::~SS_TEX_BUTTON()
{
    if( pssw )
        delete pssw;
}

/**************************************************************************\
* InitGL
*
\**************************************************************************/

void
SS_TEX_BUTTON::InitGL()
{
    float ambient[] = {0.2f, 0.2f, 0.2f, 1.0f};
    float diffuse[] = {0.7f, 0.7f, 0.7f, 1.0f};
    float position[] = {0.0f, 0.0f, -150.0f, 1.0f};
    float lmodel_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f};
    MATERIAL *pMat;

    // lighting, for intensity levels

    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    glLightfv(GL_LIGHT0, GL_POSITION, position);
    glEnable(GL_LIGHT0);

    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);

    glCullFace( GL_BACK );
    glEnable(GL_CULL_FACE);
    glFrontFace( GL_CW );
    glShadeModel( GL_FLAT );

    glColor3f( 1.0f, 1.0f, 1.0f );
    gluOrtho2D( -1.0, 1.0, -1.0, 1.0 );

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}

/**************************************************************************\
* SetTexture
*
* Set a current texture for the button
*
* Note this is a pointer to a texture, so any texture memory management is
* done by the caller.
\**************************************************************************/

void
SS_TEX_BUTTON::SetTexture( TEXTURE *pTex )
{
    pCurTex = pTex;
}

/**************************************************************************\
* Draw
*
\**************************************************************************/

void
SS_TEX_BUTTON::Draw( TEXTURE *pTex )
{
    if( pTex != NULL ) {
        glEnable(GL_TEXTURE_2D);

        ss_SetTexture( pTex ); // doesn't look at iPalRot yet
        // Set the texture palette if it exists
        if( pTex->pal && pTex->iPalRot )
            ss_SetTexturePalette( pTex, pTex->iPalRot );
    }
    // else white rectangle will be drawn

    if( bEnabled )
        intensity = DLG_INTENSITY_HIGH;
    else
        intensity = DLG_INTENSITY_LOW;

    switch( intensity ) {
        case DLG_INTENSITY_LOW:
            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
            glEnable(GL_LIGHTING);
            glColor3f( 0.5f, 0.5f, 0.5f );
            break;
        case DLG_INTENSITY_MID:
            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
            glEnable(GL_LIGHTING);
            glColor3f( 0.7f, 0.7f, 0.7f );
            break;
        case DLG_INTENSITY_HIGH:
        default:
            glColor3f( 1.0f, 1.0f, 1.0f );
            glDisable(GL_LIGHTING);
            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    }

    // Set the viewport
#ifdef SS_MULTIWINDOW
    glViewport( 0, 0, pssw->size.width, pssw->size.height );
#else
    glViewport( origin.x, origin.y, size.width, size.height );
#endif

    glBegin( GL_QUADS );
        glTexCoord2f( 0.0f, 1.0f );
        glVertex2f( -1.0f, 1.0f );
        glTexCoord2f( 1.0f, 1.0f );
        glVertex2f(  1.0f,  1.0f );
        glTexCoord2f( 1.0f, 0.0f );
        glVertex2f(  1.0f, -1.0f );
        glTexCoord2f( 0.0f, 0.0f );
        glVertex2f(  -1.0f, -1.0f );
    glEnd();

    glDisable( GL_TEXTURE_2D);

    glFlush();
}

void
SS_TEX_BUTTON::Draw()
{
    Draw( pCurTex );
}

/**************************************************************************\
* CalcGLViewport
*
* Calculate viewport for the child window
*
\**************************************************************************/

static void 
CalcGLViewport( HWND hwndParent, HWND hwndChild, IPOINT2D *pOrigin, ISIZE *pSize )
{
    RECT childRect, parentRect;

    // Get size of the child window

    GetClientRect( hwndChild, &childRect );
    pSize->width = childRect.right;
    pSize->height = childRect.bottom;

    // Calc origin of the child window wrt its parents client area
    // Note that the y-coord must be inverted for GL

    // Map the child client rect to the parent client coords
    MapWindowPoints( hwndChild, hwndParent, (POINT *) &childRect, 2 );
    pOrigin->x = childRect.left;
    // invert y coord
    GetClientRect( hwndParent, &parentRect );
    pOrigin->y = parentRect.bottom - childRect.bottom;
}