/******************************Module*Header*******************************\ * Module Name: loghot.cxx * * Copyright (c) 1997 Microsoft Corporation * \**************************************************************************/ #include #include #include #include #include #include #include "logon.hxx" #include "resource.h" static LOG_OBJECT *pHotObj; static void DrawBanner(); static BOOL bFrameObjects; // whether to frame the objects or not static float colorHot[3] = { 0.0f, 1.0f, 0.0f }; static float colorWhite[3] = { 1.0f, 1.0f, 1.0f }; #define HOT_CURSOR 1 /******************** HOT SEQUENCE ****************************************\ * \**************************************************************************/ static LOG_OBJECT* CheckForHit( int mouseX, int mouseY ) { // Check mouse coords against rect of each object. Return ptr to object // if within. mouseY = InvertY( mouseY, winSize.height ); LOG_OBJECT *pObj; GLIRECT rect, *pRect; pRect = ▭ for( int i = 0; i < nLogObj; i++ ) { pObj = pLogObj[i]; pObj->GetRect( pRect ); if( ( mouseX >= pRect->x ) && ( mouseX < (pRect->x + pRect->width) ) && ( mouseY >= pRect->y ) && ( mouseY < (pRect->y + pRect->height) ) ) { // SS_DBGPRINT( "CheckForHit() recording a hit\n" ); return pObj; } } return NULL; } static void DrawObject( LOG_OBJECT *pObj, BOOL bHot ) { if( !pObj ) return; // Set ColorMaterial color, in case lighting is on for the frame if( bHot ) { glColor3fv( colorHot ); } else { glColor3fv( colorWhite ); } pObj->Draw(); } // This redraws everything static void DrawHotSequence(void) { ClearWindow(); LOG_OBJECT *pObj; for( int i = 0; i < nLogObj; i++ ) { pObj = pLogObj[i]; DrawObject( pObj, (pObj == pHotObj) ); } Flush(); DrawBanner(); } static void FinishLogonHotSequence() { #ifndef HOT_CURSOR // User has selected an object. // Turn off hilite on current selection and return DrawObject( pHotObj, FALSE ); Flush(); #endif mtkWin->Return(); } static BOOL HotKey(int key, GLenum mask) { switch (key) { case TK_RETURN: if( pHotObj ) FinishLogonHotSequence(); break; case TK_ESCAPE: if( bDebugMode ) Quit(); break; case TK_SPACE: if( bDebugMode ) { bRunAgain = TRUE; FinishLogonHotSequence(); } break; default: if( bDebugMode ) return AttributeKey( key, mask ); return FALSE; } return FALSE; } static BOOL MouseButton(int mouseX, int mouseY, GLenum button) { // If left button click on an object, run end of logon sequence if( !(button & TK_LEFTBUTTON) ) return GL_FALSE; LOG_OBJECT *pObj; if( pObj = CheckForHit( mouseX, mouseY ) ) { pHotObj = pObj; FinishLogonHotSequence(); } return FALSE; } static BOOL MouseMove(int mouseX, int mouseY, GLenum button) { // Handle a mouse move. Redraw only when necessary LOG_OBJECT *pObj; LOG_OBJECT *pLastHotObj = pHotObj; if( pObj = CheckForHit( mouseX, mouseY ) ) { if( pObj == pHotObj ) { // State has not changed return FALSE; } // New hot object pHotObj = pObj; SetCursor( hHotCursor ); } else { SetCursor( hNormalCursor ); if( !pHotObj ) { // State has not changed return FALSE; } // No hot object pHotObj = NULL; } #ifndef HOT_CURSOR if( ! bSwapHints ) // Need to do complete redraw return TRUE; // Redraw only the objects that changed if( pLastHotObj ) { // remove hot indicator from old hot object DrawObject( pLastHotObj, FALSE ); } if( pHotObj ) { // add hot indicator to new hot object DrawObject( pHotObj, TRUE ); } // Flush the changes Flush(); #endif return FALSE; } static void DrawBanner() { BitBlt( mtkWin->GetHdc(), 0, 0, bannerSize.width, bannerSize.height, hdcMem, 0, 0, SRCCOPY ); GdiFlush(); } LOG_OBJECT * RunLogonHotSequence() { if( bDebugMode ) bRunAgain = FALSE; // Stop animation, make quads 'hot' SS_DBGPRINT( "RunLogonHotSequence()\n" ); // If the objects were flown in without context their origins would have // been in centre of the image part. Since we want to add context now, // have to offset the destination values. This is done inside next loop // Calc window rects of the quads bSwapHints = bSwapHintsEnabled; UpdateLocalTransforms( UPDATE_ALL ); bFrameObjects = FALSE; // no framing currently LOG_OBJECT *pObj; for( int i = 0; i < nLogObj; i++ ) { pObj = pLogObj[i]; pObj->ShowContext( TRUE ); if( !bFlyWithContext ) { // offset x dest value to the left (again, size assumption) pObj->OffsetDest( - OBJECT_WIDTH / 4.0f, 0.0f, 0.0f ); } if( bFrameObjects ) pObj->ShowFrame( TRUE ); pObj->CalcWinRect(); } pHotObj = NULL; // Set any gl attributes if( bFrameObjects ) { glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); bDepth = TRUE; } // Go to slower but nicer texture drawing while in this mode for( i = 0; i < nLogObj; i++ ) { pLogObj[i]->pTex->MakeCurrent(); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); } // Set up mtk functions for this sequence mtkWin->SetAnimateFunc( NULL ); mtkWin->SetKeyDownFunc(HotKey); mtkWin->SetMouseMoveFunc( MouseMove ); mtkWin->SetMouseDownFunc( MouseButton ); mtkWin->SetDisplayFunc( DrawHotSequence ); // Now get the current pointer position and simulate a mouse move with it, // in case it's over one of the objects. IPOINT2D ptMouse; mtkWin->GetMouseLoc( &ptMouse.x, &ptMouse.y ); // Need to check that mouse is inside window if( (ptMouse.x >= 0) && (ptMouse.x < winSize.width) && (ptMouse.y >= 0) && (ptMouse.y < winSize.height) ) { MouseMove( ptMouse.x, ptMouse.y, 0 ); } // Draw everything (so nicer textures show up) DrawHotSequence(); if( !mtkWin->Exec() ) return NULL; // Restore gl attributes for( i = 0; i < nLogObj; i++ ) { pLogObj[i]->pTex->MakeCurrent(); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); } glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); bDepth = FALSE; // Turn frames off for the objects for( i = 0; i < nLogObj; i++ ) { pLogObj[i]->ShowFrame( FALSE ); } // Dump the cursor SetCursor( NULL ); return pHotObj; }