|
|
/******************************Module*Header*******************************\
* Module Name: logon.cxx * * Copyright (c) 1997 Microsoft Corporation * \**************************************************************************/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <sys/types.h>
#include <stdlib.h>
#include <time.h>
#include "uidemo.hxx"
#include "logon.hxx"
#include "logobj.hxx"
//#define TEST_BITMAP 1
//#define UIDEMO_SWITCH_RES 1
MTKWIN *mtkWin; // the main window
ISIZE winSize; // main window cached size and position
IPOINT2D winPos; BOOL bSwapHintsEnabled; // global swap hints
BOOL bSwapHints; // local use
HCURSOR hNormalCursor, hHotCursor; HINSTANCE hLogonInstance; BOOL bDebugMode; BOOL bRunAgain; #if 0
BOOL bFlyWithContext = TRUE; #else
BOOL bFlyWithContext = FALSE; #endif
// Stuff for the banner
HDC hdcMem; HBITMAP hBanner; ISIZE bannerSize = { 0, 0 };
RGBA bgColor = {0.16f, 0.234f, 0.32f, 0.0f}; // ok
int nLogObj; LOG_OBJECT **pLogObj;
static LOG_OBJECT *pHotObj; // currently hot object
BOOL bLighting, bDepth; VIEW view; static BOOL bResSwitch;
// Timing stuff
AVG_UPDATE_TIMER frameRateTimer( 1.0f, 4 ); TIMER transitionTimer;
// Forwards
static void CleanUp(); static void GLFinish();
/**************************************************************************\
* \**************************************************************************/
float Clamp(int iters_left, float t) {
if (iters_left < 3) { return 0.0f; } return (float) (iters_left-2)*t/iters_left; }
void ClearWindow() { int clearMask = GL_COLOR_BUFFER_BIT; if( bDepth ) clearMask |= GL_DEPTH_BUFFER_BIT;
if( !bSwapHints ) { glClear( clearMask ); return; }
GLIRECT rect, *pRect; pRect = ▭
for( int i = 0; i < nLogObj; i++ ) { pLogObj[i]->GetRect( pRect ); glScissor( pRect->x, pRect->y, pRect->width, pRect->height ); glClear( clearMask ); AddSwapHintRect( pRect ); } // restore full scissor (mf : ? or just disable,since this only place used ?
glScissor( 0, 0, winSize.width, winSize.height ); }
void ClearAll() { static GLIRECT rect = {0}; int clearMask = GL_COLOR_BUFFER_BIT; if( bDepth ) clearMask |= GL_DEPTH_BUFFER_BIT;
glScissor( 0, 0, winSize.width, winSize.height ); glClear( clearMask ); if( bSwapHints ) { rect.width = winSize.width; rect.height = winSize.height; AddSwapHintRect( &rect ); } }
void ClearRect( GLIRECT *pRect, BOOL bResetScissor ) { int clearMask = GL_COLOR_BUFFER_BIT; if( bDepth ) clearMask |= GL_DEPTH_BUFFER_BIT;
glScissor( pRect->x, pRect->y, pRect->width, pRect->height ); glClear( clearMask );
if( bResetScissor ) glScissor( 0, 0, winSize.width, winSize.height ); }
void DrawObjects( BOOL bCalcUpdateRect ) { // Draws objects in their current positions
for( int i = 0; i < nLogObj; i++ ) { pLogObj[i]->Draw( bCalcUpdateRect ); } }
void Flush() { // glFlush, SwapBuffers (if doubleBuf)
mtkWin->Flush(); }
float MyRand(void) { return 10.0f * ( ((float) rand())/((float) RAND_MAX) - 0.5f); }
static void SetDepthMode() { if( bDepth ) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); }
static void SetTextureMode() { int mode; if( bLighting ) mode = GL_MODULATE; else mode = GL_DECAL;
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode ); }
static void SetLightingMode() { if( bLighting ) glEnable( GL_LIGHTING ); else glDisable( GL_LIGHTING ); SetTextureMode(); }
void CalcObjectWindowRects() { for( int i = 0; i < nLogObj; i++ ) { pLogObj[i]->CalcWinRect(); } }
//mf: VIEW class member
static void SetView( ISIZE *pWinSize ) { glViewport(0, 0, pWinSize->width, pWinSize->height);
view.fViewDist = 10.0f; // viewing distance
view.fovy = 45.0f; // field of view in y direction (degrees)
view.fAspect = (float) pWinSize->width / (float) pWinSize->height;
// We'll assume width >= height
glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(view.fovy, view.fAspect, 0.1, 100.0); // glOrtho( -5.0, 5.0, -5.0, 5.0, 0.0, 100.0 ); no look as good
glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0,0,view.fViewDist, 0,0,0, 0,1,0); // from, to, up...
}
void Reshape(int width, int height) { // Need to update main window info
ISIZE *pSize = &winSize;
pSize->width = width; pSize->height = height;
if( !width || !height ) return;
SetView( pSize );
UpdateLocalTransforms( UPDATE_ALL ); CalcObjectWindowRects();
// mf: this is kind of a hack, need a different mechanism, since get repaints
// from resizes and window expose (an argument for msg loops even in mtk
// programs. Of course, there's also tkDisplayFunc, which is called on PAINT,
// as opposed to IdleFunc...
ClearAll(); }
BOOL EscKey(int key, GLenum mask) { if( bDebugMode && (key == TK_ESCAPE) ) Quit(); return FALSE; }
BOOL Key(int key, GLenum mask) { if( !bDebugMode ) return FALSE;
switch (key) { case TK_ESCAPE: Quit(); break; default: return AttributeKey( key, mask ); } return TRUE; }
BOOL AttributeKey(int key, GLenum mask) { switch (key) { case TK_c : bFlyWithContext = !bFlyWithContext; break; case TK_d : bDepth = !bDepth; SetDepthMode(); break; case TK_l : bLighting = !bLighting; // This affects texturing mode
SetLightingMode(); break; case TK_s : if( mtk_bAddSwapHintRect() ) bSwapHintsEnabled = !bSwapHintsEnabled; break; default: return FALSE; } return TRUE; }
static void LoadCursors() { hNormalCursor = LoadCursor( NULL, IDC_ARROW ); hHotCursor = LoadCursor( hLogonInstance, MAKEINTRESOURCE( IDC_HOT_CURSOR ) ); }
/******************** MAIN LOGON SEQUENCE *********************************\
* \**************************************************************************/
static MTKWIN *CreateLogonWindow() { MTKWIN *win;
// Set window size and position
bResSwitch = FALSE;
UINT winConfig = 0; // Have to intially create window without cursor, so can change it later
winConfig |= MTK_NOCURSOR;
if( bDebugMode ) { winPos.x = 10; winPos.y = 30; #if 0
winSize.width = 400; winSize.height = 300; #else
winSize.width = 800; winSize.height = 600; #endif
} else { #if UIDEMO_SWITCH_RES
if( mtk_ChangeDisplaySettings( 800, 600, NULL ) ) { bResSwitch = TRUE; } #endif
winConfig |= MTK_FULLSCREEN | MTK_NOBORDER; winPos.x = 0; winPos.y = 0; winSize.width = GetSystemMetrics( SM_CXSCREEN ); winSize.height = GetSystemMetrics( SM_CYSCREEN ); #if 0
// debugging full screen ...
winSize.width /= 4; winSize.height /= 4; #endif
}
win = new MTKWIN(); if( !win ) return NULL;
// Configure and create the window (mf: this 2 step process of constructor
// and create will allow creating 'NULL' windows
#ifdef TEST_BITMAP
UINT glConfig = MTK_RGB | MTK_DOUBLE | MTK_BITMAP | MTK_DEPTH16; #else
UINT glConfig = MTK_RGB | MTK_DOUBLE | MTK_DEPTH16; #endif
if( !bDebugMode ) glConfig |= MTK_NOBORDER;
// Create the window
if( ! win->Create( "Demo", &winSize, &winPos, winConfig, NULL ) ) { delete win; return NULL; }
// Configure the window for OpenGL, setting ReshapeFunc to catch the
// resize (can't set it before in this case, since we do various gl
// calculations in the Reshape func.
win->SetReshapeFunc(Reshape); win->SetFinishFunc(GLFinish); if( ! win->Config( glConfig ) ) { delete win; return NULL; }
return win; }
static void InitGL(void) { #if 0
static float lmodel_ambient[] = {0.0f, 0.0f, 0.0f, 0.0f}; #else
static float lmodel_ambient[] = {0.2f, 0.2f, 0.2f, 0.0f}; #endif
//mf: change to one sided lighting if object is closed
static float lmodel_twoside[] = {(float)GL_TRUE}; static float lmodel_local[] = {(float)GL_FALSE}; static float light0_ambient[] = {0.1f, 0.1f, 0.1f, 1.0f}; static float light0_diffuse[] = {1.0f, 1.0f, 1.0f, 0.0f}; #if 1
// static float light0_position[] = {-1.0f, 1.0f, 1.0f, 0.0f};
static float light0_position[] = {-1.0f, 0.8f, 4.0f, 0.0f}; #else
static float light0_position[] = {-1.0f, 1.0f, 1.0f, 0.0f}; #endif
static float light0_specular[] = {1.0f, 1.0f, 1.0f, 0.0f};
static float bevel_mat_ambient[] = {0.0f, 0.0f, 0.0f, 1.0f}; static float bevel_mat_shininess[] = {40.0f}; static float bevel_mat_specular[] = {1.0f, 1.0f, 1.0f, 0.0f}; static float bevel_mat_diffuse[] = {1.0f, 1.0f, 1.0f, 0.0f};
// Set GL attributes
// glEnable(GL_CULL_FACE);
glEnable( GL_SCISSOR_TEST ); glCullFace(GL_BACK); glClearDepth(1.0f);
glClearColor( bgColor.r, bgColor.g, bgColor.b, bgColor.a ); glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular); glLightfv(GL_LIGHT0, GL_POSITION, light0_position); glEnable(GL_LIGHT0);
glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local); glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT, GL_AMBIENT, bevel_mat_ambient); glMaterialfv(GL_FRONT, GL_SHININESS, bevel_mat_shininess); glMaterialfv(GL_FRONT, GL_SPECULAR, bevel_mat_specular); glMaterialfv(GL_FRONT, GL_DIFFUSE, bevel_mat_diffuse);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glEnable( GL_TEXTURE_2D );
// Setup viewing parameters
SetView( &winSize );
// Rendering attributes
bDepth = FALSE; SetDepthMode();
bLighting = FALSE; SetLightingMode();
#if 0
glShadeModel(GL_SMOOTH); #else
glShadeModel(GL_FLAT); #endif
#ifdef TEST_BITMAP
bSwapHintsEnabled = FALSE; #else
bSwapHintsEnabled = mtk_bAddSwapHintRect(); #endif
// Update local copies of transforms, so we can calc 2D update rects
//mf: ? protect with bSwapHints ?
UpdateLocalTransforms( UPDATE_ALL ); }
static HBITMAP LoadBanner() { hdcMem = CreateCompatibleDC( NULL ); HBITMAP hBanner = LoadBitmap( hLogonInstance, MAKEINTRESOURCE( IDB_BANNER ) ); BITMAPINFO bmi = {0}; bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
if( ! GetDIBits( hdcMem, hBanner, 0, 0, NULL, &bmi, DIB_RGB_COLORS ) ) { SS_WARNING( "Couldn't get banner bitmap dimensions\n" ); } else { bannerSize.width = bmi.bmiHeader.biWidth; bannerSize.height = bmi.bmiHeader.biHeight; } if( !SelectObject( hdcMem, hBanner ) ) { SS_ERROR( "Couldn't select banner into DC\n" ); return 0; } return hBanner;
//mf: make hdcMem global, so it and hBanner can be deleted
}
BOOL LoadUserTextures( TEX_RES *pUserTexRes ) { SetWindowText( mtkWin->GetHWND(), "Loading textures..." );
for (int i = 0; i < nLogObj; i++) { pLogObj[i]->SetTexture( new TEXTURE( &pUserTexRes[i], hLogonInstance ) ); //mf: also validate the textures...
}
glFinish(); SetWindowText( mtkWin->GetHWND(), "" );
return TRUE; }
/******************** RunLogonSequence ************************************\
* \**************************************************************************/
BOOL RunLogonSequence( ENV *pEnv ) { BOOL bRet; LOG_OBJECT *pSelectedLogObj;
// Create table of ptrs to LOGOBJ's, which are wrappers around the list of
// users. The list of users and their bitmaps, etc, should eventually be
// a parameter to this function.
bDebugMode = pEnv->bDebugMode; nLogObj = pEnv->nUsers; hLogonInstance = pEnv->hInstance;
pLogObj = (LOG_OBJECT **) malloc( nLogObj * sizeof(LOG_OBJECT *) );
for( int i = 0; i < nLogObj; i ++ ) { pLogObj[i] = new LOG_OBJECT(); }
// Create a window to run the logon sequence in
mtkWin = CreateLogonWindow();
if( !mtkWin ) return FALSE;
// Do any GL init for the window
InitGL(); LoadBanner(); LoadUserTextures( pEnv->pUserTexRes );
SetCursor( NULL ); LoadCursors();
mtkWin->SetReshapeFunc( Reshape );
if( bDebugMode ) { // The sequences can repeat ad infinitum
//mf: pretty crazy logic
while( 1 ) { if( !RunLogonInitSequence() ) // fatal
break; run_hot_sequence: bRunAgain = FALSE; pSelectedLogObj = RunLogonHotSequence(); if( bRunAgain ) { continue; } if( pSelectedLogObj == NULL ) // fatal, no obect selected or window was closed
break; if( ! RunLogonEndSequence( pSelectedLogObj ) ) // fatal
break; if( bRunAgain ) { goto run_hot_sequence; } break; } } else { // Normal operation...
//mf: ? check for fatal errors ? or if !debugMode, call Quit whenever
// Exec returns false
RunLogonInitSequence(); // Run 'hot' sequence, where user selects object
if( !(pSelectedLogObj = RunLogonHotSequence()) ) { // No user selected, fatal
CleanUp(); return FALSE; }
// Set the selected user index
for( i = 0; i < nLogObj; i ++ ) { if( pSelectedLogObj == pLogObj[i] ) pEnv->iSelectedUser = i; }
// Run final sequence
RunLogonEndSequence( pSelectedLogObj ); }
// Do various clean-up
CleanUp(); return TRUE; }
void CleanUp() { if( mtkWin ) mtkWin->Close(); // this will call destructor for mtkWin
if( bResSwitch ) mtk_RestoreDisplaySettings(); }
// This function is the FinishFunc callback, and should not be called directly
static void GLFinish() { // Delete textures
//mf: may want to keep the selected one... , depending on what the caller wants
// returned. Maybe could keep the image data around, and then create a new
// TEXTURE ctor that uses this data...
for( int i = 0; i < nLogObj; i++ ) { if( pLogObj[i]->pTex ) { delete pLogObj[i]->pTex; pLogObj[i]->pTex = NULL; } } }
//mf: this can be called during debug mode, to terminate prematurely
void Quit() { CleanUp(); mtkQuit(); }
|